Reading Input File with mixed format

Hello there, I am pretty new to c++.

I am trying to read an input file (.txt) with mixed format. However, I have to ignore some lines, such as those lines with "----------" and "OUT", For an example, the .txt file about scores :

Andy 5 Kaliroy 6
Tom 4 Timmy 3
-------------
Sam 2 Darius 6
Sam OUT
Pat 3 Eddie 4
-------------
Timmy OUT
Vic 3 Connie 1
Duke 0 Jake 0
-------------
Dave 3 Kevin 0
Kevin OUT

In turn, I want to save only the names and scores of both players in the arrays, while ignoring or skipping "-----------" and the line with "OUT". Which means I only want these data without changing the original .txt file:

Andy 5 Kaliroy 6
Tom 4 Timmy 3
Sam 2 Darius 6
Pat 3 Eddie 4
Vic 3 Connie 1
Duke 0 Jake 0
Dave 3 Kevin 0


This is my attempt that compiles with no error, but when I cout the saved arrays, nothing happened.

Note a is a struct.
Both Names are string type. Scores are int type.

1
2
3
4
5
6
7
8
9
10
11
12
  while (!fin.eof()) {
		infileB >> a[i].Name1
                >> a[i].S1
                >> a[i].Name2
                >> a[i].S2;	            		
         if(a[i].Name1 == "-------------") {
                continue;
         }
         else {
         i++
         }
  }


I tried to search for a solution, but cant find any. Thank you!
If a[i].Name1 was the dashes, what do you think got input into the rest of the variables?

Also, never loop on EOF like that. The EOF flag is not set when you read the end of the file; it is only set when you try to perform a read operation and you are at the end of the file. So, the last read operation you perform will leave garbage in your variables.
I would use a getline(); and parse each lines before actually storing them into a structure.
Rather than using infileB >> a[i].Name1
Yes, SeiZa has a good point - generally lin-by-line processing is preferred over token-by-token processing. You would use getline to read into a std::string and then construct a std::istringstream from it to extract tokens after checking that the string wasn't dashes.
@ LB, I guess the rest of a[i] will also be garbage. Yeah , I am pretty lost.

So, something like this?

1
2
3
4
5
6
while (!fin.eof()) {
		getline(infileB, a[i].Name1);
                getline(infileB, a[i].S1);
                getline(a[i].Name2);
                getline(a[i].S2);
}


or should I not use fin.eof at all?

I am not exactly sure how to use std::istringstream. Thx btw
Yes, don't use .eof() at all.

Probably something more like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
std::string line;
while(std::getline(infileB, line)) //while we can read input
{
    if(line != "-------------")
    {
        std::istringstream iss (line);
        std::string name1;
        int score1;
        if(iss >> name1 >> score1) //if we can read name1 and score1
        {
            //we cannot get here if it tried to read "OUT" into score1 - it will fail
            std::string name2;
            int score2;
            iss >> name2 >> score2;
            a[i++] = NameOfYourStruct{name1, score1, name2, score2};
        }
    }
}
I haven't tested it but I think it should work. After the while loop, i-1 is the number of valid elements in your array.
Last edited on
That is ingenious. It makes sense to me, I will try it out right now, and I will let you know how it goes. Thx again btw!!
You should also check the state of your stringstream and clear it at beginning or end of loop... in my opinion.
@Seiza Icic, how do I clear it? I am still fairly new to stringstream

with LB's method, the program was able to compile with no error, but still nothing happened. I think i did something wrong on my part, still checking.

is it fine if I input the value into struct, instead of doing it at the end?

1
2
3
4
if(iss >> a[i].Name1 >> a[i].S1) {
                condition >> a[i].Name2 >> a[i].S2;
                i++;
}
Last edited on
http://www.cplusplus.com/reference/ios/ios/good/

std::stringstream::good() function returns true if the Input/Output of the stream are in their Readable/Writable state. This function should be called after each extraction of a portion of data.

It also returns false when the stream has reached EOF or end of the data in the stream.

example:
1
2
3
4
5
while (iss.good())
{
// recovering data :D
iss >> val;
}


when you want to clear a stringstream... this is the most tricky part:

std::stringstream::str("") clears out the stringstream.

iss.str("") gives an empty stream in iss.
Last edited on
SeiZa: you are confused.
http://stackoverflow.com/q/5837639/1959975
http://stackoverflow.com/q/5605125/1959975
Please don't suggest to do input that way, especially after I just made a post earlier in this thread telling not to do it.

There is no need to clear the stringstream ever.

@hanxdiviner: "nothing happened" is not the same as "there was no output". My code sample didn't output anything ;)
Last edited on
Hah never thought of that. Thanks LB
Topic archived. No new replies allowed.