C ++在类中声明数组并在类中声明2d数组

时间:2016-08-03 10:23:54

标签: c++ arrays class multidimensional-array sfml

我是使用类的新手,我在将数组转换为类时遇到了问题。我想初始化一个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}}

提前谢谢。

4 个答案:

答案 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 ++,这就是为什么在这个服装中没有容器和类似的东西。