Search code examples
c++ifstreamgetline

C++ function `getline()` doesn't work correctly for char[]


I need to extract the first 150 characters from a line and save them in a char[] array (no strings allowed). My code below doesn't work and i just can't find the reason why:

#include <ifstream>
#include <iostream>
using namespace std;
int main()
{
    ifstream myFile;
    myFile.open("message.txt");
    if(!myFile.is_open()) cout<<"error"; //added this after edit
    const int SIZE = 151;
    char buffer[SIZE]={};
    while(myFile.getline(buffer, 151)){
        buffer[150]='\0';
        cout<<buffer<<endl;
    }
    myFile.close();
}

Here's a snippet of "message.txt":

abcdefg
hijklmn
opqrstuv
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
hello

It simply prints out nothing. The file "message.txt" exists and has several lines of characters in it. Where am I wrong? EDIT: if the characters on a line are less than 150, they should all be read. If they are more than 150, the rest should be ignored.


Solution

  • If you are trying to read the first 150 characters of the 1st line, then you don't need the while loop. And you don't need to null-terminate the buffer manually, istream::getline() will do that for you, eg:

    #include <ifstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream myFile("message.txt");
        if (!myFile.is_open())
        {
            cout << "error";
            return 0;
        }
    
        const int SIZE = 151;
        char buffer[SIZE] = {};
        myFile.getline(buffer, SIZE);
    
        cout << buffer << endl;
    
        myFile.close();
        return 0;
    }
    

    If you want to read the first 150 characters of a specific line only, then you need a loop to skip all lines regardless of their length until you reach the desired line, and then you can read the 150 characters of just that line, eg:

    #include <ifstream>
    #include <iostream>
    #include <limits>
    using namespace std;
    
    int main()
    {
        ifstream myFile("message.txt");
        if (!myFile.is_open())
        {
            cout << "error";
            return 0;
        }
    
        size_t lineIndex = ...;
        while (lineIndex > 0)
        {
            if (!myFile.ignore(numeric_limits<streamsize>::max(), '\n'))
            {
                cout << "error";
                return 0;
            }
    
            if (myFile.eof())
            {
                cout << "eof";
                return 0;
            }
    
            --lineIndex;
        }
    
        const int SIZE = 151;
        char buffer[SIZE] = {};
    
        myFile.getline(buffer, SIZE);
    
        cout << buffer << endl;
    
        myFile.close();
        return 0;
    }
    

    If you want to read the first 150 characters of each line, then after a successful read you need to skip any remaining characters prior to a line break before you can then read the next line, eg:

    #include <ifstream>
    #include <iostream>
    #include <limits>
    using namespace std;
    
    int main()
    {
        ifstream myFile("message.txt");
        if (!myFile.is_open())
        {
            cout << "error";
            return 0;
        }
    
        const int SIZE = 151;
        char buffer[SIZE] = {};
    
        do
        {
            myFile.getline(buffer, SIZE);
    
            if (myFile.bad())
            {
                cout << "error";
                return 0;
            }
    
            if (myFile.fail())
            {
                // SIZE-1 characters were extracted before a line break
                // was reached, need to reset the error to keep going...
                myFile.clear();
                myFile.ignore(numeric_limits<streamsize>::max(), '\n');
            }
    
            cout << buffer << endl;
        }
        while (!myFile.eof());
    
        myFile.close();
        return 0;
    }