Jump to content

C++ problems with end-of-file

Pachuca
Go to solution Solved by Mr_KoKa,

The way you're reading from file seems to be ok, but the way you're populating arrays seems odd.

You read first line of file, both account id and balance to accountID and accountBalance, and then in a loop you're reading accounts ids from file to arrayA with index of accountID and balances to arrayB of index accountBalance so respectively, arrayA[1] and arrayB[0] (the first line of accounts.txt which you read and written to accountID and accountBalance)

 

So the array is mostly unchanged, you keep ovewriting index 1 of arrayA and index 0 of arrayB.

 

Instead of that you should not read from the file before the loop, so you won't discard any data, and then make yourself another variable where you will keep last index you have written to, set it to 0 and as you  read from file and write to array with index defined by that variable, increase the index variable.

 

So ditch this line:

inf >> accountID >> accountBalance;

and make yourself this one before the loop:

int index = 0;

and then instead of:

inf >> arrayA[accountID];
inf >> arrayB[accountBalance];

do:

inf >> arrayA[index];
inf >> arrayB[index];

And don't forget to add index++ at the end of the loop.

 

And if you want to print the values right away then fix the index for printing too.

accountID and accountBalance seems to be unneeded in this function at all.

 

You can set yourself some constant or pass another argument to your function for the max index of array so you won't go out of bounds.

FYI, file can end between first inf >> and the second one.

 

Also the last empty line will make your app to another loop iteration, as it is not end of file, but there are no more values, it won't succeed to read those, and will insert gibberish to 16th index of arrays, if your arrays are idnexed from 0 - 14 (15 cells) then it will write to somewhere where it shoudl not, and it will destroy some of the data or crash your application.

I'm having some problems with eof not giving me the results I need. Here's my function:

 

void selectBalance(ifstream &inf, int& accountID, int& accountBalance, int arrayA[], int arrayB[]) {
	cout << "Here is the list of accounts and balances:\n";
	cout << setw(5) << "Account Number: " << setw(20) << "Balance: \n";
	inf >> accountID >> accountBalance;
	while (!inf.eof()) {
			inf >> arrayA[accountID];
			inf >> arrayB[accountBalance];
			cout << setw(5) << arrayA[accountID];
			cout << setw(25) << arrayB[accountBalance] << "\n";
	}
}

everything gets passed without a problem and the ifstream is for a text file that holds 2 columns of numbers. One is for account number and another for balance. When I store it in the array for some reason the array doesn't take the first values on the list and if i use inf >> accountID >> accountBalance; in main than the result is the same except the last values show up twice. So for example the arrayA list of account numbers should be 1-10 and it returns 2-10 or 2-10 with 10 being listed twice and arrayB does the same thing. I had this problem before and to resolve it I just added an empty line at the end into the text file, but that doesn't seem to fix it here. Any ideas?

Link to comment
Share on other sites

Link to post
Share on other sites

The way you're reading from file seems to be ok, but the way you're populating arrays seems odd.

You read first line of file, both account id and balance to accountID and accountBalance, and then in a loop you're reading accounts ids from file to arrayA with index of accountID and balances to arrayB of index accountBalance so respectively, arrayA[1] and arrayB[0] (the first line of accounts.txt which you read and written to accountID and accountBalance)

 

So the array is mostly unchanged, you keep ovewriting index 1 of arrayA and index 0 of arrayB.

 

Instead of that you should not read from the file before the loop, so you won't discard any data, and then make yourself another variable where you will keep last index you have written to, set it to 0 and as you  read from file and write to array with index defined by that variable, increase the index variable.

 

So ditch this line:

inf >> accountID >> accountBalance;

and make yourself this one before the loop:

int index = 0;

and then instead of:

inf >> arrayA[accountID];
inf >> arrayB[accountBalance];

do:

inf >> arrayA[index];
inf >> arrayB[index];

And don't forget to add index++ at the end of the loop.

 

And if you want to print the values right away then fix the index for printing too.

accountID and accountBalance seems to be unneeded in this function at all.

 

You can set yourself some constant or pass another argument to your function for the max index of array so you won't go out of bounds.

FYI, file can end between first inf >> and the second one.

 

Also the last empty line will make your app to another loop iteration, as it is not end of file, but there are no more values, it won't succeed to read those, and will insert gibberish to 16th index of arrays, if your arrays are idnexed from 0 - 14 (15 cells) then it will write to somewhere where it shoudl not, and it will destroy some of the data or crash your application.

Link to comment
Share on other sites

Link to post
Share on other sites

4 minutes ago, Mr_KoKa said:

