1

I think I should begin by saying that I've just installed linux(debian) in my pc and have zero foreknowledge about doing things in linux. This problem is probably due to some really simple thing.

The relevant part of the code is similar to this:

ifstream stockNames("names.txt");

    while (!stockNames.eof())
    {
        string snline;
        getline(stockNames,snline);
        cout << snline << endl;
        .
        .
        .
    }

this should print the first line of the file 'names.txt'. Instead it prints an empty line. And when I try to use snline as an input in another function I get the error 'Segmentation Fault'. How should I modify my code to do this? Is there any difference in usage of the ifstream in linux? Cause in windows the code works just fine


I've written the simple code below

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

using namespace std;

int main(int argc, const char *argv[])
{
    string dos = "names.txt";
    ifstream stockNames(dos.c_str() );

    string snline;
    while (getline(stockNames,snline))
    {
       cout << snline << " ";

    }
    return 0;
}

content of names.txt is

ABC

DEFG

HBO

instead of showing those line, cout << snline produces nothing


One more update: I've written two more codes.

(1)

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

using namespace std;

int main(int argc, const char *argv[])
{
    cout << "program has initiated" << endl;

    ifstream stockNames("names.txt");

    if( !stockNames )
        cout << "unable to open" << endl;

    string snline;
    while (getline(stockNames,snline))
    {
        cout << snline << endl;

    }
    return 0;
}

Result is as I desired. First 'program has initiated', then ABC, DEFG, HBO in different lines. But when I change this part

        cout << snline << endl;

as

        cout << snline << " hey" << endl;

Then ABC DEFG HBO does not appear and instead the only output is " hey".

This is crazy, how can this be??

btw I tried to make a debug with ddd and when I check the variable snline, ddd prints the following line (gdb) print snline $2 = {static npos = 4294967295, _M_dataplus = {> = {<__gnu_cxx::new_allocator> = {}, }, _M_p = 0x804c1a4 "ABC\r"}}

new mini update: when I change the relevant line as "cout << snline << " " << endl;" what's printed out is ' BC' ' FGH' ' BO' in seperate lines. Why does << operator overwrites over snline??

aristos
  • 21
  • 1
  • 7

5 Answers5

3

First of all, your while loop is wrong, because the eof flag (or any other failure flag) is set after an attempt to read from the stream fails; that means, if the attempt to read fails using getline(), the loop doesn't immediately exit, instead the loop continues which is a serious bug with your code.

So write your loop as (an idiomatic way):

string snline;
while (getline(stockNames,snline))
{
    cout << snline;
    //..
}

std::getline returns istream&, which can be implicitly converted into boolean type. So if getline reads successfully, then the returned value converts to true and the loop will continue, or else it will convert to false and the loop will exit.


After the edit in your question, all I can say that you need to check the stream object before using it to read contents from the file. More specifically, you need to check if the stream has been initialized properly and it has indeed opened the input file (i.e names.txt), and is ready to read data from it.

So try doing this:

//...
ifstream stockNames(dos.c_str() );
if (!stockNames) 
{
     cout << "file couldn't open properly" << endl;
     return 0;
}
string snline;
while (getline(stockNames,snline))
{
   cout << snline << " ";
}

Now run this, and see what it prints.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

stockNames will not actually appear to reach "end of file" until it has tried to input something and received the EOF character. Therefore, you're going to want to re-write your loop as follows:

ifstream stockNames("names.txt");

string snline;
getline(stockNames,snline);

while (!stockNames.eof())
{
    cout << snline << endl;
    .
    .
    .
    getline(stockNames,snline);
}

or much simply

ifstream stockNames("names.txt");

string snline;
while (getline(stockNames, snline))
{
    cout << snline << endl;
    .
    .
    .
}
Andrew Rasmussen
  • 14,912
  • 10
  • 45
  • 81
  • I've made the modifications but the problem still stands. snline prints empty. – aristos Aug 03 '11 at 19:14
  • Can you verify that you are actually picking up the file you think you are? Are you sure it's getting names.txt? – Andrew Rasmussen Aug 03 '11 at 19:54
  • yes, if you could check the new update that i made in the thread, I've added a line to check if the file is opened successfully. There is something very weird as you can see in the update that i mentioned – aristos Aug 03 '11 at 20:04
1

To answer your question; no, there is no significant difference in how ifstream operates on Linux and Windows. Of course if you write bugged code (as the other two answers have pointed out) then you might run into problems, but I can't see how the eof bug would cause the problems you are describing.

I would concentrate on the part where you say that using snline causes a segmentation fault, that indicates a more serious issue. Could you post code that demonstrates that?

john
  • 46
  • 1
  • I think the seg fault is due to the empty input snline. I've written a simple code to show what's in the file names.txt but it doesn't work – aristos Aug 03 '11 at 19:24
  • Well, I'm sure it's caused by a bug in your code, one that you got away with on Windows but not on Linux. If you post a complete program I'm sure it will get fixed pretty soon. Until then it will be a mystery. – john Aug 03 '11 at 19:29
  • @aristos edit your question with the complete code, please do not link us to some other website. – Sam Miller Aug 03 '11 at 19:32
1

You have a dos file which uses \r\n at the end of each line. Linux doesn't recognise \r as part of the line ending so it gets included in the snline string. \r causes the next thing printed to appear at the beginning of the line so " hey" overwrites the stock names you were expecting to see.

Try

cout << snline << " " << endl;

and you'll see what I mean

john
  • 46
  • 1
  • Exactly that's it! What should I do to keep the stock names unchanged? – aristos Aug 03 '11 at 20:19
  • 1
    Either convert the file to Linux/Unix line endings, or manually remove the \r at the end of snline. Also it would be nice if you gave my answer a tick :) – john Aug 03 '11 at 20:22
  • All the ticks in the world john. Thank you so much =) – aristos Aug 03 '11 at 20:24
0

You aren't checking whether the stream opened properly.

std::ifstream stockNames("names.txt");
if (! stockNames) {
    std::cerr << "Unable to open file 'names.tex'\n";
}
else {
   // Do the rest of your stuff here.
}

Always check status. Don't just plow ahead and assume everything is OK.

BTW, using namespace std; is something you see in a lot of bad books that are trying to save a tiny amount of ink. Try to get out of this bad habit.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • Thanks I've just added that. Could you check the latest update in the original post please. I think << operator overwrites snline for some reason – aristos Aug 03 '11 at 20:13