Using getline() doesn't return the entire line from a text file

I am trying to use getline() to simply read each line from a text file, but getline() isn't returning the full contents of the line.

I did read through the tutorial on this site that covered performing this simple operation, and I had no problems when proceeding through that tutorial examples.

Here is the text file that I am trying to read from:
Abbottsburg
o34078e6.tif
http://www.archive.org/download/usgs_drg_nc_34078_e6/o34078e6.tif

Acme
o34078c2.tif
http://www.archive.org/download/usgs_drg_nc_34078_c2/o34078c2.tif



But this is all that gets output when I try to read from it:
Abbottsburg
e6.tif
//www.archive.org/download/usgs_drg_nc_34078_e6/o34078e6.tif
me
4078c2.tif
ttp://www.archive.org/download/usgs_drg_nc_34078_c2/o34078c2.tif



This is the code that I am using. From the original code, have include a few debug items that didn't really help me to figure things out:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
char * MasterList = "OutputFile.txt";

int main ()
     string * MasterListLines;
     ifstream MasterListStream (MasterList);

     string TempString;
     int NumberOfLines = 0;

     if (MasterListStream.is_open())
     {
       while (! MasterListStream.eof())
                   {
                    getline (MasterListStream, TempString);
                    ++NumberOfLines;

                   /*  This lists the current line number, then the line from the text file that was just read, then the current position of the stream pointer. */
                    cout << "Line Number: " << NumberOfLines << endl;
                    cout << TempString << endl;
                    cout << "Now at pos: " << MasterListStream.tellg() << endl << endl;
                     }
     }
     else cout << "Unable to open file";

   return 0;
}



With the included debug items, this was the full printed output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
C:\Documents and Settings\HP_Administrator\Desktop\C++ Map Renamer>"Map Renamer.
exe"
Line Number: 1
Abbottsburg
Now at pos: 19

Line Number: 2
e6.tif
Now at pos: 32

Line Number: 3
//www.archive.org/download/usgs_drg_nc_34078_e6/o34078e6.tif
Now at pos: 98

Line Number: 4
me
Now at pos: 104

Line Number: 5
4078c2.tif
Now at pos: 117

Line Number: 6
ttp://www.archive.org/download/usgs_drg_nc_34078_c2/o34078c2.tif
Now at pos: 183

Line Number: 7

Now at pos: -1



Any ideas as to what I did wrong?
Instead of checking whether MasterListStream.eof(), try checking .good() instead, which will cause it exit on errors. You can then check the failbit or badbit to see what happened.
Ok, so I added some ifs to directly confirm the state of bad or fail. Everything was fine except for a single true failbit at the very end, which I assume is the result of reaching eof.

Everything else is the same as before, with the new if checks in bold:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
char * MasterList = "OutputFile.txt";

int main ()
     string * MasterListLines;
     ifstream MasterListStream (MasterList);

     string TempString;
     int NumberOfLines = 0;

     if (MasterListStream.is_open())
     {
       while (! MasterListStream.eof())
                   {
                    if (MasterListStream.bad() == true)
                           cout << "badbit is true" << endl;
                    else
                         cout << "badbit is false" << endl;
                    if (MasterListStream.fail() == true)
                          cout << "failbit is true" << endl;
                    else
                        cout << "failbit is false" << endl;
                    getline (MasterListStream, TempString);
                    ++NumberOfLines;

                   /*  This lists the current line number, then the line from the text file that was just read, then the current position of the stream pointer. */
                    cout << "Line Number: " << NumberOfLines << endl;
                    cout << TempString << endl;
                    cout << "Now at pos: " << MasterListStream.tellg() << endl << endl;
                     }
                    if (MasterListStream.bad() == true)
                           cout << "badbit is true" << endl;
                    else
                         cout << "badbit is false" << endl;
                    if (MasterListStream.fail() == true)
                          cout << "failbit is true" << endl;
                    else
                        cout << "failbit is false" << endl;
     }
     else cout << "Unable to open file";

   return 0;
}



And this was the resulting printout:

C:\Documents and Settings\HP_Administrator\Desktop\C++ Map Renamer>"Map Renamer.
exe"
badbit is false
failbit is false
Line Number: 1
Abbottsburg
Now at pos: 19

badbit is false
failbit is false
Line Number: 2
e6.tif
Now at pos: 32

badbit is false
failbit is false
Line Number: 3
//www.archive.org/download/usgs_drg_nc_34078_e6/o34078e6.tif
Now at pos: 98

badbit is false
failbit is false
Line Number: 4
me
Now at pos: 104

badbit is false
failbit is false
Line Number: 5
4078c2.tif
Now at pos: 117

badbit is false
failbit is false
Line Number: 6
ttp://www.archive.org/download/usgs_drg_nc_34078_c2/o34078c2.tif
Now at pos: 183

badbit is false
failbit is false
Line Number: 7

Now at pos: -1

badbit is false
failbit is true



Any other ideas?
Last edited on
I used the first code you posted and it works fine.
I have the following output:
Line Number: 1
Abbottsburg
Now at pos: 13

Line Number: 2
o34078e6.tif
Now at pos: 27

Line Number: 3
http://www.archive.org/download/usgs_drg_nc_34078_e6/o34078e6.tif
Now at pos: 94

Line Number: 4

Now at pos: 96

Line Number: 5
Acme
Now at pos: 102

Line Number: 6
o34078c2.tif
Now at pos: 116

Line Number: 7
http://www.archive.org/download/usgs_drg_nc_34078_c2/o34078c2.tif
Now at pos: 181


