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!
Related
I have this code:
string a = "D:\\Users\\user-pc\\Desktop\\testing\\a.txt";
ifstream f;
/*edit*/ string line;
/*edit*/ getline(f, line);
f.open(a);
if ( f.eof() )
cout << "ended";
else
cout << "nope"
and the file 'a.txt' which has nothing in it.
the output is nope, alway nope. I don't get it.. Do I use it wrong?
EDIT: still .eof() not working
std::basic_istream<...>::eof() only returns true if a recent extraction set the appropriate bit in the stream state. When a file stream is constructed, its stream state is always that of std::ios_base::goodbit.
An alternative is to check if the next available character is the EOF character:
if (f.peek() == std::char_traits<char>::eof())
eofbit error state flag is only set once a read tries to read past the end of the file.
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
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.
Ok so this is killing me at the moment cause its such a simple part of my program that just doesn't want to work. I'm reading data from a textfile to use in a GA.
The first getline() works perfectly, but the second one doesn't want to write any data into my string. When i cout the string it doesn't show anything.
Here is the code:
ifstream inFile;
inFile.open(fname.c_str());
char pop[20], mut[20];
inFile.getline(pop,20);
cout << pop;
inFile.getline(mut,20);
cout << mut; //this outputs nothing
Thanks for any help in advance.
A sample form my file:
there is no line between them mutation is the line straight after population
Population size: 30
Mutation: 20
Your file's first line is 20 characters long (19+new line) but pop[20] can only contain 19 (because the last one is reserved for the null terminator '\0').
When istream::getline stops because it has extracted 20-1 characters, it doesn't discard the new line delimiter (because it was never read). So the next getline just reads the end of the first line, discarding the new line.
That's why you get nothing in the second string.
Your problem is that the length of your input line exceeds the length of the buffer which must hold it.
The solution is to not use character arrays. This is C++, use std::string!
std::ifstream inFile;
inFile.open(fname.c_str());
std::string pop;
std::getline(inFile, pop);
cout << pop << "\n";
std::string mut;
std::getline(inFile, mut);
cout << mut << "\n";
I think you need to find out what the problem is. Add error checking code to your getline calls, refactor the (simple) code into a (simple) function, with a (simple) unittest. Possibly, your second line is longer than the assumed 20 characters (null-term included!).
For an idea of what I mean, take a look at this snippet.
try something like
while (getline(in,line,'\n')){
//do something with line
}
or try something like
string text;
string temp;
ifstream file;
file.open ("test_text.txt");
while (!file.eof())
{
getline (file, temp);
text.append (temp); // Added this line
}
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;
}