简体   繁体   中英

fgets doesn't stop reading user input

I found some challenge on reddit to make a program which will sum up all DnD dice rolls. Number of throws is unlimited therefore I created this while loop.

I used fgets to input the string, (I can't input only integers because the input is for example 1d3, where 1 is number of dice thrown, and 3 is number of sides of the dice thrown.)

When the user is prompted to input dice, fgets never stops reading user input.

For example:

To end inputting dice type 0
1d3 
1d4
1d5
0
0
^C

Main function:

int main(void)
{
    char input[MAXSIZE];
    int sum = 0;
    printf("To end inputting dice type 0\n");
    while(*(input) != 0);
    {
        fgets(input, sizeof(input), stdin);
        printf("Debug: input = ");
        puts(input);
        printf("\n");
        sum += dice(input);
        printf("Debug: sum = %d\n", sum);
    }
    printf("Sum of dice rolls is %d.", sum);
    return 0;
}

Firstly, the literal value of the character input 0 is not 0 . In ASCII , it is 48 (decimal).

Try

 while(*(input) != '0')  // (1) - use the character literal form
                         // (2) remove the ;

That said, the standard output is usually line buffered . You need to force a flush if you want to see the outputs in the terminal. You can do that by either

  • add a newline

      printf("Debug: input = \\n"); 
  • use fflush(stdout) .

Try this:-

while(fgets(input, sizeof input, stdin) != NULL)

or

while(fgets(input, sizeof input, stdin))

The issue was really simple and such a beginner mistake I feel shameful for even asking the question.

The semicolon after the while loop.

Thanks all for helping me out.

char input[MAXSIZE] = { 0 }; // initialise input!
// otherwise you get to here and access an uninitialised variable:
while(*(input) != 0); // <--- and a semicolon right there!!! Remove that!

In fact I think the loop you want is while (fgets(input, sizeof input, stdin) && strcmp(input, "0\\n")) ... note that I've hoisted the fgets into the loops control expression.

You should probably do a check after calling fgets to ensure a newline is read, for example

while (fgets(input, sizeof input, stdin) && strcmp(input, "0\n")) {
    size_t n = strcspn(input, "\n");
    if (input[n] == '\n') input[n] = '\0';
    else assert(input[n] == '\0'), // #include <assert.h>
         fscanf(stdin, "%*[^\n]"),
         fgetc(stdin);

There's no undefined behaviour associated with reading unsigned integers when using fscanf , so if you only plan on using positive values you can use that instead of fgets if you wish, ie

unsigned dice_count, dice_sides;
while (fscanf(stdin, "%ud%u", &dice_count, &dice_sides) == 2) {
    printf("You chose to roll %u times with dice that contain %u sides\n", dice_count, dice_sides);
}

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