corporateWhore
corporateWhore

Reputation: 635

Reading text file from stdin stops at last line

I wrote a short program to test reading text files from stdin:

int main(){
    char c;

    while(!feof(stdin)){

        c = getchar();       //on last iteration, this returns '\n'

        if(!isspace(c))      //so this is false
            putchar(c);

        //remove spaces
        while (!feof(stdin) && isspace(c)){    //and this is true
                c = getchar();  //      <-- stops here after last \n
                if(!isspace(c)){
                    ungetc(c, stdin);
                    putchar('\n');
                }
        }
    }
    return 0;
}

I then pass it a small text file:

jimmy   8
phil    6
joey    7

with the last line (joey 7) terminated with a \n character.

My problem is, after it reads and prints the last line, then loops back to check for more input, there are no more characters to read and it just stops at the line noted in the code block.

Question: The only way for feof() to return true is after a failed read as noted here: Detecting EOF in C. Why isn't the final call to getchar triggering EOF and how can I better handle this event?

Upvotes: 0

Views: 997

Answers (1)

chqrlie
chqrlie

Reputation: 144715

There are multiple problems in your code:

  • You do not include <stdio.h>, nor <ctype.h>, or at least you did not post the whole source code.
  • You use feof() to check for end of file. This is almost never the right method, as underscored in Why is “while ( !feof (file) )” always wrong?
  • You read the byte from the stream in a char variable. This prevents proper testing for EOF and also causes undefined behavior for isspace(c). Change the type to int.

Here is an improved version:

#include <stdio.h>

int main(void) {
    int c;

    while ((c = getchar()) != EOF) {
        if (!isspace(c)) {
            putchar(c);
        } else {
            //remove spaces
            while ((c = getchar()) != EOF && isspace(c)) {
                continue;  // just ignore extra spaces
            }
            putchar('\n');
            if (c == EOF)
                break;
            ungetc(c, stdin);
        }
    }
    return 0;
}

While your method with ungetc() is functionally correct, it would be better to use an auxiliary variable this way:

#include <stdio.h>
#include <ctype.h>

int main(void) {
    int c, last;

    for (last = '\n'; ((c = getchar()) != EOF; last = c) {
        if (!isspace(c)) {
            putchar(c);
        } else
        if (!isspace(last))
            putchar('\n');
        }
    }
    return 0;
}

Upvotes: 2

Related Questions