Item at end of text file being read twice [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)
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.

Related

How to read just before EOF from a file and put it into a string? [duplicate]

This question already has answers here:
How do I read an entire file into a std::string in C++?
(23 answers)
Closed 3 years ago.
My function reads a file and puts it into a string in order for me to process it. I need to read just before EOF, obviously. The problem is that the EOF character is also put inside the string and I can't find a way to bypass it, since it leds other parts of the program to fail. I link the function below.
string name_to_open, ret = string();
ifstream in;
getline(cin, name_to_open);
in.open(name_to_open.c_str());
if (!in.is_open()) {
cout << "Error." << endl;
return string();
}
else {
ret += in.get();
while (in.good()) {
ret += in.get();
};
};
in.close();
return ret;
The function reads fine until the end of the file, then appends EOF and \0. How can I solve the problem? Does the EOF character work fine in controls? I also tried to put a line ret[ret.size() - 1] = '\0'; at the end of the cycle, but this doesn't seem to work either.
ret += in.get(); appends the character read from the tile to the string whether the value read was good or not. You need to 1) read, 2) test that the read is valid and the value read is safe to use, 3) use the value read. Currently your code reads, uses, and then tests whether or not the value read was safe to use.
Possible solution:
int temp;
while ((temp = in.get()) != EOF) // read and test. Enter if not EOF
{
ret += static_cast<char>(temp); // add the character
};
Note: get returns an int, not a char. This is to be able to insert out-of-band codes such as EOF without colliding with an existing valid character. Immediately treating the return value as a char could result in bugs because a special code may be mishandled.
Note: there are many better ways to read an entire file into a string: How do I read an entire file into a std::string in C++?

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.

Is `eof`` a valid state of `ifstream`? [duplicate]

This question already has answers here:
What's preferred pattern for reading lines from a file in C++?
(5 answers)
Closed 9 years ago.
The code is:
ifstream fin("D://abc.txt", ios::in);
string line;
while ( fin ) {
getline( fin, line );
cout << line << endl;
}
The text file is:
hi, I am Eric!
hi, I am Jack!
And the output is
hi, I am Eric!
hi, I am Jack!
hi, I am Jack!
And when I change the condition to !fin.eof(), output is correct. Is eof a valid state of ifstream ?
It's because the state is not changed until after the std::getline function fails. This means that you read the first two lines correctly, but then the state isn't changed so you enter the loop again, but now the std::getline call fails but you don't check for it, and it's also now that the eof flag is set.
You should do e.g.
while (std::getline(...))
{
// ...
}
The eof state is only reached once you try reading past the end of the stream. The getline call that reads the last line from your file does not do so (it reads up until the newline). But the getline call in the next iteration of the loop will reach the end of the file.
A better way to read every line in the file is :
while (getline(fin, line)) {
cout << line << endl;
}
The usage
while(fin)
is not good. it will check the value of fin, not whether fin reaches the end.
you may check this page:
http://www.cplusplus.com/reference/string/string/getline/
when you finish the second call of function getline, the pointer fin not point to NULL, so you go into the third process in while, the third time you call
getline(fin,line);
it meet the eof of fin, so fin change state, then you won't go to the forth call, but since you didn't clear the value of
line
so it will also print
hi, I am Jack!

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

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.