The way you're reading from file seems to be ok, but the way you're populating arrays seems odd.

You read first line of file, both account id and balance to accountID and accountBalance, and then in a loop you're reading accounts ids from file to arrayA with index of accountID and balances to arrayB of index accountBalance so respectively, arrayA[1] and arrayB[0] (the first line of accounts.txt which you read and written to accountID and accountBalance)

 

So the array is mostly unchanged, you keep ovewriting index 1 of arrayA and index 0 of arrayB.

 

Instead of that you should not read from the file before the loop, so you won't discard any data, and then make yourself another variable where you will keep last index you have written to, set it to 0 and as you  read from file and write to array with index defined by that variable, increase the index variable.

 

So ditch this line:


inf >> accountID >> accountBalance;

and make yourself this one before the loop:


int index = 0;

and then instead of:


inf >> arrayA[accountID];
inf >> arrayB[accountBalance];

do:


inf >> arrayA[index];
inf >> arrayB[index];

And if you want to print the values right away then fix the index for printing too.

accountID and accountBalance seems to be unneeded in this function at all.

 

You can set yourself some constant or pass another argument to your function for the max index of array so you won't go out of bounds.

FYI, file can end between first inf >> and the second one.

that fixed it, thanks so much.

Link to comment
Share on other sites

Link to post
Share on other sites

Just be careful as if there is empty line at the end of your accounts file it will try to read it as it is not eof yet. It will fail to read it but will populate your array next index so if your array is made just to fit the data, then it will be written to the memory that is not your array, or that is not owned by your app, which will crash it.

 

You can check if read operation succeeded by checking >> operator result like: 

if(!static_cast<bool>(inf >> arrayA[index])){
  cout << "Read account id operation failed, stopping reading.";
  return;
}

if(!static_cast<bool>(inf >> arrayB[index])){
  cout << "Read balance operation failed, stopping reading.";
  return;
}

 

Link to comment
Share on other sites

Link to post
Share on other sites

On 24.7.2017 at 4:30 AM, Mr_KoKa said:

Just be careful as if there is empty line at the end of your accounts file it will try to read it as it is not eof yet. It will fail to read it but will populate your array next index so if your array is made just to fit the data, then it will be written to the memory that is not your array, or that is not owned by your app, which will crash it.

 

You can check if read operation succeeded by checking >> operator result like: 


if(!static_cast<bool>(inf >> arrayA[index])){
  cout << "Read account id operation failed, stopping reading.";
  return;
}

if(!static_cast<bool>(inf >> arrayB[index])){
  cout << "Read balance operation failed, stopping reading.";
  return;
}

 

std::ios, the base class for io streams, has a overload for operator bool (operator void*() pre C++11) that evaluates the stream. Thus, the ugly static_cast is not necessary...

 

if(!(inf >> arrayA[index]){

...Should work just as well and is the canonical way.

Link to comment
Share on other sites

Link to post
Share on other sites

I ended up splitting the argument into different functions to simplify this part. This is my code now and it works great. Reads the data in my input file than I can reference it into double arrays to use in main. 

 

int readData(ifstream &in, int arrayAcc[], float arrayBal[]) {
	int index = 0;

	in >> fixed >> showpoint >> setprecision(2);
	while (!in.eof()) {
		in >> arrayAcc[index];
		in >> arrayBal[index];
		//for testing - cout << arrayAcc[index] << "\t" << arrayBal[index] << endl;
		index++;
	}
	return index;
}

 

Link to comment
Share on other sites

Link to post
Share on other sites

8 hours ago, Pachuca said:

I ended up splitting the argument into different functions to simplify this part. This is my code now and it works great. Reads the data in my input file than I can reference it into double arrays to use in main. 

 


int readData(ifstream &in, int arrayAcc[], float arrayBal[]) {
	int index = 0;

	in >> fixed >> showpoint >> setprecision(2);
	while (!in.eof()) {
		in >> arrayAcc[index];
		in >> arrayBal[index];
		//for testing - cout << arrayAcc[index] << "\t" << arrayBal[index] << endl;
		index++;
	}
	return index;
}

 

That code still suffers the eof bug and will read 1 bogus record at the end of the file. The while loop will only end after eof has been set by a failed read, but by then you already stored the (bogus, because the read failed) values and increased your index.

 

Try this:

while (in >> arrayAcc[index] >> arrayBal[index]) {
		//for testing - cout << arrayAcc[index] << "\t" << arrayBal[index] << endl;
		index++;
	}

This will break the loop when a read fails and prevent the index from being incremented at that point.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×