0

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?

Community
  • 1
  • 1
corporateWhore
  • 617
  • 2
  • 12
  • 23

1 Answers1

2

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;
}
Community
  • 1
  • 1
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I read the link and think I understand the topic better. So thank you. But even after incorporating your suggested changes execution still stops at the last `getchar()` call. At line 11. – corporateWhore Sep 04 '16 at 19:19
  • What do you mean by *it stops*? it should at least output the `'\n'` – chqrlie Sep 04 '16 at 19:27
  • Ok, I think it's an eclipse debugger problem. In eclipse, when the debugging line gets to `while((c = getchar()) != EOF && isspace(c)` it just stops and won't continue any further. The only option I have is to press the stop button. When I compiled it and ran it in a terminal it worked just fine. Sorry about that. – corporateWhore Sep 04 '16 at 19:36
  • This is definitely an eclipse problem. I just tried the same code in cLion and it worked fine as well. I'll have to investigate the eclipse issue separately. Thank you for your help. – corporateWhore Sep 04 '16 at 20:37