-2

Let's assume that I have the following input

8 2 I slept long 
8 3 5 Students didn't do well
9 1 What should I do? seriously
9 5 I have no idea what to do from now on

stored in wow.txt.

I wanted to take two integers and the string separately for each line (so for the first line, I take in 8, 2, and then I slept long string as inputs and move onto next line, and for the second line, I take in 8 and 3 as integers then 5 Students didn't do well as a string and so on), but I don't know how to do so.

If I use getline, then I would take the entire line as input, and I was wondering if there's a way of taking the first couple of inputs and the rest of the line separately.

Any help would be greatly appreciated.

jrd1
  • 9,026
  • 4
  • 30
  • 48
user98235
  • 702
  • 1
  • 7
  • 23

3 Answers3

2

This is a simple exercise in parsing. Mainly, one where you have to get creative with how input streams are used in C++.

  int a, b;

  std::string line = "8 2 5 Students didn't do too well";

  std::istringstream iss(line);//initialize to the contents of the string.

  iss >> a >> b;

  std::string str;
  std::getline(iss, str);

Since input streams skip over whitespace by default, you can use this to your advantage. Simply:

  1. Read the first two inputs as integers using a string stream.
  2. Use std::getline to store the remainder of the string (where it is understood that the delimiting character in std::getline is a newline) from the string stream.

And, that's it.

Hence, the contents of a, b and str respectively will be:

8
2
 5 Students didn't do too well

As you no doubt observe, the only caveat is that the first character of the stored string (str) will be a space. But, you can remove that on your own.

jrd1
  • 9,026
  • 4
  • 30
  • 48
  • This is an interesting way of avoiding doing the parsing yourself, but often something you want to do is error checking, or handling cases, so splitting and parsing yourself is my choice. But I gave a +1 for the correctness and novelty. – SingleStepper Aug 03 '14 at 00:29
  • @SingleStepper: Thank you for your comment. I agree with what you said. However, to correctly address such concerns as you have quite correctly stated, that would take far too long an explanation. Plus, as this has already been done before, it's better to use some Open Source library to better and robustly address those concerns. – jrd1 Aug 03 '14 at 00:34
1

In order to get a complete example, you could do it like this:

// Open a file for input
ifstream f("wow.txt");

// Repeat until you reach the end of the file
while (!f.eof()) {
    int i, j;

    // Read the integers using stream operators
    f >> i >> j;

    // If there are no more integers (e.g. an empty line or
    // invalid integers at the beginning), end the loop
    if (!f.good())
        break;

    string s;

    // Read the rest of the line into a string
    getline(f, s);

    // Remove the space char at the beginning of the string 
    // (if present)
    if (s.length() > 1) {
        s = s.substr(1);
    }

    // Output result, separated by semicolons.
    cout << i << ";" << j << ";" << s << endl;
}

As you may have noticed, in cases like theses you need to decide, how to deal with unexpected inputs. Here, I simply exit the loop, if there are not two integers at the beginning of the line. On the other hand, I ignore a missing string after the integers and accept empty strings here.

How you want to do this depends on how reliable you input data is and in what scenario you are using the function.

Edit jrd1 had pretty much the same idea as me, I was just a slower to post it. I still leave my answer here since it adds using a fstream and shows a simple way to deal with parsing errors.

MartinStettner
  • 27,323
  • 13
  • 73
  • 104
0

Since the file is text, it's a series of lines that will be read in as such. You'll need to split (using the space character) yourself in whatever language you're using. In Binary mode it's the same thing, there's no such thing as "reading until a space is found"

Unless you read character by character looking for spaces, but that's inefficient.

SingleStepper
  • 351
  • 1
  • 10