[英]C++ Declaring arrays in class and declaring 2d arrays in class
我是使用類的新手,但在將數組分配到類中時遇到了問題。 我想為限制為50個字符的文本初始化一個char數組,然后用一個函數替換文本。
#ifndef MAP_H
#define MAP_H
#include "Sprite.h"
#include <SFML/Graphics.hpp>
#include <iostream>
class Map : public sprite
{
private:
char mapname[50];
int columnnumber;
int linenumber;
char casestatematricia[];
public:
void setmapname(char newmapname[50]);
void battlespace(int column, int line);
void setcasevalue(int col, int line, char value);
void printcasematricia();
};
#endif
順便說一句,我可以像這樣初始化我的2d數組
char casestatematricia[][];
我想稍后使此2d數組動態化,在其中輸入像這樣的列號和行號
casestatematricia[linenumber][columnnumber]
創建戰場。
這是cpp代碼,以便您對我要做什么有所了解。
#include "Map.h"
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace sf;
void Map::setmapname(char newmapname[50])
{
this->mapname = newmapname;
}
void Map::battlespace(int column, int line)
{
}
void Map::setcasevalue(int col, int line, char value)
{
}
void Map::printcasematricia()
{
}
先感謝您。
考慮遵循這一常規做法。 大多數(例如數字)庫在類內部不使用2D數組。 他們使用動態分配的1D數組並重載()或[]運算符,以類似於2D的方式訪問正確的元素。 因此,從外面看,您永遠無法說出您實際上在處理連續存儲,它看起來像是2D陣列。 這樣,陣列更易於調整大小,存儲,轉置和整形更有效。
只是您的問題的命題:
class Map : public sprite
{
private:
std::string mapname;
int columnnumber;
int linenumber;
std::vector<char> casestatematricia;
static constexpr std::size_t maxRow = 50;
static constexpr std::size_t maxCol = 50;
public:
Map():
casestatematricia(maxRow * maxCol, 0)
{}
void setmapname(std::string newmapname)
{
if (newmapname.size() > 50)
{
// Manage error if you really need no more 50 characters..
// Or just troncate when you serialize!
}
mapname = newmapname;
}
void battlespace(int col, int row);
void setcasevalue(int col, int row, char value)
{
// check that col and line are between 0 and max{Row|Column} - 1
casestatematricia[row * maxRow + col] = value;
}
void printcasematricia()
{
for (std::size_t row = 0; row < maxRow; ++row)
{
for (std::size_t col = 0; col < maxCol; ++col)
{
char currentCell = casestatematricia[row * maxRow + col];
}
}
}
};
要訪問像2D數組這樣的1D數組,請查看C ++中將1D數組作為2D數組訪問 。
當您考慮序列化時,我想您想將其保存到文件中。 只是一個建議:不要將原始內存存儲到文件中只是為了在重新啟動軟件時“節省”時間。 您只有一個非便攜式解決方案! 認真地說,借助計算機的強大功能,您不必擔心從文件加載時間!
我建議您在類中添加2種方法,以將Map保存到文件中
void dump(std::ostream &os)
{
os << mapname << "\n";
std::size_t currentRow = 0;
for(auto c: casestatematricia)
{
os << static_cast<int>(c) << " ";
++currentRow;
if (currentRow >= maxRow)
{
currentRow = 0;
os << "\n";
}
}
}
void load(std::istream &is)
{
std::string line;
std::getline(is, line);
mapname = line;
std::size_t current_cell = 0;
while(std::getline(is, line))
{
std::istringstream is(line);
while(!is.eof())
{
char c;
is >> c;
casestatematricia[current_cell] = c;
++current_cell;
}
}
}
僅以舉例的方式給出該解決方案。 他們不處理錯誤,我選擇將其以ASCII格式存儲在文件中。 您可以更改為以二進制形式存儲,但是不要使用原始內存的直接寫入。 您可以看一下C-序列化技術 (只需要轉換為C ++)即可。 但是請不要使用memcpy
或類似技術進行序列化
我希望我做對了。 你有兩個問題。 您想知道如何分配char mapname[50];
的值char mapname[50];
通過void setmapname(char newmapname[50]);
。 您想知道如何創建動態尺寸的2D數組。
我希望您對指針感到滿意,因為在兩種情況下都需要它。
對於第一個問題,我想首先糾正您對void setmapname(char newmapname[50]);
理解void setmapname(char newmapname[50]);
。 C ++函數不接受數組。 它接受指向數組的指針。 因此,這與編寫void setmapname(char *newmapname);
一樣好void setmapname(char *newmapname);
。 為了更好地理解,請轉到將數組傳遞給C ++中的函數
這樣,我將更改功能以讀取新地圖名稱的長度。 並分配mapname
,只需使用循環來復制每個字符。
void setmapname(char *newmapname, int length) {
// ensure that the string passing in is not
// more that what mapname can hold.
length = length < 50 ? length : 50;
// loop each value and assign one by one.
for(int i = 0; i < length; ++i) {
mapname[i] = newmapname[i];
}
}
對於第二個問題,您可以使用矢量,如Garf365建議的那樣,但我希望僅使用指針,而我將使用1D數組表示2d戰場。 (您可以閱讀Garf365提供的鏈接)。
// Declare like this
char *casestatematricia; // remember to initialize this to 0.
// Create the battlefield
void Map::battlespace(int column, int line) {
columnnumber = column;
linenumber = line;
// Clear the previous battlefield.
clearspace();
// Creating the battlefield
casestatematricia = new char[column * line];
// initialise casestatematricia...
}
// Call this after you done using the battlefield
void Map::clearspace() {
if (!casestatematricia) return;
delete [] casestatematricia;
casestatematricia = 0;
}
只要記住在不再使用它時調用clearspace()
。
僅出於您的利益,這就是您創建動態尺寸2D數組的方式
// Declare like this
char **casestatematricia; // remember to initialize this to 0.
// Create the battlefield
void Map::battlespace(int column, int line) {
columnnumber = column;
linenumber = line;
// Clear the previous battlefield.
clearspace();
// Creating the battlefield
casestatematricia = new char*[column];
for (int i = 0; i < column; ++i) {
casestatematricia[i] = new char[line];
}
// initialise casestatematricia...
}
// Call this after you done using the battlefield
void Map::clearspace() {
if (!casestatematricia) return;
for(int i = 0; i < columnnumber; ++i) {
delete [] casestatematricia[i];
}
delete [][] casestatematricia;
casestatematricia = 0;
}
希望能有所幫助。
PS:如果需要序列化字符串,則可以使用pascal字符串格式,以便支持可變長度的字符串。 例如“ 11hello world”或“ 3foo”。
更換:
char mapname[50];
同
char *mapname;
在類的構造函數中分配內存:
mapname = new char[50];
然后替換:
void Map::setmapname(char newmapname[50])
{
this->mapname = newmapname;
}
有:
void Map::setmapname(char *newmapname, size_t size)
{
memcpy(mapname,newmapname,size);
}
編輯:正如評論中指出的,我忘記了析構函數:在析構函數中釋放內存:
if(mapname)
delete [] mapname;
作為發布此問題的用戶,他是C ++類的新手,這就是為什么在此answear中沒有容器之類的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.