【问题标题】:How to put characters from file into two-dimensional vector?如何将文件中的字符放入二维向量中?
【发布时间】:2019-11-16 14:46:43
【问题描述】:

我一直在尝试从外部文件中读取字符,以将其放入char 类型的二维向量中。这些元素必须能够与某些值进行比较,才能在“MazeSample.txt”中给出的迷宫中导航。

虽然我无法将字符放入向量中,但我能够使用getcout 函数读取和输出字符。 以下代码尝试以正确的格式读取向量,但最终提供了错误:

//MazeSample.txt
SWWOW
OOOOW
WWWOW
WEOOW

//source.cpp
vector<vector<char>> maze;
ifstream mazeFile;
char token;

mazeFile.open("MazeSample.txt");

while (!mazeFile.eof()) {
    mazeFile.get(token); //reads a single character, goes to next char after loop

    for (int row = 0; row < maze.size(); row++) {
        for (int column = 0; column < maze.at(row).size(); row++) {
            maze.push_back(token);
        }
    }

    //cout << token;
}

mazeFile.close();

对于“MazeSample.txt”中提供的迷宫,我希望maze 向量逐行读取每个字符,模仿迷宫样本的格式。

在上面的代码中,maze.push_back(token) 出现错误: “没有重载函数的实例“std::vector<_ty _alloc>::push_back...”与参数列表匹配” “参数类型是:(char)” "对象类型为:std::vector>, std::allocator>>>"

【问题讨论】:

    标签: c++ c++11 file-io 2d-vector


    【解决方案1】:

    您正在将char 插入到vector&lt;vector&lt;char&gt;&gt;。您应该创建一个vector&lt;char&gt;,将char 类型的值插入其中,然后将vector&lt;char&gt; 插入vector&lt;vector&lt;char&gt;&gt; maze;。这是您的程序的更正版本。它可以用简单的方式编写,但为了您的理解,我在您的程序之上进行了更正。

    vector<vector<char>> maze;
    ifstream mazeFile;
    string token;
    
    mazeFile.open("MazeSample.txt");
    
    while (!mazeFile.eof()) {
        std::getline(mazeFile, token); //reads an entire line
    
        //Copy characters in entire row to vector of char
        vector<char> vecRow;
        vecRow.assign(token.begin(), token.end());
    
        //Push entire row of characters in a vector
        maze.push_back(vecRow);
    
    }
    
    mazeFile.close();
    

    【讨论】:

      【解决方案2】:

      您的问题的原因是您尝试将 char 放入 std 向量的 std::vector 中。所以你输入了错误的类型。

      maze.at(row).push_back(token); 会这样做,但随后不存在行。您还需要 push_back 并清空行,然后才能向其写入数据。

      那是你的语法错误。

      然后,您的代码可以通过使用 C++ 算法大大缩短。见:

      
      #include <iostream>
      #include <vector>
      #include <algorithm>
      #include <iterator>
      #include <sstream>
      
      
      std::istringstream testDataFile(
      R"#(00000
      11111
      22222
      33333
      44444
      )#");
      
      
      
      // This is a proxy to read a complete line with the extractor operator
      struct CompleteLineAsVectorOfChar {
          // Overloaded Extractor Operator
          friend std::istream& operator>>(std::istream& is, CompleteLineAsVectorOfChar& cl) {
              std::string s{}; cl.completeLine.clear();  std::getline(is, s); 
              std::copy(s.begin(), s.end(), std::back_inserter(cl.completeLine));
              return is; }
      
          operator std::vector<char>() const { return completeLine; }  // Type cast operator for expected value
          std::vector<char> completeLine{};
      };
      
      
      int main()
      {
          // Read complete source file into maze, by simply defining the variable and using the range constructor
          std::vector<std::vector<char>> maze { std::istream_iterator<CompleteLineAsVectorOfChar>(testDataFile), std::istream_iterator<CompleteLineAsVectorOfChar>() };
      
          // Debug output:  Copy all data to std::cout
          std::for_each(maze.begin(), maze.end(), [](const std::vector<char> & l) {std::copy(l.begin(), l.end(), std::ostream_iterator<char>(std::cout, " ")); std::cout << '\n'; });
      
          return 0;
      }
      

      但这不是结束。 std::vector&lt;char&gt; 对字符串没有优势。您几乎可以拥有与std::vector&lt;char&gt; 相同的所有功能。这是设计上的改进。然后代码看起来更像这样:

      #include <iostream>
      #include <vector>
      #include <algorithm>
      #include <iterator>
      #include <sstream>
      
      std::istringstream testDataFile(
      R"#(00000
      11111
      22222
      33333
      44444
      )#");
      
      int main()
      {
          // Read complete source file into maze, by simply defining the variable and using the range constructor
          std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };
      
          // Debug output:  Copy all data to std::cout
          std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
      
          return 0;
      }
      

      这是迄今为止更简单的解决方案。它也将满足您的需求。

      请注意:我使用 istringstream 来读取数据,因为我在 SO 上没有文件。但这与使用任何其他流(如 ifstream)的原因相同。

      编辑

      第一种方案读取源码,​​直接放入std::vector&lt;std::vector&lt;char&gt;&gt;

      第二个解决方案将所有内容放在std::vector&lt;std::vector&lt;std::string&gt;&gt; 中,这是最有效的解决方案。 std::string 也几乎是 std::vector&lt;std::vector&lt;char&gt;&gt;

      OP 请求第三种解决方案,我们使用第二种解决方案,然后将std::vector&lt;std::vector&lt;std::string&gt;&gt; 复制到std::vector&lt;std::vector&lt;char&gt;&gt;

      请看下面

      
      #include <iostream>
      #include <vector>
      #include <algorithm>
      #include <iterator>
      #include <sstream>
      
      std::istringstream testDataFile(
          R"#(00000
      11111
      22222
      33333
      44444
      )#");
      
      int main()
      {
          // Read complete source file into maze, by simply defining the variable and using the range constructor
          std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };
      
          // Debug output:  Copy all data to std::cout
          std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
      
      
          // Edit: Copy into a std::vector<std::vector<char> -------------------------------------------------------
          std::cout << "\n\n\nSolution 3:\n\n";
      
          // Define the new variable with number of lines from the first maze
          std::vector<std::vector<char>> mazeChar(maze.size());
      
          // Copy the data from the original maze
          std::transform(
              maze.begin(),               // Source
              maze.end(), 
              mazeChar.begin(),           // Destination
              [](const std::string & s) {
                  std::vector<char>vc;    // Copy columns
                  std::copy(s.begin(), s.end(), std::back_inserter(vc)); 
                  return vc; 
              }
          );
      
          // Debug Output
          std::for_each(
              mazeChar.begin(),
              mazeChar.end(),
              [](const std::vector<char> & vc) {
                  std::copy(vc.begin(), vc.end(), std::ostream_iterator<char>(std::cout));
                  std::cout << '\n';
              }
          );
      
          return 0;
      }
      

      希望这会有所帮助。 . .

      【讨论】:

      • 谢谢!虽然第二种解决方案有效,易于理解且高效,但我如何能够将字符插入 2D 字符向量(根据原始问题)?
      • 我添加了一个额外的例子。但相信我。第2个是最好的。也许您应该向您的讲师解释 std::string 与 std::vector 几乎相同。 . .
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多