Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly read and parse a string of integers from stdin C++

Just as the title says, I'm reading in a string of integers from stdin. The data i'm trying to read in appears in the following form in a text file:

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

The first two lines are always just single numbers (no problems there!) and the following lines each have 3 numbers. This file is redirected as stdin to my program (myprogram < textfile).

I've tried so many things but have not been able to successfully to do this! It seems so simple but I keep tripped up on where (or how) i should convert to an integer. Here is my latest attempt:

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;

}

I segfault when i try to use atoi...

Thanks in advance!

like image 544
Wakka Wakka Wakka Avatar asked Nov 16 '25 10:11

Wakka Wakka Wakka


1 Answers

If you trust your input enough not to care whether the numbers have line breaks in the expected places, then you can do something like this:

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";
}

If you think it would help to have an error and explanation when linebreaks aren't in the expected places (e.g. numCities and numRoads on one line, blank line, x y on one line while z is on the next...) then you can read specific lines and parse out the values (more tedious though):

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...)
}
like image 77
Tony Delroy Avatar answered Nov 17 '25 22:11

Tony Delroy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!