简体   繁体   中英

Don't understand how .eof () works in c++

I have started working with files recently in class. When doing my homework, I can't really understand .eof().

The program which we are coding should do the following: the program asks you for a file name, opens it, and reads every character and counts every word. In the end it shows the average length of the words.

What happens is: Whenever I open a file with a text that ends with a dot, it works correctly, the average is correct. However, when the text does not end with a dot (for example: 9 8 7 6 5 4 3 2 1 Ignition), it shows that there are no words. I've been searching through the internet and I've only found that the End of File constant is normally -1 . I'm just trying to figure out how it works. Thanks

The code is the following:

bool isSeparator (char lletra){ //Com que són caràcters anglesos no hem de tenir en compte els accents
    //Pre: cert
    //Post: retorna cert si lletra és un separador, fals altrament -- els números són entesos com separadors
    bool separador = true;
    if(lletra>='a' and lletra<='z')
        separador = false;
    else if(lletra>='A' and lletra<='Z')
        separador = false;
    else {
        separador = true;
    }
    return separador;
}

void calculateNumbers (string fileName){
    ifstream openFile (fileName.c_str());
    char lletra; //Iniciem la primera variable
    openFile>>lletra;
    double wordCounter, average, wordLength, totalLength;
    char auxiliar = ' ';
    wordCounter = average = wordLength = totalLength = 0;

    while (not openFile.eof()){ //Mentre no trobi el final, que continui mirant lletres
        if (not isSeparator(lletra)){
            wordLength++;
            auxiliar = lletra;
        } else if (isSeparator (lletra) and not isSeparator(auxiliar)){
            wordCounter++;
            totalLength+=wordLength;
            wordLength = 0;
            auxiliar = lletra;
        }
        openFile>>lletra;
    }
    cout<<setprecision(3);
    cout<<fixed;
    average = totalLength/wordCounter;
    if (average==0){
        cout<<"Mitjana longitud mot: cap mot!";
    } else {
        cout<<totalLength<<" "<<wordCounter<<endl;
        cout<<"Mitjana longitud mot: "<<average<<endl;
    }
    cout<<openFile.eof();
}

Some of the things are in catalan. If there's anything you don't understand just ask me.

This question explains how .eof() works.

Your code actually reads the file correctly (although does not use recommended style). The lletra stores the latest character read from the file and the loop body is not entered once the characters have run out.


Your code only increments wordCounter when it encounters a separator. So when the file has . , wordCounter becomes 1 . If the file has no . (and no other separator) it's always 0 even though the file had a "word" in it.

This makes the line average = totalLength/wordCounter; causes undefined behaviour by dividing by zero.

To fix this: you could add logic so that if the file does not end in a separator, then pretend that it did, so that you count the last word as a word. Eg after the loop exits, check lletra and if it's not a separator then increment the word counter.

Also it would be better if the discrete variables were integer types instead of double .


NB. If you are actually trying to count the number of words in the file , by the normal meaning of "word", then the method you are using is not useful because you can not tell the difference between foo bar and foobar .

If you want to make lletra catch all the spaces then you need to change openFile>>lletra to openFile.get(lettra) . The >> operator skips spaces. If you use the recommended style from the link in my first paragraph then you only need this change in one place, rather than changing both places in the code as it stands.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM