我是使用类的新手,我在将数组转换为类时遇到了问题。我想初始化一个char数组,用于限制为50个字符的文本,然后用函数替换文本。
char casestatematricia[][];
顺便说一下,我可以像那样初始化我的2d数组
casestatematricia[linenumber][columnnumber]
我想稍后将这个二维数组动态化,我输入一个列号和一个像这样的行号
#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()
{
}
创造一个战场。
这是cpp代码,以便您了解我想要做什么。
{{1}}
提前谢谢。
答案 0 :(得分:4)
考虑以下常见做法。 大多数(例如数字)库不在类内使用2D数组。 它们使用动态分配的1D数组并重载()或[]运算符以类似2D的方式访问正确的元素。 所以在外面你永远不能告诉你实际上是在处理连续存储,它看起来像一个2D数组。 通过这种方式,数组更容易调整大小,更有效地存储,转置和重塑。
答案 1 :(得分:2)
只是你问题的主张:
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];
}
}
}
};
要像二维数组一样访问一维数组,请查看Access a 1D array as a 2D array in C++。
当您考虑序列化时,我想您想将其保存到文件中。只是一个建议:不要将原始内存存储到文件中以保存&#34;保存&#34;重新启动软件的时间。你只有一个非便携式解决方案!严肃地说,凭借计算机的强大功能,您不必担心从文件加载的时间!
我建议你在你的类中添加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 - serialization techniques(只需翻译成C ++)。但请不要使用memcpy
或类似的技术来序列化
答案 2 :(得分:-1)
我希望我做对了。你有两个问题。您想了解如何通过char mapname[50];
分配void setmapname(char newmapname[50]);
的值。并且您想知道如何创建动态大小的2D数组。
我希望你对指针感到满意,因为在这两种情况下,你都需要它。
对于第一个问题,我想首先纠正您对void setmapname(char newmapname[50]);
的理解。 C ++函数不接受数组。它接收指向数组的指针。所以它和写void setmapname(char *newmapname);
一样好。为了更好地理解,请转到Passing Arrays to Function in 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字符串格式,以便支持可变长度的字符串。例如&#34; 11hello world&#34;,或&#34; 3foo&#34;。
答案 3 :(得分:-3)
替换:
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 ++,这就是为什么在这个服装中没有容器和类似的东西。