【问题标题】:How to read n integers from standard input in C++?如何从 C++ 的标准输入中读取 n 个整数?
【发布时间】:2011-10-17 23:05:13
【问题描述】:

我需要阅读以下内容:

5 60 35 42
2 38 6
5 8
300 1500 900

然后将第一行保存在一个数组中。调用其他函数后,对下一行执行相同操作,依此类推。

我尝试使用gets(),然后使用sscanf() 扫描字符串中的整数,但我不知道如何从字符串中读取n 个数字。

【问题讨论】:

标签: c++ stdin


【解决方案1】:

C++

如果您有未知数量的条目分布在未知数量的行中,以 EOF 结尾:

int n;
while(cin >> n)
  vector_of_int.push_back(n);

如果您有已知数量的条目分布在未知数量的行中:

int n;
int number_of_entries = 20; // 20 for example, I don't know how many you have.
for(int i ; i < number_of_entries; ++i)
  if(cin >> n)
    vector_of_int.push_back(n);

如果您在一行中有未知数量的条目:

std::string str;
std::getline(std::cin, str);
std::istringstream sstr(str);
int n;
while(sstr >> n)
  vector_of_int.push_back(n);

如果您有未知数量的条目分布在已知数量的行中:

for(int i = 0; i < number_of_lines; ++i) {
  std::string str;
  if(std::getline(std::cin, str)) {
    std::istringstream sstr(str);
    int n;
    while(sstr >> n)
      vector_of_int.push_back(n);
  }
}
  

【讨论】:

  • 有没有办法一次完成这一行?因为我认为 cin 不会读取 \n 所以我不知道该行何时更改。
  • @RobertoLapuente - 对于您给出的示例,我的第一种方法是正确的 - 几个数字分布在多行中,在文件末尾结束。 cin 读取并忽略\n,就像它读取并忽略空格字符一样。
  • @Rob:我认为每一行都是它自己的数组。他需要在四个数组中的每一个上运行一个函数。
  • @Rob 我可以做 'while (std::getline(std::cin, str)>0)' 或类似的东西? 'getline' 到达 EOF 时的返回值是什么?
  • @Roberto :对于您的目的,它返回 false(从技术上讲不是这种情况,但同样,对于 您的 目的......),所以 while (std::getline(std::cin, str)) 就足够了。
【解决方案2】:

我以前曾在比赛中看到过这样的输入文件。如果速度比错误检测更重要,您可以使用自定义例程。这是一个与我使用的类似的:

void readintline(unsigned int* array, int* size) {
    char buffer[101];
    size=0;
    char* in=buffer;
    unsigned int* out=array;
    fgets(buffer, 100, stdin);
    do {
        *out=0;
        while(*in>='0') {
            *out= *out* 10 + *in-'0';
            ++in;
        }
        if (*in)
            ++in; //skip whitespace
        ++out;
    } while(*in);
    size = out-array;
}

如果一行中有超过 100 个字符,或者比数组可以容纳的数字更多,它会破坏你的记忆,但是你不会得到更快的例程来读取无符号整数行。

另一方面,如果你想要简单:

int main() {
    std::string tmp;
    while(std::getline(std::cin, tmp)) {
        std::vector<int> nums;
        std::stringstream ss(tmp);
        int ti;
        while(ss >> ti) 
            nums.push_back(ti);
        //do stuff with nums
    }
    return 0;
}

【讨论】:

  • 其实输入来自 ACM 编程竞赛。我想过这样的事情,但我认为应该有更简单的方法。
【解决方案3】:

我可能会这样写代码:

// Warning: untested code.
std::vector<int> read_line_ints(std::istream &is) { 
    std::string temp;
    std::getline(is, temp);

    std::istringstream buffer(temp);
    int num;
    std::vector<int> ret;

    while (buffer>>num)
        ret.push_back(num);
    return ret;
}

【讨论】:

    【解决方案4】:

    在 C++ 中,您可以使用std::istringstream

    std::string nums = "1 20 300 4000";
    std::istringstream stream(nums);
    int a, b, c, d;
    stream >> a >> b >> c >> d;
    assert(a == 1 && b == 20 && c == 300 && d == 4000);
    

    如果您想从标准输入中获取它,那么也可以这样做,但只需使用std::cin

    std::cin >> a >> b >> c >> d;
    

    【讨论】:

      【解决方案5】:

      快速的解决方案是使用scanf()阅读它们

      int array[1000];
      int index = 0;
      
      while ((index < 1000) && (scanf("%d", &tmp) == 1)) {
          array[index++] = tmp;
      }
      

      这还需要更多的验证...

      【讨论】:

      • 不要忘记%d之前的空格来吃任何空格。
      • @RobertoLapuente 我也会采用这个解决方案。很多人不知道scanf的返回值的用法,所以即使你决定用c++的istringstream,也一定要学会这一点。
      • @TomZych 它是自动完成的。 %d 之前有空格的问题是,如果在第一个整数之前没有空格,那么scanf 会失败(因为你告诉它它必须看到空格)
      • @Shahbaz:好点。我不使用scanf,太脆弱了,我记得 91 年的 C 课程中的一些内容。我猜你把空格放在后面?我很确定你需要它。
      • @TomZych,那么您将强制 scanf 在最后一个可能不存在的数字之后读取空格。通常scanf 忽略格式字符串前后的空格除非 您请求%c,它也将空格作为字符读取并且不会忽略它。在这种情况下,是的,您需要空间。
      【解决方案6】:

      C++:

      vector<int> ints;
      while( !cin.eof() )
      {
         int t;
         cin >> t;
         if ( !cin.eof() )
            ints.push_back(t);
      }
      

      替代方案(感谢 Shahbaz)

      int t;
      vector<int> ints;
      while(cin >> t)
         ints.push_back(t);
      

      【讨论】:

      • 因为eof 标志直到之后 才会设置,所以ints 中的最后一个元素将始终是垃圾数据。
      • 请不要鼓励使用eof()。它不会像人们想的那样做,而且几乎总是会导致一个错误(就像你在这里的那个)。
      • 使用eof(一般情况下)是没有问题的。我修复了代码。
      • 有没有办法一次完成这一行?因为我认为 cin 不会读取 \n 所以我不知道该行何时更改。
      • @George :不,你没有——while( !somestream.eof() ) 永远不会正确,在这种情况下,每个 temp 实例的最后一个元素将包含垃圾数据,以及ints 的最后一个元素。
      【解决方案7】:

      在 C++ 中,通过标准输入读取由空格分隔的 N 个整数非常简单:

      #include <iostream>
      
      using namespace std;
      
      const unsigned N = 5;
      
      int main(void)
      {
         int nums[N];
      
         for (unsigned i = 0; i < N; ++i)
            cin >> nums[i];
      
         cout << "Your numbers were:\n";
      
         for (unsigned i = 0; i < N; ++i)
            cout << nums[i] << " ";
      
         cout << "\n";
      
         return 0;
      }
      

      【讨论】:

      • 我花了很长时间才发帖,因为我看不到代码按钮。 :/ 我也使用了数组而不是向量,因为我们已经知道数组的大小,希望 Stroustrup 不会介意。另请注意,此代码中没有错误处理。
      猜你喜欢
      • 2021-04-09
      • 2011-04-14
      • 2019-07-26
      • 2018-04-28
      • 1970-01-01
      • 2014-08-22
      • 2020-02-25
      • 2023-03-18
      • 2011-01-31
      相关资源
      最近更新 更多