Function End of file loops extra loop ? C++ [duplicate] - c++

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 9 years ago.
am trying to read characters from file but when I use end of file function it loops more than the number of character inside the file by 1 .. but I don't know why ?
#include <iostream>
#include <fstream>
int main()
{
ifstream file;
char ch1;
file.open("c:\\Downloads\\test.txt" , ios::in);
int i=0;
while(!file.eof())
{ i++;
file>>ch1;
cout<<ch1<<endl;
}
cout <<i<<endl;
file.close();
return 0;
}
file contains
[]
output : [ ] ] 3

Well, when you've read the last character in the file file.eof() is still false, because the stream doesn't yet know that it's reached the end. Only after you attempt to read the already nonexistent character is eof set to true. You should probably do this
char ch;
while(file >> ch)
{
...
}

The reason is because just because you haven't hit the end of the file yet, doesn't mean the next read is going to succeed. Because you are reading characters, the EOF will only be set when you actually attempt to read after the last character.
In fact, even when you are reading strings, integers or other similar things out of a file there is a similar problem. At the end of many text files is an extra \n with no text after it. So when the last line is read, there is still a \n in the stream but EOF has not been set. You then proceed to read the next line which is not there whatever you are extracting into is left with the same contents as before. This results in what appears to be a duplicate reading.

Related

Why input stream object fails after reading file to the end?

Here is the code .
It is giving the EXACT output as shown below means it is reading the file.
But it is also showing fails as you can see it means fin.fails() is true.
I want to know why this is true although i am successful in reading the file.
#include<fstream>
#include<iostream>
using namespace std;
int main()
{ ifstream fin;
fin.open("pro.txt");
char ch;
int data;
while(!fin.eof())//!(fin >> ch).eof()
{
fin.get(ch);
cout<<ch;
if(fin.fail()) {
cout<<"fails";
break;
}
}
fin.clear();
fin.seekg(0);
int pos=(int)fin.tellg();
cout<<"\n this is :"<<pos;
fin.close();
return 0;
}
Output is :
this is my name
fails
this is 0
Contents of pro.txt:
this is my name
Don't know why this is happening!
Still can't find why the fin.fails() is true because i think no one willing to
But i figured out to read white spaces and file without making fin.fails() =true .
just replace the while(!fin.eof()) with while(fin.get(ch)) and remove the fin.get(ch) present in while body -> this was the reason why my output was skipping one character for each read.. this i had mentioned in the comments.
The problem is the following: Reading the last character in your file with get will not set the eofbit, so the call to fin.eof() in your while condition still returns false after you read the last character of the file inside the loop body. Then during the iteration following the read of the last character you try to read another character inside the loop body, even though there is no character to read anymore. This will set the eofbit and the failbit as per specification of get.
TL;DR: Reading over the end of a file is supposed to set the failbit.

Problems with reading text from a file [duplicate]

This question already has answers here:
Read whole ASCII file into C++ std::string [duplicate]
(9 answers)
Closed 9 years ago.
I have this function that reads the text from a file and adds it to a string, now the weird thing is that it works fine if its a short text. But if its a longer text the string becomes empty, any help solving this problem is appreciated.
string inlasning(string namn)
{
string filString, temp;
ifstream filen(namn.c_str());
if(!filen.good())
{
cout << "Otillganglig fil" << endl;
filString = "ERROR";
return filString;
}
else
{
while(!filen.eof())
getline(filen, temp);
filString.append(temp);
}
filen.close();
return filString;
}
1) Don't use eof() to control the loop. Put getline directly into the loop condition. Search StackOverflow if you have problems doing this.
2) Your while loop has no braces and thus only covers the getline line, despite your misleading indentation.
3) getline discards newlines. Your final string will be wrong.
4) The actual behavior you're observing comes from the fact that you only append the very last thing that getline returns to your string. When your file contains one line of text and doesn't end in a newline, this will seem to work. If it has more lines but doesn't end in a newline, you'll only get the last line. If the file does end in a newline, because of your incorrect loop condition the last call to getline will actually give you an empty string, which will be exactly the contents of your string.
Replace
while(!filen.eof())
getline(filen, temp);
filString.append(temp);
with
while(!filen.eof())
{
getline(filen, temp);
filString.append(temp);
}
Use "is_open()" to check if the file exists:
if( ! filen.is_open() ){...} // you don't need an else clause
...And your while loop must has braces or it will only execute the getline(...) instruction:
while( filen.good() ) {
getline( filen , temp );
filString += ( temp + '\n' );
}
If your file doesn't ends with '\n', remove the last char from the string

