簡體   English   中英

C ++在類中聲明數組並在類中聲明2d數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM