Search code examples
cuser-inputfgetsstrtol

C - Can't read user integer input


I'm trying to read user integer input with the following code. I'm aware that strtol returns a long value.

long color = 1;
char buf[256];
char * last;

while(color != 0){
    printf("Enter a color (0 to stop): ");
    fgets(buf, 256, stdin);

    color = strtol(buf, &last, 10);

    if(last != '\0'){
        printf("You didn't enter a number.\n");
    }
    else{
        printf("%d\n", color);
    }
}

I tried running this, first entering 4, which gave me You didn't enter a number. I tried it again with "forty" and got the same result. What am I missing here? All I want to do is get basic user input for an integer value that verifies only an integer was entered. I don't need a long because the values will all be between 3000 and 4000.


Solution

  • last != '\0' is equivalent to last != NULL. You're testing whether last is a null pointer, which it never is, because strtol never sets *endptr to NULL.

    You should probably do this instead:

    if (last == buf || *last != '\0')
    

    (The first condition handles the case where buf is an empty string.)

    There's a secondary problem in your input code:

    fgets(buf, 256, stdin);
    

    This line does not check the return value of fgets to make sure buf was filled, and it does not remove the trailing newline of any user input.

    Do this instead:

    if (!fgets(buf, 256, stdin)) {
        break;
    }
    buf[strcspn(buf, "\n")] = '\0';
    

    As for why '\0' acts as a null pointer here:

    Any integer constant expression with value zero is implicitly converted to a null pointer if used in a pointer context. '\0' is such a zero-valued integer expression, and you're comparing it to a pointer, so it is in pointer context.