PPasf PPasf - 3 months ago 11
C Question

fgets that would skip when called the second time

I think the problem of my code is with my fgets but I do not know how to fix it. So, when I call the function for the first time, everything works, but if for the second time, the function skips everything after the printf.

So the output would be:

Output:
Please enter x and y coordinates separated by a comma for the piece you wish to enter: 3,4
x: 3, y:4
Please enter x and y coordinates separated by a comma for the piece you wish to enter: x:
, y:


This is the code:

void functioncall()
{
char coord[4];
printf("Please enter x and y coordinates separated by a comma for the piece you wish to place: ");
fgets(coord, 4, stdin);

char *xcoord = strtok(coord, ",");
char *ycoord = strtok(NULL, " ");
if (!ycoord)
{
ycoord = "";
}

printf("x: %s, y: %s\n", xcoord, ycoord);
}


I cannot give an input when it is called for the second time.

Answer

The reason for the behaviour you see is the size of the coord array. When you specify the size as 4, it means you can get 1 digit, 1 comma, 1 digit, and 1 null byte stored — which doesn't leave room for the newline, so the second call to the function reads the newline (only), which doesn't parse well.

You should allow for much more space — users are endlessly inventive in what they type (leading blanks, trailing blanks, intermediate blanks, signs, leading zeros, etc.). I tend to use 4096 for single lines of input — partly for the shock value, and also because if someone's willing to write a 4-page essay on a single line, they deserve what they get.

This code works for me:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void functioncall(void)
{
    char coord[4096];
    printf("Please enter x and y coordinates separated by a comma for the piece you wish to place: ");
    if (fgets(coord, sizeof(coord), stdin) == 0)
    {
        fprintf(stderr, "Got EOF in %s\n", __func__);
        exit(EXIT_FAILURE);
    }
    const char delims[] = ", \n\t";

    char *xcoord = strtok(coord, delims);
    char *ycoord = strtok(NULL, delims);
    if (!ycoord)
    {
        ycoord = "";
    }

    printf("x: [%s] y: [%s]\n", xcoord, ycoord);
}

int main(void)
{
    functioncall();
    functioncall();
    return 0;
}

Example run (program name cd19, source file cd19.c):

$ ./cd19
Please enter x and y coordinates separated by a comma for the piece you wish to place: 234 , 495
x: [234] y: [495]
Please enter x and y coordinates separated by a comma for the piece you wish to place: 1,2
x: [1] y: [2]
$

The choice of delimiter characters ensures that the 234 , 495 example works OK (the tab is optional, but not necessarily a bad idea). It does, however, mean that the user is not obliged to enter a comma.