Zhi Zheng
Zhi Zheng

Reputation: 11

C Programming int validation

int main() {
    int choice;
    printf("\n----------Welcome to Coffee Shop----------");
    printf("\n\n\t1. Login   ");
    printf("\n\t2. Sign Up ");
    printf("\n\nPlease enter 1 or 2: ");
    scanf(" %d", &choice);
    system("cls||clear");
    
    //put while loop to check
    switch (choice) {
    case 1:
        system("cls||clear");
        login();
        break;
    case 2:
        system("cls||clear");
        user_signup();
        break;
    default:
        printf("\nInvalid Number\n");
        main();
        break;
    }

    return 0;
}

How do i make user retype their input if the input is not int? I tried to use isdigit() but it wont work, May i know what are the solutions?

Upvotes: 0

Views: 90

Answers (5)

sirosi
sirosi

Reputation: 11

I think it would be better to receive it as a string and check if all chars are numbers. And if all the chars are numbers, they convert them to int

like this

int main() {
    int choice;
    char chars[100];
    printf("\n----------Welcome to Coffee Shop----------");
    printf("\n\n\t1. Login   ");
    printf("\n\t2. Sign Up ");
    printf("\n\nPlease enter 1 or 2: ");
    scanf(" %s", chars);
    choice = stringToInteger(chars);
    system("cls||clear");

    //put while loop to check
    switch (choice) {
    case 1:
        system("cls||clear");
        login();
        break;
    case 2:
        system("cls||clear");
        user_signup();
        break;
    default:
        printf("\nInvalid Number\n");
        main();
        break;
    }

    return 0;
}

int stringToInteger(char* chars)
{
    int i = 0, number = 0;

    while(chars[i] >= '0' && chars[i] <= '9')
    {
        number = chars[i++] - '0' + number * 10;
    }

    return number;
}

Upvotes: 1

chux
chux

Reputation: 154312

scanf(" %d", &choice); fails to handle cases where the converted input is outside the int range. That leads to undefined behavior.

Drop using scanf().

Use fgets() to read a line of user input into a string, then validate.
For str2subrange(), see Why is there no strtoi in stdlib.h?.

bool validate_int(const char *s, int *value) {
  const int base = 10;
  char *endptr;
  errno = 0;
  long lvalue = str2subrange(s, &endptr, base, INT_MIN, INT_MAX);
  // For OP's case, could instead use 
  long lvalue = str2subrange(s, &endptr, base, 1, 2);
  if (value) {
    *value = (int) lvalue;
  }
  if (s == endptr) {
    return false; // No conversion
  }
  if (errno == ERANGE) {
    return false; // Out of range
  }

  // Skip trailing white-space
  while (isspace(((unsigned char* )endptr)[0])) {
    endptr++;
  }

  if (*endptr != '\0') {
    return false; // Trailing junk
  }

  return true;
}

Upvotes: 1

Anthony Kelly
Anthony Kelly

Reputation: 465

Instead of the recursive call to main() you should use a loop. Also consider getchar() instead of scanf for single character input. For example, the following will do what you want.

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

int main() {
    int valid_choice = 0;
    while (!valid_choice) {
        printf("\n----------Welcome to Coffee Shop----------");
        printf("\n\n\t1. Login   ");
        printf("\n\t2. Sign Up ");
        printf("\n\nPlease enter 1 or 2: ");
        char choice = getchar();
        system("cls||clear");
    
        //put while loop to check
        switch (choice) {
        case '1':
            valid_choice = 1;
            system("cls||clear");
            login();
            break;
        case '2':
            valid_choice = 1;
            system("cls||clear");
            user_signup();
            break;
        default:
            printf("\nInvalid Number\n");
            break;
        }
    }

    return 0;
}

Upvotes: 0

The scanf() function returns the number of fields that were successfully converted and assigned. So in your scanf(" %d", &choice); line, you can do this:

do {
    printf("\n\nPlease enter 1 or 2: ");
    int result=scanf(" %d", &choice);
    if (result==1) {
        break;
    }
    printf("\nInvalid Number\n");
} while (1);

Upvotes: 0

4386427
4386427

Reputation: 44340

scanf returns the number of input items successfully matched. So you can build a loop that runs until you get exactly one item.

A very simple approach would be:

while(1)
{
    int res = scanf(" %d", &choice);

    if (res == 1) break;  // Done... the input was an int

    if (res == EOF) exit(1); // Error so exit

    getchar();  // Remove an discard the first character in stdin
                // as it is not part of an int
}

printf("Now choice is an int with value %d\n", choice);

That said, I recommend that you take a look at fgets and sscanf. They are often a better approach than scanf

Upvotes: 1

Related Questions