Search code examples
c++arraysfile-iofstreamdynamic-arrays

How to use std::getline() to read a text file into an array of strings in C++?


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

Solution

  • 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);
    }