Search code examples
cfgets

Why code is being executed in such strange sequence in c?


int is_valid(char *input)
{
    int i;

    for (i = 0;; i++)
    {
        // Check for null terminator
        if ( ! input[i])
        {
            printf("stop executing is_valid()");
            return 0;
        }

        // Will be executed for null terminator... o_O
        printf("%c isdigit: %d\n", input[i], isdigit(input[i]));
    }

    return 1;
}

int main()
{
    char input[80];
    fgets(input, sizeof(input), stdin);
    is_valid(input);
    return 0;
}

Output:

1 isdigit: 1
0 isdigit: 1
1 isdigit: 1

 isdigit: 0 // Why is that here? null terminator after return?!
stop executing is_valid()invalid input!

Why null terminator is processed via isdigit before return? And.. ok, why if condition is executed after it?


Solution

  • Why null terminator is processed via isdigit before return?

    It is not. It is executed for '\n' character read by fgets.

    C11-§7.21.7.2

    The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.

    For the input

    101
    

    there are 5 characters in there

    101\n\0  
    

    \n is not a digit of course.

    You need to add a condition for \n too

    if (input[i] == '\0' || input[i] == '\n')
    {
        printf("stop executing is_valid()");
        return 0;
    }