Make sure you open the bracket after the int main() because you don't in both programs...
I can't figure this out either...
The problem seems to be that the first getline() is reading too far since after you call it the first time the position is 19 when it should be about 10. I tried using the ifstream::getline() instead but had the same problem..
Weird - I took out the debug line with the tellg() and it works fine.
Do you have the opening bracket after the int main() ???

I used the Visual Studio and had errors because of that, but despites that it should work fine...
When I copied it, the bracket was missing but I added it (wouldn't compile otherwise). The program did not work - it was having the same problem that the OP had. Once I removed the tellg() line it works, which is strange because tellg() shouldn't alter the stream at all.
Try to open it with the binary flag on
ifstream MasterListStream (MasterList, ios::binary);
Do you have the opening bracket after the int main() ???

Yes, I do. Sorry about that. I pasted that code from a larger block that had a bunch of commented out stuff. I was trying to trim the irrelevant stuff to make it more readable, and I missed the inclusion of that one bracket.

I found that by opening this text file with ios::binary it reads everything just fine. I guess that there is some kind of format conflict somewhere with reading streams in text mode.

I'm using Windows Xp, SP3, and I'm compiling with Dev-C++ 4.9.9.2 . The text file was created in the same manner and in the same format as the text files that I used when I was going through this site's tutorials, and I have never seen this problem before now.

I guess I'll just have to stick to opening files in binary mode.
It is a known bug with GCC. You cannot use ::getline() and tellg() together. (I suspect it is because the getline() function tries to be sneaky and reads a whole bunch of characters at once instead of one at a time...) In any case, it is one of those things still broken with GCC.

The answer is: don't use tellg() with ::getline(). (Sorry.)

I would, however, like to point out a couple of things that need improvement.

1. Don't use char * to address static (immutable) data.
const char* MasterList = "OutputFile.txt";

2. Lines 15 and 17. Don't use .eof() to terminate a file-read loop. If something goes wrong, you'll get an infinite loop. There is no reason to separate everything. Use .good() instead (either explicitly or implicitly) and check why the loop terminated after it terminates.
1
2
3
4
while (MasterListStream)  // implicit
  {
  ...
  }
or
1
2
3
4
while (MasterListStream.good())  // explicit
  {
  ...
  }


3. You aren't saving yourself any memory to use a string * over a plain old string. More on this in your other thread.

Hope this helps.
It is a known bug with GCC. You cannot use ::getline() and tellg() together. (I suspect it is because the getline() function tries to be sneaky and reads a whole bunch of characters at once instead of one at a time...) In any case, it is one of those things still broken with GCC.

The answer is: don't use tellg() with ::getline(). (Sorry.)

AHA! SO I'M NOT CRAZY! lol Thanks

Well this kind of sucks. The reason that I switched over to GCC was that OpenWatcom was buggy. Are there are other more stable, free compilers that are out there?

2. Lines 15 and 17. Don't use .eof() to terminate a file-read loop. If something goes wrong, you'll get an infinite loop. There is no reason to separate everything. Use .good() instead (either explicitly or implicitly) and check why the loop terminated after it terminates.

Yeah, I will do that from now on. I just started by using that because that is what was used in the example codes in this site's tutorial.


3. You aren't saving yourself any memory to use a string * over a plain old string. More on this in your other thread.

I wasn't trying to save any memory, I just thought that I had to do things that way in order to create the dynamic memory that I needed to read in x number of lines into a string array whose size would be determined by the size of the document.

I'll get to my other thread in a minute. It's dinner time now.
Crazy is as crazy does. :-P

I like Edgar Allan Poe's stuff:
I'm not mad! I... I'll PROVE it! Listen. No really, listen! I'M NOT MAD! AAAAHHHH!

XD

Are there are other more stable, free compilers that are out there?

The GCC is one of the best compilers out there. Don't switch for just a single bug. (I dislike Watcom for the same reason.)

Stroustrup likes Microsoft's C++ compiler suite.

Borland's compiler is also top-notch.

Comeau's compiler is campaigned as the best there is, but it costs $$. (But it is very cheap, considering, and worth the $$.)

I just thought that I had to do things that way...

I figured that was the case.

Yeah, the neat thing about the STL containers is that they can be resized freely.

There are some caveats:
std::string doesn't ever shrink (you have to destruct and create a new).
std::vector is always contiguous (a wonderful array layout), but this can bite you for large data in terms of space and time.
std::deque solves those problems, but it cannot be treated as a C array.
etc.
So you've got to use the right container for the right job.

I'm off to eat now too. Enjoy your dinner!
Yeah, I used Watcom for about a day. I was trying to do the simple Hello World! tutorial on this site, but I kept getting compile errors every time. Eventually, I posted a question about it to the Watcom newsgroup, and the response was:
Open Watcom's standard template library is a work in progress and is
currently incomplete. Specifically the IOStreams operators for strings
have not yet been implemented.

After hearing that even basic string functionality hadn't even been implemented by year 2008, I figured I would save myself a lot of future headache by looking for a different compiler.

The ironic thing is that I thought Watcom would be more "up to spec" considering that it had been recently updated, and I had originally decided not to go with Dev-C++ because it hadn't been updated since 2005. lol

I was going to download the MS package at one time, but after seeing that it would be several hundred megabytes vs the 9Mb of Dev-C++ , I decided to go with the one that I would actually be able to download and use in the same day, considering my dailup connection. lol

I might spend some $ on one after I get comfortable with C++ a little more. I just don't want to spend money on something that I might end up sucking at and never want to do again. lol

Thanks again!
Topic archived. No new replies allowed.