如何正确初始化多维字符数组并将其传递给函数?

4

我正在编写一个程序,用于找到迷宫的出口。我有一个表示实际迷宫的多维数组。

const int size = 12;
    char maze[ size ][ size ] = {
            "############",
            "#...#......#",
            "..#.#.####.#",
            "###.#....#.#",
            "#....###.#..",
            "####.#.#.#.#",
            "#..#.#.#.#.#",
            "##.#.#.#.#.#",
            "#........#.#",
            "######.###.#",
            "#......#...#",
            "############",
        };

VS C++ 给我一个警告信息,说数组的大小太小了。我猜测这是因为每行中必须也有 '\0' 符号导致的。如何在不使用 '\0' 符号的情况下初始化 char 数组?我不想将 size 的值初始化为 13,因为在函数(打印数组、移动等)中使用该常量会太混乱。有没有什么方法可以做到这一点?

另外,如何使用指针将此数组传递给函数 void mazeTraverse

int main()
{
  mazetraverse(maze)
}

void mazeTraverse(char (*maze)[ size ])

这样的代码无法正常工作...


让我想起了Nethack - John Dibling
函数名是 mazeTraverse。你为什么要调用 mazetraverse - AnT stands with Russia
4个回答

3

在处理字符串时需要考虑到字符串末尾的空字符:

char maze[size][size + 1] = { /*  */ };

或者,为了更灵活的操作,您可以执行以下操作:

char *maze[size] = { /*  */ };

我看到你在使用C++。你没有使用std::string,有什么原因吗?

std::string maze[size] = { /*  */ };

这个方法更加灵活,现在你只需要更改原型为:

void mazeTraverse(std::string maze[]);

如果你疯狂到了极点,你可以使用std::vector<std::string>


编辑:我建议学习一下std::string。它与char*的用法类似,但你不需要手动分配内存等操作。例如:

std::string mystring = "lol";
mystring = "lololol"; // perfectly legal!

std::cout << mystring[0] << "\n";
// Or: printf("%c\n", mystring[0]);

char* sz[8];
strcpy(sz, mystring[0].c_str());

// And so on...

非常感谢!你的示例完美运行。我没有使用C++风格的字符串,因为我还没有学习它。现在我专注于C风格的字符串。 - Alex
@Alex稍微修改了我的答案。 - Mateen Ulhaq

2
只要您在使用C++语言,为什么不创建一个简单的类呢?
class Maze {
  public:
    Maze(int width, const std::string& data) 
      :width_(width),
       data_(data.begin(), data.end()) {
    }

    char operator()(int row, int column) const { 
      return data_[width_*row + column]; 
    }

  private:
    int width_;
    std::vector<char> data_;
};

你可以利用后续字符串文本的隐式连接特性,比如 "foo" "bar",来轻松地进行初始化:

Maze my_maze(12, 
             "############"
             "#...#......#"
             "..#.#.####.#"
             "###.#....#.#"
             "#....###.#.."
             "####.#.#.#.#"
             "#..#.#.#.#.#"
             "##.#.#.#.#.#"
             "#........#.#"
             "######.###.#"
             "#......#...#"
             "############");

请注意,引号(在“数组”中)后面没有逗号。 - Mateen Ulhaq
@lidjam:不,我肯定是指operator()。Operator[]只允许一个参数;我们需要两个(即行和列)。 - SuperElectric
@muntoo:没错。为了让每个人都明白,将字符串字面量放在一起而不使用逗号等价于编写一个巨大的字符串。构造函数接受这个const char*并隐式地将其转换为std::string,然后可以轻松地复制到内部表示中:一个std::vector<char>,无需使用空终止字符。 - SuperElectric
你的例子对我来说太难理解了。我熟悉类的基础知识,但像:width_(width), data_(data.begin(), data.end())和std::string这样的东西现在对我来说还不清楚。 - Alex
@SuperElectric:如果你指的是 operator(),那么签名应该是 char operator()(int row, int column) const。你的代码缺少一个关键部分——你正在定义哪个运算符。 - ildjarn
显示剩余2条评论

1
"不起作用"?这段代码是可以工作的。而且它完美地工作着。(假设编译器允许您使用那些13个字符的字符串字面量来初始化大小为12的数组。这实际上是C++中的一个错误,但您说您只是得到了一个警告)。

这样

mazeTraverse(maze);

根据我的理解,代码将编译并且按照你的意愿执行。那么在你的情况下,到底是哪里出了问题呢?“不起作用”并不能准确描述问题。

至于如何消除数组初始化时的警告,如果你坚持要使用精确大小的数组,你需要以逐个字符的方式进行初始化,例如:

char maze[ size ][ size ] = {
  { '#', '#', '#', ... },
  { ...                },
  // and so on
};

如果你想使用字符串字面量,那么正如你自己所指出的,你必须声明内部子数组的更大尺寸。
char maze[ size ][ size + 1 ] = {
  "############",
  // and so on
};

并相应地更改函数声明

void mazeTraverse(char (*maze)[ size + 1 ])

1

初始化,我会:

char* maze[ size ] = {
        "############",
        "#...#......#",
        "..#.#.####.#",
        "###.#....#.#",
        "#....###.#..",
        "####.#.#.#.#",
        "#..#.#.#.#.#",
        "##.#.#.#.#.#",
        "#........#.#",
        "######.###.#",
        "#......#...#",
        "############",
    };

为了传递参数,您应该能够使用char**。这样就可以:

void mazeTraverse(char ** param)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接