reading from file to vector- last line gets repeated [duplicate]

This question already has answers here:
Reading from text file until EOF repeats last line [duplicate]
(7 answers)
Testing stream.good() or !stream.eof() reads last line twice [duplicate]
(3 answers)
reading a line in text file twice
(4 answers)
Closed 9 years ago.
I am trying to read values from a file to a vector
std::vector<float> setTimesArray (std::string flName){
int i=0, dummy=0;
float temp;
std::vector<float> pObs;
std::string line;
std::ifstream inFile;
inFile.open(flName.c_str());
if(!inFile){
std::cout<<"\n.obs file not valid. Quitting programme...";
exit(1);
}
while(inFile.good()){
i++;
getline(inFile, line);
if(i>=3){ //I don't want first two lines
std::istringstream in(line);
in>>dummy;//discards first value in the line
in>>temp;
pObs.push_back(temp);
in.str(""); //discards remaining part of the line
}
}
return pObs;
inFile.close();
}
Problem is, the last value gets repeated. For example, flName had total 975 lines. Thus pObs must be having size=973 (975-2 initial lines). But the size is 974 and I see that the last value is repeating. What mistake have I made?
try:
while (getline(inFile,line))
instead of while(inFile.good())
and remove the getline() call from within the method.
You may also want to change your last two lines of codes to this, as per Daniel Kamil Kozar's suggestion:
inFile.close();
return pObs;
After the last line, good() is still allowed to return true. It doesn't have to return false until after a failed read. Thus, if it returns true, and then fails the read, your line variable won't take a new value. The correct solution would probably be to correct the bounds checking, but in this case, moving the declaration of line into the scope of you while loop and checking for and empty string should correct the issue.

Item at end of text file being read twice [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
ifstream not reading EOF character
(4 answers)
Closed 9 years ago.
The text file contains lines formatted like so:
lSdhmhlN 15479 6694.74 O
szUfGnoI 18760 5275.53 n
I'm reading the file line by line, putting its data into buffer variables, storing those variables in a TopicD object, and inserting that object into a binary search tree. Problem is that the last line of the file is being read twice so that two identical TopicD objects are created and inserted into the tree. Why?
Here's my code:
template<class ItemType>
void read( BinarySearchTree<ItemType> & tree )
{
ifstream read( FILE_NAME.c_str() );
if ( read.fail() )
die( "Error opening the file." );
string strbuff;
double dubbuff;
int intbuff;
char chbuff;
while ( !read.eof() )
{
read >> strbuff;
read >> intbuff;
read >> dubbuff;
read >> chbuff;
TopicD buff( strbuff, dubbuff, intbuff, chbuff );
tree.add(buff);
}
read.close();
}
Consider snipping just a bit out of that loop:
while (read >> strbuff >> intbuff >> dubbuff >> chbuff)
tree.add(TopicD( strbuff, dubbuff, intbuff, chbuff ));
Never rely on .eof() to be true when you reach EOF. Rather, it will be true when, among other things, you try to read again once you are there. Therefore your first read after arriving at EOF is failing, but by that time you've stopped checking for errors (which you were never checking to begin with, by the way) and just blindly insert whatever you have in your variables into your tree.

what's wrong here? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is iostream::eof inside a loop condition considered wrong?
i used this code to replace the first " with `` and the second one with ''
everything works just fine except it runs through the loop one more time after the last character is read and that makes the program print another character
#include <fstream>
#include <iostream>
using namespace std ;
void main ()
{
ifstream infile;
infile.open("infile.txt");
ofstream outfile;
outfile.open("outfile.txt");
char c ;
int i = 0 ;
while ( !infile.eof() )
{
infile.get(c)
if (c=='\"')
{
i++ ;
if (i%2==0)
outfile<<"\'\'";
else
outfile<<"``";
}
else
outfile<<c;
}
outfile.close();
infile.close();
}
Don't do while ( !infile.eof() ) - this only checks if the previous read hit the end of the file, not if the next one will. So when the last character is read, it loops round again, sees that it hasn't hit the end of file yet and then proceeds to read another character even though there isn't another character to read. Your c will have the same value from the previous iteration.
Instead, do this:
while (infile.get(c))
{
// ...
}
This will read a character from the file and then, if that was succesful, will do something with that character.