【问题标题】:How to properly read and parse a string of integers from stdin C++如何从标准输入 C++ 正确读取和解析整数字符串
【发布时间】:2012-07-21 06:11:51
【问题描述】:

正如标题所说,我正在从标准输入读取一串整数。我试图读取的数据以以下形式出现在文本文件中:

3
4
7 8 3
7 9 2
8 9 1
0 1 28
etc...    

前两行总是只有一个数字(没有问题!),接下来的每行都有 3 个数字。该文件作为标准输入重定向到我的程序(myprogram

我已经尝试了很多东西,但都无法成功地做到这一点!看起来很简单,但我一直在纠结应该在哪里(或如何)转换为整数。这是我最近的尝试:

int main()
{

  string str, str1, str2;
  int numCities;
  int numRoads, x, y, z;
  cin >> numCities >> numRoads;

  cout << numCities << " " << numRoads << endl;
  //getline(cin, str1);


  while( getline(cin, str))
  {
    char *cstr;
    cstr = new char[str.size()+1];
    strcpy(cstr, str.c_str());

    x = atoi(strtok(cstr, " ")); //these will be stored in an array or something
    y = atoi(strtok(NULL, " ")); //but right now i just want to at least properly
    z = atoi(strtok(NULL, " ")); //store the appropriate values in these variables!


  }


 return 0;

}

我尝试使用 atoi 时出现段错误...

提前致谢!

【问题讨论】:

  • @Kevin : while (cin.good()) 是一种反模式。 @Wakka,你想单独存储每一行​​的数字,还是只存储所有数字的一个大列表?
  • @ildjarn:while (cin &gt;&gt; x &gt;&gt; y &gt;&gt; z) 呢?
  • @Victor :那肯定是一个改进。 ;-]

标签: c++ string parsing integer


【解决方案1】:

如果您足够信任您的输入而不关心数字是否在预期的位置有换行符,那么您可以执行以下操作:

int main()
{
    int numCities, numRoads;
    if (cin >> numCities >> numRoads)
    {
        int x, y, z;
        while (std::cin >> x >> y >> z)
        {
            // use the values in here...
        }
        if (!std::cin.eof())
            std::cerr << "encountered unparsable x, y and/or z before end of file\n";
    }
    else
        std::cerr << "unable to parse numCities and/or numRoads\n";
}

如果您认为当换行符不在预期位置时(例如,numCities 和 numRoads 在一行,空白行,xy 在一行,而 z 在下一行......)然后你可以读取特定的行并解析出值(虽然更乏味):

int main()
{
    std::string line;
    int numCities, numRoads;

    if (!std::getline(line, std::cin))
        FATAL("couldn't read line on which numCities was expected");
    std::istringstream iss(line);
    char unexpected;
    if (iss >> numCities)
        FATAL("unable to parse numCities value out of line '" << line << '\'')
    if (iss.getchar())
        FATAL("unparsabel trailing garbage characters after numCities value on line '" << line << '\'')

    // etc. (you can factor the above kind of logic into a function...)
}

【讨论】:

    【解决方案2】:

    首先,您使用cin 读取您的输入,然后使用getline。但是,当您阅读最后一个数字时,缺少'\n'。你的第一个getline(cin, str) 正在阅读'\n',这就是你得到段错误的原因。要检查它,请将以下几行添加到您的代码中:

    // just change these lines: 
    getline(cin, str);
    cout << str << endl;
    while(getline(cin, str))
    {
        cout << str << endl;
    
        // ...
    

    您的输出将是:

    // output
    3 4
    
    7 8 3
    7 9 2
    8 9 1
    0 1 28
    

    您是否只想获取int 的所有数字?对于这个输入,我建议:

    while (cin >> x >> y >> z) 
    {
        cout << x << " " << y << " " << z;
    }
    

    getline()解决方案

    您仍然可以使用getline 函数。然后,我建议您将输入读数更改为在前两行也使用getline。通过这种方式,您不会遇到'\n' 的问题。但是,我认为它变得太复杂了,我不推荐。特别是如果这是一个马拉松问题。

    // ...
    getline(cin, str);
    numCities = atoi( str.c_str() );
    
    getline(cin, str);
    numRoads = atoi( str.c_str() );
    
    cout << numCities << " " << numRoads << endl;
    
    while(getline(cin, str))
      {    
        char *cstr;
        cstr = new char[str.size()+1];
        strcpy(cstr, str.c_str());
    
        x = atoi(strtok(cstr, " "));
        y = atoi(strtok(NULL, " "));
        z = atoi(strtok(NULL, " "));
      }
    

    【讨论】:

    • 抱歉回复晚了(昨晚我的电脑坏了)。虽然带有 cin 的状态正是我所需要的,但我肯定是过于复杂了。我猜如果 cin 没有读取任何内容,它会返回 NULL 吗?非常感谢!
    • 没错! cinstd::istream 类型,读取后返回。由于它是在一个布尔上下文中,它将被函数std::istream::operator void*() 转换为布尔值。 NULL 变为 false 并且任何其他指针变为 trueMore information here
    【解决方案3】:

    您可以将数据存储为字符串,然后将字符串更改为整数。

    测试代码如下:

    #include <iostream>
    #include <stdlib.h>
    #include <fstream>
    #include <string>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        ifstream in("t1.txt");
    
        string s1,s2,s3;
        int a1,a2,a3;
    
        in>>s1>>s2;
        a1 = atoi(s1.c_str());
        a2 = atoi(s2.c_str());
        cout<<a1<<" "<<a2<<endl;
    
        while((in>>s1>>s2>>s3))
        {
            a1 = atoi(s1.c_str());
            a2 = atoi(s2.c_str());
            a3 = atoi(s3.c_str());
            cout<<a1<<" "<<a2<<" "<<a3<<endl;
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 2021-06-19
      • 1970-01-01
      • 2019-07-26
      • 2016-12-13
      相关资源
      最近更新 更多