【问题标题】:How to correctly initialize multidimentional char array and pass it to function?如何正确初始化多维字符数组并将其传递给函数?
【发布时间】:2023-04-09 13:04:02
【问题描述】:

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

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

VS C++ 给了我一个警告信息,说大小对于这样的数组来说太小了。我想这是因为每行中还必须有 '\0' 符号。如何初始化没有 '\0' 符号的 char 数组?我不想用值 13 初始化size,因为将这个常量用于函数(打印数组、移动等)会很混乱。有什么办法吗?

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

int main()
{
  mazetraverse(maze)
}

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

这样的代码不起作用...

【问题讨论】:

  • 让我想起了Nethack
  • 函数名是mazeTraverse。你为什么要打电话给mazetraverse

标签: c++ multidimensional-array char


【解决方案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 ])

【讨论】:

    【解决方案2】:

    要初始化,我会:

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

    要传递参数,您应该能够使用 char**。那就是:

    void mazeTraverse(char ** param)
    

    【讨论】:

      【解决方案3】:

      您需要考虑字符串末尾的 NULL 字符:

      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 稍微编辑了我的答案。
      【解决方案4】:

      只要你在使用 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”)隐式连接到“foobar”的事实轻松初始化它:

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

      【讨论】:

      • 请注意引号后没有任何逗号(在“数组”中)。
      • @lidjam:不,我绝对是指 operator()。 Operator[] 只允许一个参数;我们需要两个(即行和列)。
      • @muntoo:没错。只是为每个人拼写出来:将字符串文字彼此相邻而不用逗号等同于写​​出一个巨大的字符串。构造函数采用这个 const char* 并隐式将其转换为 std::string,然后可以轻松地将其复制到内部表示:一个 std::vector ,不需要空终止字符。
      • 你的例子对我来说太难理解了。我熟悉类的基础,但我现在不知道 :width_(width)、data_(data.begin()、data.end()) 和 std::string 之类的东西。
      • @SuperElectric :如果你的意思是operator(),那么签名应该是char operator()(int row, int column) const。您的代码缺少一个关键部分——您正在定义哪个运算符。
      猜你喜欢
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      • 2021-11-13
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多