0

I have a question similar to the one posted here:

C++: Read from text file and separate into variable

The difference is that the original post had the file.txt in the following format:

  • name int int int
  • name int int int

My file has the following format:

  • fname lname

  • int int int

  • fname lname

  • int int int

I am trying to read the name in (first and last) and store it to a single variable and each int into its own separate variable (for future calculations).

I have tried using something similar to the answer, but the newlines are messing up my variables.

As an added bonus, there are random blank lines in my file.

Here is the code I have so far

if (myfile.is_open())
{    
    while (getline(myfile, line))
    {
        istringstream iss(line);

        string fname;

        string lname;

        if (line != "")
        {
            iss >> fname >> lname >> x >> y >> z >> a >> b >> c;
            cout << "name: " << fname << endl;
            //iss >> x >> y >> z >> a >> b >> c;
            cout << "x: " << x << "y: " << y << endl;

        }
        else cout << "";
    }
}
Community
  • 1
  • 1
  • The names and the ints are in different lines but you try to extract them from the same line. `iss >>` etc will only be access 1 line. You'll need some way to remember which kind of line you are on, taking into account blank lines. Also, not a big deal but don't set up the stringstream until after you've checked for a blank line, as that is more efficient. – Neil Kirk Oct 06 '15 at 01:53

4 Answers4

0

You need 2 lines and to break up your variable reading.

iss >> fname >> lname >> x >> y >> z >> a >> b >> c; //don't know why you have 6 ints when you specified 3, I'll assume 6 is correct

becomes

issFirstLine >> fname >> lname;
issSecondLine >> x >> y >> z >> a >> b >> c;

Now there are multiple ways of doing this. 2 options are: You could try to read 2 lines separately, and only do the printing if you have 2 non-empty lines, or you could have some sort of variable to determine if you are on a name or an int line, print accordingly, and change the expected type at the end of a successful output.

Dominique McDonnell
  • 2,510
  • 16
  • 25
0

You can use freopen() for read the file. There will no problem, if the multiple blank line between the desire input line.

freopen("test.txt","r",stdin);
string fname;
string lname;
int x, y,z ,a ,b ,c;
while(cin>>fname){
cin>>lname>> x >> y >> z ;
//your other code
}
Animesh Kumar Paul
  • 2,241
  • 4
  • 26
  • 37
0

Something like that should work.

#include <stdio.h>

int main(int argc, char** argv) {
    FILE *fin = fopen("in.txt", "r");

    char fname[1024], lname[1024];
    int x, y, z;
    while (fscanf(fin, "%s %s %d %d %d", fname, lname, &x, &y, &z) == 5) {
        printf("%s %s %d %d %d\n", fname, lname, x, y, z);
    }

    return 0;
}
anmaxvl
  • 181
  • 1
  • 8
  • This isn't so much C++ as it is C – Tas Oct 06 '15 at 02:42
  • Also doesn't guarantee that the input is on two lines or that the requested number of elements was even read. `fscanf(fin, "%s %s\n%d %d %d", fname, lname, &x, &y, &z) == 5` would. – user4581301 Oct 06 '15 at 02:53
  • @Tas true, but this way you don't have the "new line" issue and generally fscanf is faster than ifstream, I believe (unless you use buffering of some sort). – anmaxvl Oct 07 '15 at 02:31
0

OP is so close it hurts.

I'm going to suggest a simplification by introducing a function to help eliminate the blank lines:

istream & getNonBlankLine(istream & in,
                           string & line)
{
    while (getline(in, line) && line.length() == 0)
    {
        //does nothing. If the loop didn't exit, line was blank
        // if the loop exited, either we're out of lines or we got a valid line
        // out of lines case is handled by testing the stream state on return 
    }
    return in; // lets us chain and also lets us easily test the state of the stream
}

And then back to the job at hand:

if (myfile.is_open())
{
    string nameline;
    string numberline;
    while (getNonBlankLine(myfile, nameline) &&
           getNonBlankLine(myfile, numberline))
    { // got two non-blank lines and the stream is still good
        //turn lines into streams
        stringstream namess(nameline);
        stringstream numberss(numberline);

        // parse streams 
        if (namess >> fname >> lname && // read in first and last name or return error 
            numberss >> x >> y >> z) // read in x, y, and z or return error
        {
            // do stuff with input
        }
        else
        { //something did not read in correctly. Bad line
            cerr << "invalid input"<< endl; // notify user and abort
            return -1;
        }
    }
}

One unsolicited change is this checks all input for validity. OP's cut and all answers so far will silently fail if the input does not conform. This must have two names on the first line and three integers on the second. Anything else should trigger invalid input error message and premature exit. I say should because I haven't actually tested this.

user4581301
  • 33,082
  • 7
  • 33
  • 54