Search code examples
c++file-iovectorgetline

Getline is returning nothing but blank


I am trying to open many files in a row. The file names are all stored in a vector, which is passed to my function. This is just a simple test to make sure that everything is working. If it works, then I will need to pushback whatever the file holds into another vector.

void readfile(vector<string> &filename)
{
    string temp;
    ifstream infile(filename[2].c_str());
    getline (infile, temp);
    cout << temp << endl;
}

This is simply outputting a blank line, although the text file holds about a paragraph of information. I have not used File I/O in a while, so I am a little rusty. Any help is appreciated.

Edit: You all have been a great help, one more thing, I need to pass them without periods, or spaces. Basically just a string of chars.


Solution

  • OP's code does not check for success of any of their file IO, so the file may not have opened, the file may be empty, and the read may have failed for any number of reasons.

    Fortunately, getline returns the input stream and streams implement a really neat operator bool that returns false if the stream is in an error condition and could not be read. If the file could not be read, the contents of temp are most certainly not valid and should not be used.

    So...

    void readfile(vector<string> &filename)
    {
        string temp;
        ifstream infile(filename[2].c_str());
        if (getline (infile, temp)) //test the read for success
        {
            cout << temp << endl;
        }
        else
        {
            cout << "failed to read file" << endl;
        }    
    }
    

    If getline fails for any reason, including file not open, file is empty, and file is corrupt and unreadable, the stream's state will be marked bad and return false when checked by if().

    Normally at this point you should check the type of error, infile.clear() the stream to remove the error condition, and pick up the pieces, but in this case there isn't much point. If you can't read the beginning of a file into a string, you got big problems and should take a closer look at the health and contents of file filename[2].

    By the way, if your compiler is relatively up to date, ifstream's constructor will eat a std::string and ifstream infile(filename[2]); will be valid.

    Style-wise, you're better off just passing the filename string into readfile, not the vector. This allows you to reuse the readfile function for more than just element 2 of a vector.

    void readfile(string & filename)
    {
        string temp;
        ifstream infile(filename);
        if (getline (infile, temp)) //test the read for success
        {
            cout << temp << endl;
        }
        else
        {
            cout << "failed to read file " << filename << endl;
        }    
    }
    

    And call with

    readfile(filename[2]);
    

    Expanding this function to meet OP's true goal

    void readfile(string & filename,
                  vector<string> & strings)
    {
        string temp;
        ifstream infile(filename);
        if (getline (infile, temp)) //test the read for success
        {
            strings.push_back(temp);
            cout << temp << endl;
        }
        else
        {
            cout << "failed to read file " << filename << endl;
        }    
    }
    

    and call with

    vector<string> strings;
    ...
    readfile(filename[2], strings);
    

    2024 update

    Copy elision is now the law of the land in some cases, and so commonplace in most other typical use cases that it should be taken advantage of to simplify the function further

    vector<string> readfile(string & filename)
    {
        vector<string> & strings
        string temp;
        ifstream infile(filename);
        if (getline (infile, temp)) //test the read for success
        {
            strings.push_back(temp);
            cout << temp << endl;
        }
        else
        {
            cout << "failed to read file " << filename << endl;
        }    
        return strings; // will take advantage of Named Return Value Optimization 
                        // (NRVO) to eliminate the copy with most modern compilers.
    }
    

    and call with

    vector<string> strings = readfile(filename[2]);