Read and Write from File in C++

Hello,

I wrote a simple program. I have three rows and columns.
When I want to read from a file, the program read four rows instead of three rows.

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

#include<iostream>
#include<sstream>
#include<fstream>
#include<iomanip>


using namespace std;

int main()
{
	ofstream myfile;
	myfile.open("example1.txt");

	int a, b, c;

	for (int j = 0; j < 3; j++)
	{
		cin >> a >> b >> c;
		myfile << a;
		myfile << " " << b;
		myfile << " " << c << endl;
	}

	myfile.close();




	return 0;
}



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
#include<iostream>
#include<sstream>
#include<fstream>
#include<iomanip>


using namespace std;

int main()
{
	int grade1[3];
	int grade2[3];
	int grade3[3];

	ifstream infile;
	infile.open("example1.txt");
	int num = 0;
	float sum = 0;

	while (!infile.eof())
	{
		infile >> grade1[num]; 
		infile >> grade2[num]; 
		infile >> grade3[num];

		sum += grade1[num] + grade2[num] + grade3[num];
		++num;

	}
	cout << "The Average is: " << sum / 9 << endl;


	infile.close();

	return 0;
}
Your code looks okay. Could you post your input file?
Thank you for your reply,

File:
10 20 30
40 50 60
70 80 90

The Average is: 1.90887e+08
I overlooked a logical error at your program. We need to test if ifile fails on reading the content. So this will fix the error:

1
2
3
4
while( infile >> grade1[num] >> grade2[num] >> grade3[num] )
{
   //...
}

The reading will now terminate after trying to read after EOF and infile returns false in this case.
Last edited on
Thank you for your answer,
Could you please explain why was my code wrong?

It's because EOF will read AFTER the last valid input. So after you would have read your last line, the stream is still okay, so the while loop processes another round.
This means, the EOF will get read when you trying to read the next value after your last valid value.
Hello Shervan360,

To look at this differently.

1
2
3
4
5
6
7
8
9
10
while (!infile.eof())
{
    infile >> grade1[num];
    infile >> grade2[num];
    infile >> grade3[num];

    sum += grade1[num] + grade2[num] + grade3[num];

    ++num;
}

Your while condition evaluates to true so you enter the loop.

The first thing you do is make 3 reads from the file. BTW infile >> grade1[num] >> grade2[num] >> grade3[num]; works just as well with less work.

Process what you have read ending up back at the while condition that still evaluates to true.

This time when you enter the loop and it reads the file there is nothing left to read and it sets the "eof" bit on the stream leaving the stream unable to read anything.

If you look closely you should find that "num" has a value of 3 this time thus putting what you could not read past the end of the array. Not what you want.

Possible solutions are:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
infile >> grade1[num];
infile >> grade2[num];
infile >> grade3[num];

while (!infile.eof())
{
    sum += grade1[num] + grade2[num] + grade3[num];

    ++num;

    infile >> grade1[num];
    infile >> grade2[num];
    infile >> grade3[num];
}


Or
1
2
3
4
5
6
7
8
9
while (!infile.eof())
{
    if (infile >> grade1[num] >> grade2[num] >> grade3[num])
    {
        sum += grade1[num] + grade2[num] + grade3[num];

        ++num;
    }
}

I would say that nuderobmonkey's example is the more preferred way to read a file of unknown length. Although I would add while(num < MAXSIZE && infile >> grade1[num] >> grade2[num] >> grade3[num])
At the beginning of "main" I would define "MAXSIZE" as constexpr int MAXSIZE{ 3 };. Then you could use:
1
2
3
4
5
6
7
int main()
{
        constexpr int MAXSIZE{ 3 };

	int grade1[MAXSIZE];
	int grade2[MAXSIZE];
	int grade3[MAXSIZE];

This way if you need to change the size you only have 1 place to make the change.

When you open a file stream for input or output ALWAYS check that it is open. I tend to use this to check:
1
2
3
4
5
6
if (!inFile)
{
	std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
	
	return 1;
}

"std::quoted" is from the <iomanip> header file, which you do include.

Andy

Edit: typo.
Last edited on
Hello Shervan360,

I started working on your program and have a question:

Given your input file:

10 20 30
40 50 60
70 80 90


Does each row mean 1 students' grades or is it each column?

You defined:
1
2
3
int grade1[MAXSIZE];
int grade2[MAXSIZE];
int grade3[MAXSIZE];

I am thinking what you want is: int grades[MAXROWS][MAXCOLS]{};. Where each row is 1 students' grades.

As it is with 3 rows of 3 the while loop is not working the way I believe you want it to.

Andy
Thank you so much @Handy Andy and @nuderobmonkey
Hello Shervan360,

If you have the time post your new code. If you are satisfied no worries.

Andy
Topic archived. No new replies allowed.