Search code examples
c++visual-studio-2012eofseekg

Read from file after end-of-file is reached


I have a function named readNextString(ifstream &file , char* &pBuffer) which extracts the next string from a file, until ',' or '\n' is reached, removes whitespace at the beginning and at the end of the string, saves the rest in pBuffer and returns true if everything worked fine - false otherwise. Everything works until the end-of-file is reached. When the eof flag is set I can't move my get pointer. I've tried this:

if(file.eof())
{
   file.clear();
   file.seekg(0 , ios::end)
}

...and then remove whitespaces at the end of the string. This almost helped. The function extracts the string without the spaces but I get an infinite loop.

My actual question is: How can I check if the next char is EOF, and if I can't - is there any alternative way to do this?

Here is my actual function:

bool readNextString(ifstream &file , char* &pBuffer)
{
    if(file.eof()){
        return false;
    }
    for(; file.good() && isWhitespace(file.peek()) && !file.eof() ; file.seekg(1 , ios::cur))
        ;
    if(file.eof()){
        cout << "The file is empty.\n";
        return false;
    }else{
        streamoff startPos = file.tellg();
        cout << "startPos : " << startPos << endl;
        for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
            ;
        streamoff A = file.tellg();
        cout << "A : " << A << endl;
        file.seekg(-1 , ios::cur);
        for(;file.good() && isWhitespace(file.peek()) ; file.seekg(-1 , ios::cur))
            ;
        file.seekg(2 , ios::cur);
        streamoff endPos = file.tellg();
        cout << "endPos : " << endPos << endl;
        pBuffer = new char[endPos-startPos];
        if(pBuffer)
        {
            file.seekg(startPos , ios::beg);
            file.get(pBuffer , endPos-startPos , ',' || '\n');
            for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
                ;
            file.seekg(2 , ios::cur);
            streamoff temp = file.tellg();
            cout << "temp : " << temp << endl;
            return true;
        }else{
            cout << "Error! Not enough memory to complete the task.\nPlease close some applications and try again.\n";
            return false;
        }
    }
}

And that's one place where I call it:

void printCities()
{
    ifstream city ;
    city.open("cities.txt", fstream::in);
    if(city.is_open())
    {
        char *currCity;
        int counter = 1;
        while(readNextString(city , currCity))
        {
            cout << counter++ << ". " << currCity << endl;
            delete[] currCity;
            currCity = NULL;
        }
        if(city.eof())
            cout << "There are no cities added.\n";
        city.close();
    }else
        cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}

Hope I was clear enough. If you find some other mistakes or possible errors I'll be glad to hear it and learn from it.


Solution

  • Ok.I did it otherwise! getline() for the WIN ! :D So this is my code (this time is much more readable) :

    bool readNextString(ifstream &file , char pBuffer[] )
    {
        while(isWhitespace(file.peek()) && !file.eof())
            file.ignore(1);
        if(!file.eof())
        {
            streamoff start = file.tellg();
            stringstream toComma;
            if(file.getline(pBuffer , 200 , ','))
            {
                toComma << pBuffer;
                toComma.getline(pBuffer ,200, '\n');
                int i=strlen(pBuffer)-1;
                for(; isWhitespace(pBuffer[i]) ;i--)
                    ;
                pBuffer[i+1] = '\0';
                file.clear();
                file.seekg(start + strlen(pBuffer) , file.beg);
                return true;
            }else return false;
        }
        return false;
    }
    

    I've made some changes in my other function too:

    void printCities()
    {
        ifstream city ;
        city.open("cities.txt", fstream::in);
        if(city.is_open())
        {
            if(!isEmpty(city))
            {
                char currCity[200];
                int counter = 1;
                while(readNextString(city , currCity) && counter < 10)
                    cout << counter++ << ". " << currCity << endl;
            }else
                cout << "There are no cities added.\n";
            city.close();
        }else
            cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
    }
    

    The function isEmpty(ifstream &file) returns true if the file is empty and false otherwise.

    Thanks to all for help ! Best regards !