Testing getchar() == EOF doesn't work as expec

2020-03-30 02:52发布

问题:

I have an assignment to "Write a C program that allows a user to enter up to 20 integers (it will stop accepting numbers based on a sentinel value or based on the 20-integer limit being reached). The program should then display the numbers in the reverse order of entry."

I decided to make my sentinel value "EOF" (or CTRL+D / CRTL+Z). My code has some really erratic behavior:

  1. You have to press the EOF keys twice (which also creates a blank entry that is counted int the array.
  2. The first digit from the first entry gets truncated.

Everything else seems to work OK but, this is clearly not the desired results. Below is my code. Can you explain what's wrong?

main() {
int i,iMax;
double dblMean;
int x[MAX];

printf("Please Enter Up to 20 Integers\n");

for (i=0; i<MAX; i++)
{
    printf("%d.> ",i+1);
    if (getchar() == EOF)           /* Check for CTRL+D OR CTRL+Z */
    break;                          /* Exit loop if EOF entered :: Must be pressed twice and eats first character of first entry */
    scanf("%d",&x[i]);
    iMax=i;
}

printf("\nYou entered  %d numbers\n",iMax+1);               /* Should be i+1 but EOF had to be entered twice */
printf("\nIndex       Item        Reverse Item\n");
for (i=0; i<=iMax; i++)
    printf("%3d%4c%8d%9c%11d\n",i,'  ',x[i],'  ',x[iMax-i]);
return 0;

}

EDITED: Here is my final code, Thank you all for your help:

#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int main()
{
    int i,iMax;
    int x[MAX];

    printf("Please Enter Up to 20 Integers\n");

    for (i=0; i<MAX; i++)
    {
        printf("%d.> ",i+1);
        if (scanf("%d",&x[i]) != 1)                         /* Checks for CTRL+D OR CTRL+Z */
        break;                                              /* EOF returns -1 and loop will be exited */
        iMax=i;                                             /* iMax must be set for second loop to exit properly */
                                                            /* Can sizeof x be used instead for second loop? */
    }

    printf("\nYou entered  %d numbers\n",iMax+1);           /* Displays number of items entered... Will be <= MAX*/
    printf("\nIndex       Item        Reverse Item\n");
    for (i=0; i<=iMax; i++)                                 /* Why wont 'for (i=0; i<=sizeof x; i++)' work? */
        printf("%3d%4c%8d%9c%11d\n",i,'  ',x[i],'  ',x[iMax-i]);
    return 0;
}

回答1:

The getchar() call reads (and effectively discards) the first digit because it is not EOF.

You don't test that scanf() worked; you should.

for (i = 0; i < MAX; i++)
{
    if (scanf("%d", &x[i]) != 1)
        break;
}

At this point, there are i integers in the array; you don't really need to set iMax in the loop. You could simply set it when the loop exits.



回答2:

Also, in addition to checking scanf, here is what you need to know:-

EOF is not a character. The EOF is a macro that getchar() returns when it reaches the end of input or encounters some kind of error. The ^D is not "an EOF character". What's happening under linux when you hit ^D on a line by itself is that it closes the stream, and the getchar() call reaches the end of input and returns the EOF macro. If you type ^D somewhere in the middle of a line, the stream isn't closed, so getchar() returns values that it read and your loop doesn't exit.

see http://www.c-faq.com/stdio/getcharc.html for a nice description.