Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using fgets and strtol to get a single integer

Tags:

c

I am learning C and I am trying to use fgets() and strtol() to accept user input and just take the first character. I am going to make a menu that will allow a user to select options 1-3 and 4 to exit. I want each option to only be selected if '1', '2', '3', or '4' are selected. I don't want 'asdfasdf' to work. I also don't want '11212' to select the first option since it starts with a 1. I created this code so far while I started testing and for some reason this loops over the question and supplies a 0 to the input.

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

int main() {
    char a[2];
    long b;

    while(1) {
        printf("Enter a number: ");

        fgets(a, 2, stdin);

        b = strtol(a, NULL, 10);

        printf("b: %d\n", b);
    }
  return 0;
}

output

Enter a number: 3
b: 3
Enter a number: b: 0
Enter a number:

It should be:

Enter a number: 3
b: 3
Enter a number: 9
b: 9
like image 611
bob dilly Avatar asked Oct 28 '25 09:10

bob dilly


1 Answers

You need to have enough room for the '\n' to be read or else it will be left in the input buffer and the next iteration it will be read immediately and thus make fgets() return with an empty string and hence strtol() returns 0.

Read fgets()'s documentation, it reads until a '\n' or untill the buffer is full. So the first time, it stops because it has no more room to store characters, and then the second time it still has to read '\n' and it stops immediately.

A possible solution is to increase the buffer size, so that the '\n' is read and stored in it.

Another solution, is to read all remaining characters after fgets().

The second solution could be cleanly implemented by reading one character at a time instead, since you are just interested in the first character you can discard anything else

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

int main() 
{
    int chr;
    while (1) {
        // Read the next character in the input buffer
        chr = fgetc(stdin);
        // Check if the value is in range
        if ((chr >= '0') && (chr <= '9')) {
            int value;
            // Compute the corresponding integer
            value = chr - '0';
            fprintf(stdout, "value: %d\n", value);
        } else {
            fprintf(stderr, "unexpected character: %c\n", chr);
        }
        // Remove remaining characters from the
        // input buffer.
        while (((chr = fgetc(stdin)) != '\n') && (chr != EOF))
            ;
    }
    return 0;
}
like image 136
Iharob Al Asimi Avatar answered Oct 30 '25 00:10

Iharob Al Asimi