【问题标题】:C++: Reading lines of integers from cinC++:从 cin 读取整数行
【发布时间】:2026-02-01 16:10:01
【问题描述】:

当我熟悉 C++ 的 I/O 方面时,我正在尝试编写一个程序来从 std::cin 读取一些整数行。假设输入如下所示:

1 2 3
4 5 6
7 8 9
10 11 12

如何将上述行读入二维向量?

vector<vector<int>> nums;
/* 
 ... some code here and nums will look like the following:
 nums = {
    {1,2,3},
    {4,5,6},
    {7,8,9},
    {10,11,12}
  }
*/

我还尝试将上述整数行读取为一维向量,但在处理 '\n' 字符时遇到了一些问题。我的代码是:

string rawInput;
vector<int> temp;
while(getline(cin, rawInput, ' ') ){
  int num = atoi( rawInput.c_str() );
  temp.push_back(num);
 }

我通过打印出“temp”向量中的所有元素得到的最终结果是:

1 2 3 5 6 8 9 11 12   // 4, 7, 10 went missing

感谢任何帮助。谢谢。

【问题讨论】:

  • 你可以用atoi(x.c_str())代替stoi(x)

标签: c++


【解决方案1】:

首先使用 getline 抓取整行,然后您可以使用 istringstream 为该行创建 ints 流。

此时只需使用带有两个迭代器的向量构造函数来创建整数的每个子向量。您的istringstream 上的istream_iterator&lt;int&gt; 可以完成此操作:

std::vector<std::vector<int>> nums;
std::string line;
while (std::getline(std::cin, line)) {
    std::istringstream ss(line);
    nums.emplace_back(std::istream_iterator<int>{ss}, std::istream_iterator<int>{});
}

【讨论】:

    【解决方案2】:

    发生的事情是因为你只使用''(空格)作为分隔符,输入恰好是

    1
    2
    3\n4 //<------ Newline also comes with the input
    
    ...
    

    所以,您将3\n46\n7 等传递给atoi,它会返回 3,6 等(atoi 解析输入直到第一个非数字输入)并且4,7 丢失。

    要实现你想要的,你可以使用 getline 和 istringstream(将默认分隔符保留为换行符)

    string rawInput;
    vector<vector<int>> temp;
    while(getline(cin, rawInput) ){
      istringstream bufferInput(rawInput); 
      temp.push_back(vector<int>{std::istream_iterator<int>{bufferInput}, std::istream_iterator<int>{}});
    }
    

    【讨论】:

    • 很好地识别问题,而不是仅仅提出其他解决方案。
    【解决方案3】:

    你可以使用字符串流

    string rawInput;
    vector<int> temp;
    stringstream ss;
    
    while(getline(cin,rawInput)){
      ss<<rawInput;
      vector<int> temp;
      int x;
      
      while(ss>>x){
        temp.push_back(x);
      }
      
      num.push_back(temp)
    }

    【讨论】:

      【解决方案4】:

      我最近写了另一个问题的答案,但经过一些修改,它完全符合您的要求(我希望):

      #ifndef _IOSTREAM_H
      #include <iostream>
      #endif
      #ifndef _STRING_H
      #include <string>
      #endif
      #ifndef _VECTOR_H
      #include <vector>
      #endif
      
      using namespace std;
      
      enum XYZ { X = 0, Y = 1, Z = 2 };
      
      struct Vector {
          float x, y, z;
          Vector(float _x=0, float _y=0, float _z=0) {
              x = _x;
              y = _y;
              z = _z;
          }
          float& operator[](size_t index) {
              if (index == XYZ::X) return x;
              if (index == XYZ::Y) return y;
              if (index == XYZ::Z) return z;
              throw new exception;
          }
      };
      
      
      
      #define min(a, b) (((a) < (b)) ? (a) : (b))
      
      bool isCharNumeric(char c) {
          const char* numbers = "0123456789";
          for (size_t index = 0; index < strlen(numbers); index++)
              if (c == numbers[index]) return true; return false;
      }
      
      vector<Vector> parseNumbers(string str_in) {
          str_in += "  "; //safe, no out of bounds
          vector<Vector> results = {};
          char currentChar;
          char skipChar = ' ';
          bool found_period = false;
          size_t count_len = 0;
          Vector vector_buffer(0,0,0);
          XYZ current_axis = (XYZ)0;
          for (size_t index = 0; index < str_in.length(); index++) {
              currentChar = str_in[index];
              if (currentChar == skipChar || currentChar == '\n' || currentChar == '\t')
                  continue;
      
              else if (isCharNumeric(currentChar)) {
                  string word = ""; //word buffer
                  size_t word_len = min(min(str_in.find_first_of(' ', index + 1) - (index), str_in.find_first_of('\n', index + 1) - (index)), str_in.find_first_of('\t', index + 1) - (index)); //whatever char comes first; newline, tab or space
                                                                                                                                                                    //append chars of following word checking if it is still valid number char
                  if (word_len > 0) {
                      size_t count_word_len = 0;
                      for (count_word_len = 0; count_word_len < word_len; count_word_len++)
                          if (isCharNumeric(str_in[index + count_word_len])) {
                              word += str_in[index + count_word_len];
                          }
                          else if (str_in[index + count_word_len] == '.' && isCharNumeric(str_in[index + count_word_len + 1])) {
                              //Floating-point numbers
                              word += '.';
                              found_period = true;
                              continue;
                          }
                          else {
                              word = "";
                              continue;
                          }
      
                          vector_buffer[current_axis] = stof(word);
      
      
                          if (current_axis == XYZ::Z) {
                              current_axis = XYZ::X;
                              results.push_back(vector_buffer);
                          }
                          else {
                              current_axis = (XYZ)(current_axis + 1);
                          }
      
      
                          index += count_word_len;
                          word = "";
                          continue;
                  }
      
              }
          }
          return results;
      }
      

      示例实现:

      int main(int argc, char** argv) {
          string user_input;
          cin >> user_input;
          vector<Vector> numbers = parseNumbers(user_input);
          for each (Vector v in numbers) {
              cout << "X=" << v.X << "\n";
              cout << "Y=" << v.Y << "\n";
              cout << "Z=" << v.Z << "\n\n";
          }
      }
      

      【讨论】:

      • 您可能应该添加一个链接到您之前回答的问题。
      【解决方案5】:

      令人惊讶的是,没有一个答案使用 istream 流运算符: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

      当流为空时,设置了 eofbit,因此运行一个 while 循环。

      适用于所有类型,并且可以为自定义类型(例如 2D 纹理)重载。

      【讨论】: