Need help with Fstream - Reading numbers from file, & separating rows

Below is a simple little program I made. I need to read a file with x amount of numbers in a row, and y amount of rows. For each row, I need to output the information, and to find some easy stuff, like average, total, etc. I need to separate this per row, and I also need to find the average, total, n amount, etc. for the entire thing. So far, my main issue is trying to separate the individual rows - I'm guessing that this involves EOF, as well as some kind of nested for loop.

FYI, in the class I'm in, they just barely got into functions, and didn't get into arrays yet. Even though I know both of those pretty well, and even though the teacher would probably let me use them, I'd rather not for the challenge of doing something differently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    int num;
    int count = 0;
    int total = 0;
    int average = 0;

    ifstream fileIn;

    fileIn.open("file.txt");

    if (!fileIn) {

	cout << "nError opening file...Closing program.n";
	fileIn.close();

    } else {

    while (!fileIn.eof()){

	    fileIn >> num;
	    cout << num << " ";
	    total += num;
	    count++;

	    }

    average = total/count;

	cout << "\n\nTotal is " << total << "." << endl;
	cout << "Total amount of numbers is " << count << "." << endl;
        cout << "Average is " << average << "." << endl;

	fileIn.close();

	return 0;
    }
}
Last edited on
Using eof() in a while loop like this is wrong:
1
2
3
4
5
    while (!fileIn.eof())
    {
        fileIn >> num;
        // etc.
    }

The problem is, the fileIn >> at line 3 might fail for many different reasons, just one of which is eof. But more importantly, the program goes on to use the result without bothering to check whether the read was successful or not. By the time it gets to check eof() in the while condition, it is already too late.

In the original program, this can lead to processing the last value twice, giving incorrect results, depending upon whether or not there was a newline or any whitespace after the last value in the file.

This is a correct way to handle it:
1
2
3
4
5
6
    while (fileIn >> num)
    {
        cout << num << " ";
        total += num;
        count++;
    }

Notice there is no eof() test here - it is simply not needed, and is best avoided as mentioned above. How does this work? Well, inside the while condition, this fileIn >> num attempts to read a number from the file. If a number was successfully read in, the result tests as true and the body of the loop is executed. If it fails for any reason, say because there is non-numeric data in the file, or because the end of file has been reached, it gives false.

Now on to the other parts of your question. In order to deal with the data on each row separately, the easiest way is to read the entire row into a string, then process the contents of the string. Again, this is made incredibly easy by using a stringstream, which allows a std::string to be treated as if it was a file containing data. A simple example:
1
2
#include <string>
#include <sstream> 

1
2
3
4
5
6
7
8
9
10
    string line;
    while (getline(fileIn, line))
    {
        istringstream ss(line);
        while (ss >> num)
        {
            cout << num << " ";
        }
        cout << endl;
    }

Last edited on
Topic archived. No new replies allowed.