11

I am trying to use std::getline() in my project to read in a text file into an array of strings.

Here is my code:

ifstream ifs ( path );
string * in_file;
int count = 0;
while ( !ifs.eof() )
{
    ++count;
    if ( count == 1 )
    {
        in_file = new string[1];
    }
    else
    {
            // Dynamically allocate another space in the stack
    string *old_in_file = in_file;
    in_file = new string[count];
            // Copy over values
    for ( int i = 0 ; i < ( count - 1 ) ; i++ )
    {
        in_file[i] = old_in_file[i];
    }
    delete[] old_in_file;
    }
            // After doing some debugging I know this is the problem what am I 
            // doing wrong with it?
    getline(ifs,in_file[count - 1]);
}

So after doing some decoding I know that the getline() is not placing any value in the array of strings. It seems to place a null string in the array.

The goal is to read in a text file like:

Hello
Bye
See you later

The array will be filled like:

in_file [0] = Hello
in_file [1] = Bye
in_file [2] = See you later
2
  • If your assignment permits you to use std::vector, you should probably do that instead of new'ing and delete'ing every iteration. Commented Oct 1, 2013 at 18:32
  • Search StackOverflow for "parse getline read file". This has been asked toooo many times. Commented Oct 1, 2013 at 18:33

2 Answers 2

11

Never wrap reading from the stream with the following loop:

while ( !ifs.eof() )

At some websites, you will find an example telling you to do:

while ( ifs.good() )

which is a bit better than the first loop, yet still it is quite error prone and not advisable to do. Have a look at: Why is iostream::eof inside a loop condition considered wrong?

The most common ways of reading the files are either using std::getline when reading by lines:

std::string line;
while ( std::getline(ifs, line) ) {
    if (line.empty())                  // be careful: an empty line might be read
        continue;                      
    ...
}

or simply using >> operator when reading by words or extracting concrete types (e.g. numbers):

std::string word;
while ( ifs >> word ) {               
    ...
}

And to your dynamically allocated C-style array of std::string objects: avoid dynamic allocation as much as possible. Believe me, you don't want to take care of memory management on your own. Prefer using objects with automatic storage duration. Take advantage of what the standard library provides.
As it was pointed out already: use STL containers such as std::vector instead of C-style arrays:

std::ifstream ifs(path);
std::vector<std::string> lines;

std::string line;
while ( std::getline(ifs, line) )
{
    // skip empty lines:
    if (line.empty())
        continue;

    lines.push_back(line);
}
Sign up to request clarification or add additional context in comments.

2 Comments

I know this works, but I'm confused as to using the result of std::getline as the condition for the while loop. How does the stream returned by std::getline cause the loop to continue or stop?
while ( std::getline(ifs, line) ) won't work if you need to synchronize access to the stream with locks in a multi-threaded environment
10

Why so trouble ?

Simply use std:vector of std::string

std::string str;

std::vector <std::string> vec;

while ( std::getline(ifs,str) )
{
  vec.push_back(str) ;
}

If you really need an array of string

do :

string * in_file = new string[vec.size()];

And copy the elements from vec to in_file

for(size_t i=0;i<vec.size();i++)
 in_file[i] = vec[i];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.