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

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.

Related

How to efficiently read the last line of file in c++ [duplicate]

This question already has answers here:
c++ fastest way to read only last line of text file?
(7 answers)
Closed 5 years ago.
I need to read the last line of file that is growing while some calculations are made. At the beginning there is no problem because the file is small, but when the file gets bigger the reading process is to slow.
while(!file.eof()){
if ((std::getline(file,line))){
std::istringstream iss(line);
std::istream_iterator<double> it(iss), end;
std::vector<double> v(it, end);
std::copy(v.begin(), v.end(), arr);
v.clear();
line.clear();
}
}
What is a more efficient way to read the last line of a file with out reading all the file until the end is reach?
use seekg() to jump to the end of file, and read backward - something like this
if(fs.is_open())
{
fs.seekg(-1, std::ios_base::end);
if(fs.peek() == '\n')
{
fs.seekg(-1, std::ios_base::cur);
int i = fs.tellg();
for(i;i > 0; i--)
{
if(fs.peek() == '\n')
{
//Found
fs.get();
break;
}
fs.seekg(i, std::ios_base::beg);
}
}
std::string lastline;
getline(fs, lastline);
Use this algorithm:
Seek until the end of the file.
Copy in reverse until newline is reached (skip the newline if file ends in it). EDIT: This step is actually a bit tricky with streams. Memory mapping would make this easier, however keep in mind that there is no standard API for memory mapping.
The copy is now the last line in reverse.
You could just reverse search for the newline and copy in forward direction, or just reverse the inverted line, or you could copy into the front of a double ended queue so that the line is reversed while copying, but perhaps fastest might be to keep it reversed and process it with reverse iterators, depending on what you intend to do with the line.

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

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.

Output to console overlaps [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reading from text file until EOF repeats last line
The cout output from my c++ program, prints to console but overlaps.
For instance:
while(pFile.good()){
getline (pFile, pLine);
cout<<pLine;
}
This code, prints the last line, and some leftovers of the previous line.
I'm using vi on cygwin. This happened out of the blue. Did I change some setting?
getline() discards any newline character it encounters. To keep your code from merging all lines together into one big line, you need to do this instead:
cout << pLine << endl;
As chris pointed out, you also should use getline() as your while condition. Otherwise, the stream may be considered "good" now, but reach EOF when you call getline(). So try this loop:
while (getline(pFile, pLine)) {
cout << pLine << endl;
}
The reason your last line is printed twice is because your last call to getline() failed, but you still printed pLine (even though its content is undefined).
while(pFile.good()){
getline (pFile, pLine); // What happens if this line fails.
// Like when you read **past** the end of file.
cout<<pLine;
}
The correct version of your code is:
while(pFile.good()){
if (getline (pFile, pLine))
{ cout<<pLine;
}
}
But this is usually written as:
while(getline (pFile, pLine))
{
// The loop is only entered if the read worked.
cout<<pLine;
}
Remember that the last successful call to getline() reads up-to but not past the end of line. That mean the next call to getline() will fail and set the EOF bit.
Also note that your output is stinging together because you are not adding a '\n' seporator between your lines. Note: the getline() reads upto the next '\n' character but this termination character is not added to the string pLine.
here u are writing at sameline because getline simply discards new line character,thats why u have to write <<endl
while(pFile.good()){
getline (pFile, pLine);
cout<<pLine<<endl;
}