1

I need to get user input for a number between 0 and 100. The problem is when i input letter in scanf the program crashes or recognizes it as a 0.I want to avoid any user mistake that would potentially crash my program.I used getch previously but i don't know how to get multiple digit numbers with it. Any help on how to solve this problem would be nice. Thank you.

do
    {
        printf("Enter ID: ");
        scanf("%d", &NewWorkder->id);
        TargetList= FillWorker();
        TargetList= SeekList(Head, NewWorker->id);
    }
    while (NewWorker->id<0 || NewWorker->id>100 || (TargetList)!= (NULL) ||NewWorker->id ==0);
    fprintf(filemechanic,"%s %s %d\n", NewWorker->name, NewWorker->surname, NewWorker->id);
    free(TargetList);
    fclose(filemechanic);
}
LuQchor
  • 15
  • 4

2 Answers2

2

Don't use scanf at all. Maybe you could use its return value to see if no digits were entered at all, but if you don't want an input like 12ab to be valid, scanf won't help.

Here's an example that uses fgets and strtol to check for a valid number:

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

int main(void)
{
    char nptr[1024];
    char *errptr;
    long n = 0;
    do
    {
        printf("Enter a base-10 number: ");
        fgets(nptr, sizeof nptr, stdin);
        n = strtol(nptr, &errptr, 10);
    } while ((*errptr != '\n' && *errptr != '\0') || n < 0 || n > 100);
}

Example of running:

Enter a base-10 number: ab
Enter a base-10 number: 12ab
Enter a base-10 number: -1
Enter a base-10 number: 101
Enter a base-10 number: 123
Enter a base-10 number: 50
[end]
mediocrevegetable1
  • 4,086
  • 1
  • 11
  • 33
  • It would be nicer if the program provided an appropriate error message if the input was out of range, instead of merely repeating the prompt. Unfortunately, this would make the code significantly more complex, as my answer demonstrates. – Andreas Wenzel May 30 '21 at 16:35
  • @AndreasWenzel yeah, I would have to do the checks outside the `while ()` then. I also tried to keep close to what OP's `do ... while` loop was like (which puts similar checks in the `while ()` and so doesn't print an error either), but error messages are always helpful. – mediocrevegetable1 May 30 '21 at 16:42
  • Thank you this was very helpful I managed to fix my problem. – LuQchor May 30 '21 at 17:58
1

If you want to see whether scanf was able to successfully match an integer, you must check the return value.

Change the line

scanf("%d", &NewWorkder->id);

to:

if ( scanf("%d", &NewWorkder->id) != 1 )
{
   fprintf( stderr, "Error reading number!\n" );
   exit( EXIT_FAILURE ); 
}

If you want to check whether the value is in the desired range, you can add the following code:

if ( newWorker->id < 0 || newWorker->id > 100 ) )
{
   fprintf( stderr, "Input is out of range!\n" );
   exit( EXIT_FAILURE ); 
}

If you don't want your program to exit on bad input, but would prefer it to print an error message and prompt the user again, you could use the following code instead:

bool bad_input;

do
{
    bad_input = false;

    //prompt user for input
    printf("Enter ID: ");

    //call scanf and verify that function was successful
    if ( scanf("%d", &NewWorkder->id) != 1 )
    {
        printf( "Error reading number, try again!\n" );
        bad_input = true;
    }

    //verify that input is in range
    if ( newWorker->id < 0 || newWorker->id > 100 ) )
    {
        printf( "Number must be between 0 and 100, try again!\n" );
        bad_input = true;
    }

    //discard remainder of line
    for ( int c; (c=getchar()) != EOF && c != '\n'; )
        ;

} while ( bad_input );

However, for line-based input, I wouldn't recommend using scanf, because that function does not extract the entire line from the input stream; it only extracts as much as it needs. This can be confusing and can lead to programming bugs. Instead, I would recommend using fgets and strtol instead. See the other answer for such a solution. Also, I suggest that you read this guide: A beginners' guide away from scanf()

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39