understanding ungetc use in a simple getword

895 Views Asked by At

I've come across such an example of getword. I understand all the checks and etc. but I have a problem with ungetc.

When the c does satisfy if ((!isalpha(c)) || c == EOF)and also doesn't satisfy while (isalnum(c)) -> it isn't a letter, nor a number - ungetc rejects that char.

Let's suppose it is '\n'.

Then it gets to return word however it can't be returned since it is not saved in any array. What happens then?

    while (isalnum(c)) {
        if (cur >= size) {
            size += buf;
            word = realloc(word, sizeof(char) * size);

        }
        word[cur] = c;
        cur++;
        c = fgetc(fp);
    }
    if ((!isalpha(c)) || c == EOF) {
        ungetc(c, fp);          
    }
    return word;

EDIT @Mark Byers - thanks, but that c was rejected for a purpose, and will not satisfy the condition again and again in an infinite loop?

3

There are 3 best solutions below

2
Jonathan Leffler On BEST ANSWER

The terminal condition, just before the line you don't understand, is not good. It should probably be:

int c;

...

if (!isalpha(c) && c != EOF)
    ungetc(c, fp);

This means that if the last character read was a real character (not EOF) and wasn't an alphabetic character, push it back for reprocessing by whatever next uses the input stream fp. That is, suppose you read a blank; the blank will terminate the loop and the blank will be pushed back so that the next getc(fp) will read the blank again (as would fscanf() or fread() or any other read operation on the file stream fp). If, instead of blank, you got EOF, then there is no attempt to push back the EOF in my revised code; in the original code, the EOF would be pushed back.

Note that c must be an int rather than a char.

2
Mark Byers On

ungetc pushes the characters onto the stream so that the next read will return that character again.

ungetc(c, fp);  /* Push the character c onto the stream. */
/* ...etc... */
c = fgetc(fp);  /* Reads the same value again. */

This can sometimes be convenient if you are reading characters to find out when the current token is complete, but aren't yet ready to read the next token.

0
Peter Cerba On

OK. Now I understand why that case with eg. '\n' was troubling me. I'm just dumb and forgot about the section in main() referring to getword. Of course before calling getword there are a couple of tests (another ungetc there) and it fputs that characters not satisying isalnum It emerges from this that while loop in getword always starts with at least one isalnum positive, and the check at then end is just for following characters.