3

I am reading a file like this:

char string[256];

std::ifstream file( "file.txt" ); // open the level file.

if ( ! file ) // check if the file loaded fine.
{
    // error
}

while ( file.getline( string, 256, ' ' )  )
{
    // handle input
}

Just for testing purposes, my file is just one line, with a space at the end:

12345 

My code first reads the 12345 successfully. But then instead of the loop ending, it reads another string, which seems to be a return/newline.

I have saved my file both in gedit and in nano. And I have also outputted it with the Linux cat command, and there is no return on the end. So the file should be fine.

Why is my code reading a return/newline?

Thanks.

  • Wont; fix the problem. But use the `getline(std::istream&, std::string&)` found in it takes a stream and std::string. – Martin York Jan 16 '11 at 06:15
  • Are you sure the file does not contain a blank line. Dump it out using a hex editor to be sure. – Martin York Jan 16 '11 at 06:16
  • @Martin regarding your first comment, why would I want to do that? as far as your second comment, I'll try to check. but I outputted the file with the Linux command `cat`, and there was no newline. –  Jan 16 '11 at 06:20
  • Which characters does it specifically read after the string? – tiagovrtr Jan 16 '11 at 06:23
  • @tiagovtr when I output the string it just results in a return/newline –  Jan 16 '11 at 06:26
  • @Martin hmmm... at the end of the file there is a `0A`... could that be the culprate? –  Jan 16 '11 at 06:28
  • @Jay: Use the getline(std::istream&, std::string&) version because the line may not always have a maximum length of 256. It pays to think forward. – Martin York Jan 16 '11 at 06:34
  • @Jay: Yes. The 0A may be the culprit. But It depends on the preceding characters. The file is short dump all the hex values. If you don;t have the appropriate tools I have posted code below to help. – Martin York Jan 16 '11 at 06:35
  • @Martin `31 32 33 34 35 20 0A` –  Jan 16 '11 at 06:51
  • @Jay: That looks good. I have another sample below. – Martin York Jan 16 '11 at 06:56
  • @Martin yeah, that was from a GUI program. see my comment on your answer for what other programs outputted. –  Jan 16 '11 at 07:01

4 Answers4

4

First leets make sure your input file is good:

Run the following command and let us know the output:

#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
#include <fstream>>
#include <iomanip>
#include <algorithm>

int main()
{
    std::ifstream file("file.txt");
    std::cout << std::hex;

    std::copy(std::istreambuf_iterator<char>(file),
              std::istreambuf_iterator<char>(),

              std::ostream_iterator<int>(std::cout, " ")); 
}

Edit:

The output was 31 32 33 34 35 20 0A

Try running this code and see what the output is:

#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
#include <fstream>>
#include <iomanip>
#include <algorithm>

int main()
{
    std::ofstream file("file.txt");
    file << "12345 \n";
}

Dump the output of this file and compare it to the original.
The problem is that different platforms have different line termination sequences. I just want to verify that '0x0A' is the line termination sequence for your platform. Note the line termination sequence is converted into a '\n' when a file is read in text mode and when you output '\n' to a file in text mode it is converted to the line termination sequence.

Edit 2

So I have the file: file.txt

> od -ta -tx1 file.txt
0000000    1   2   3   4   5  sp  nl                                    
           31  32  33  34  35  20  0a                                    
0000007

So the file contains 1 line terminated with 0x0A

Using this program:

#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
#include <fstream>>
#include <iomanip>
#include <algorithm>

int main()
{
    std::ifstream   file("file.txt");

    std::string line;
    while(std::getline(file,line))
    {
        std::cout << "Line(" << line << ")\n";
    }
}

I get:

> g++ t.cpp
> ./a.out
Line(12345 )
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • @Jay: Or run `hexdump` or `od` or `xxd`, if you have any of them on your system. – ephemient Jan 16 '11 at 06:43
  • If you have the tools then use them. This is just provided because I assume you are on Windows with no accesses to these tools. – Martin York Jan 16 '11 at 06:48
  • I'm on Linux... `hexdump`: "0000000 3231 3433 2035 000a 0000007" ; `od`: "0000000 031061 032063 020065 000012 0000007" ; `xxd`: "0000000: 3132 3334 3520 0a 12345 ." my comment on the OP was what a GUI program gave me. –  Jan 16 '11 at 06:56
  • @martin I dumped the output of the file resulting from your new code, and it was the same: `31 32 33 34 35 20 0A`. so it seems my file is bad, correct? –  Jan 16 '11 at 07:05
  • @Jay: If the output from the file is the same then the input is good. – Martin York Jan 16 '11 at 08:11
  • @Martin wait, I'm confused. what we have figured out here is that my original file /did/ have a return/newline at the end, and that was what was causing the problem, right? –  Jan 16 '11 at 20:53
  • @Jay: I am confused as well. Your original code should work with the input file you provided. My last update shows that the file you use with the standard getline() will read the one and only line in the file. There si something else going on in your code. Probably under the bit /* handle input */. But I can not reproduce your problem with the info we have. – Martin York Jan 16 '11 at 21:07
  • @Martin I am using the `getline` method to read until a space, not a `\n`. so my problem apparently is that that it is reading a `\n` at the end of the file. is there a way to have my file /not/ have `\n` at the end, or is it required? and if it is, how do I get my code not to read it? –  Jan 16 '11 at 21:41
  • @Jay: OK. Now I see what is happening. Yes it is quite possable to have a file that does not have the line termination sequence it it. Unfortunately most tools (especially editors) are going to add one automatically. But if you remove the `0x0A` then your code should work. – Martin York Jan 16 '11 at 23:31
2

it is working...

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

ifstream file("file.txt");

int main()
{
   string tmp="",st="";

   while (!file.eof())
    {
      file>>tmp;  
      if (tmp != "") st+=tmp;
      tmp="";  
    }
   cout<<st<<endl; 

   return 0;
}

input file.txt : 1 2 3 4 5
answer : 12345

Elmi Ahmadov
  • 1,017
  • 5
  • 14
  • 25
  • sorry, it is still irrelevant. –  Jan 16 '11 at 06:15
  • 1
    There is no change here from the OP. except that it is more clunky. I would say this is the standard anti-pattern for reading a file. I am not sure the standard specifies the content of tmp when getline() fails (I could be wrong). – Martin York Jan 16 '11 at 06:38
0

Try this way:

while ( !file.eof()  )
{
    file.getline( string, 256, ' ' );
        // handle input
}
Rostyslav Dzinko
  • 39,424
  • 5
  • 49
  • 62
tiagovrtr
  • 162
  • 3
  • 15
  • @tiagovtr yeah, that was what I was doing originally. it didn't work. and the code in the OP is better anyway: http://stackoverflow.com/questions/3511110/unexpected-behaviour-of-getline-with-ifstream/3511291#3511291 –  Jan 16 '11 at 06:18
  • No. The eof() is not true until after you try an read past it. So you may have read the whole file and still enter the loop. At which point you do the getline() and it fails. Then you are `handling input` when string is not correct. – Martin York Jan 16 '11 at 06:40
  • @Martin your comment is directed at @tiagovtr's answer, right? –  Jan 16 '11 at 07:08
  • @Jay: Yes. This comment is for this answer. – Martin York Jan 16 '11 at 08:00
0

It's old, but there does not seem to be proper resolution for this.

I'm surprised that no one has noticed that he's using space delimiter. Due to that the whole line won't be read, but only upto the first space. Thus getline will still have more data to read before encountering EOF.

So the next getline will read newline and return the same as the delimiter is . If the getline call were like this:

file.getline(string, 256)

it'll not return newline and will finish in one step.

SRK
  • 53
  • 4
  • The first comment for this question suggests the same solution so maybe this answer could be formulated constructively for new readers so they can easily apply this solution. The question have an accepted answer so this will not be the first answer people will read if it doesn't get upvotes. – Daniel Persson Mar 19 '20 at 05:42