Как сканировать только одно целое и повторять чтение, если пользователь вводит нецифровые символы?

Вот небольшая проблема с тиро с C-кодом, пытающимся просто запретить пользователю вводить символ или целое число меньше 0 или более 23.

#include  #include  int main(void) { const char *input; char *iPtr; int count = 0; int rows; printf("Enter an integer: "); scanf("%s", input); rows = strtol(input, &iPtr, 0); while( *iPtr != '\0') // Check if any character has been inserted { printf("Enter an integer between 1 and 23: "); scanf("%s", input); } while(0 < rows && rows < 24) // check if the user input is within the boundaries { printf("Select an integer from 1 to 23: "); scanf("%s", input); } while (count != rows) { /* Do some stuff */ } return 0; } 

Я сделал это на полпути, и небольшое повышение будет оценено по достоинству.

    Используйте scanf("%d",&rows) вместо scanf("%s",input)

    Это позволяет получить прямое значение integer из stdin без необходимости преобразования в int.

    Если пользователь вводит строку, содержащую нецифровые символы, тогда вы должны очистить свой stdin до следующего scanf("%d",&rows) .

    ваш код может выглядеть так:

     #include  #include  int clean_stdin() { while (getchar()!='\n'); return 1; } int main(void) { int rows =0; char c; do { printf("\nEnter an integer from 1 to 23: "); } while (((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) || rows<1 || rows>23); return 0; } 

    объяснение

    1)

     scanf("%d%c", &rows, &c) 

    Это означает, что от пользователя вводится целое число и рядом с ним нецифровой символ.

    Пример1: если пользователь вводит aaddk а затем ENTER , scanf вернет 0. Ничего не закрыто

    Пример2: Если пользователь вводит 45 а затем ENTER , scanf вернет 2 (2 элемента закрыты). Здесь %d – capting 45 а %c – capting \n

    Пример 3: Если пользователь вводит 45aaadd а затем ENTER , scanf вернет 2 (2 элемента закрыты). Здесь %d – capting 45 а %c – capting a

    2)

     (scanf("%d%c", &rows, &c)!=2 || c!='\n') 

    В примере1: это условие TRUE потому что scanf возвращает 0 ( !=2 )

    В примере 2: это условие FALSE потому что scanf return 2 и c == '\n'

    В примере 3: это условие TRUE потому что scanf возвращает 2 и c == 'a' (!='\n')

    3)

     ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) 

    clean_stdin() всегда TRUE потому что функция всегда возвращает 1

    В примере 1: (scanf("%d%c", &rows, &c)!=2 || c!='\n') имеет значение TRUE поэтому условие после && должно быть проверено, поэтому clean_stdin() будет выполнено и все условие TRUE

    В примере 2: (scanf("%d%c", &rows, &c)!=2 || c!='\n') является FALSE поэтому условие после && не будет проверяться (поскольку когда-либо его результат все условие будет FALSE ), поэтому clean_stdin() не будет выполняться, и все условие будет FALSE

    В примере 3: (scanf("%d%c", &rows, &c)!=2 || c!='\n') имеет значение TRUE поэтому условие после && должно быть проверено, поэтому clean_stdin() будет выполнено и все условие TRUE

    Поэтому вы можете заметить, что clean_stdin() будет выполняться только в том случае, если пользователь вводит строку, содержащую нецифровой символ.

    И это условие ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) вернет FALSE только если пользователь вводит integer и ничего больше

    И если условие ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) является FALSE а integer находится между 1 и 23 тогда while цикл будет ломаться иначе while цикл while будет продолжаться

     #include  main() { char str[100]; int num; while(1) { printf("Enter a number: "); scanf("%[^0-9]%d",str,&num); printf("You entered the number %d\n",num); } return 0; } 

    %[^0-9] в scanf() забирает все, что не находится между 0 и 9 . В основном он очищает входной stream не цифр и помещает его в str . Ну, длина нецифровой последовательности ограничена 100. Следующие %d выбирают только целые числа во входном streamе и помещают его в num .

    Вы можете создать функцию, которая читает целое число от 1 до 23 или возвращает 0, если не-int

    например

     int getInt() { int n = 0; char buffer[128]; fgets(buffer,sizeof(buffer),stdin); n = atoi(buffer); return ( n > 23 || n < 1 ) ? 0 : n; } 

    Вам нужно будет повторить свой вызов strtol внутри ваших петель, где вы просите пользователя повторить попытку. Фактически, если вы сделаете цикл, do { ... } while(...); вместо этого вы не получаете одинаковое повторение в два раза.

    Вы также должны форматировать свой код, чтобы можно было видеть, где код находится внутри цикла, а не.

    MOHAMED, ваш ответ велик, и это действительно помогло мне. Здесь я разместил код, который, я думаю, немного проще:

     #include  int getPositive(void); void clean_input(void); int main(void) { printf("%d\n",getPositive()); return 0; } int getPositive(void) { int number; char buffer; // Holds last character from user input. // (ie '\n' or any other character besides numbers) int flag; // Holds scanf return value do{ flag = scanf("%d%c", &number, &buffer); // Gets input from user // While scanf did not read 2 objects (ie 1 int & 1 char) // or the user inputed a number and then a character (eg. 12te) // ask user to type a valid value while (flag !=2 || buffer!='\n') { clean_input(); printf("%s","You have typed non numeric characters.\n" "Please type an integer\n?"); flag = scanf("%d%c", &number, &buffer); } if(number<0) { printf("%s","You have typed a non positive integer\n" "Please type a positive integer\n?"); } else { // If user typed a non negative value, exit do-while. break; } }while(1); } void clean_input(void) { while (getchar()!='\n'); return; } в #include  int getPositive(void); void clean_input(void); int main(void) { printf("%d\n",getPositive()); return 0; } int getPositive(void) { int number; char buffer; // Holds last character from user input. // (ie '\n' or any other character besides numbers) int flag; // Holds scanf return value do{ flag = scanf("%d%c", &number, &buffer); // Gets input from user // While scanf did not read 2 objects (ie 1 int & 1 char) // or the user inputed a number and then a character (eg. 12te) // ask user to type a valid value while (flag !=2 || buffer!='\n') { clean_input(); printf("%s","You have typed non numeric characters.\n" "Please type an integer\n?"); flag = scanf("%d%c", &number, &buffer); } if(number<0) { printf("%s","You have typed a non positive integer\n" "Please type a positive integer\n?"); } else { // If user typed a non negative value, exit do-while. break; } }while(1); } void clean_input(void) { while (getchar()!='\n'); return; } 

    В моем случае я хочу, чтобы номер был просто положительным. Если вы хотите, чтобы ваш номер находился между 1 и 23, вы заменяете number<0 number<1 || number>23 number<1 || number>23 в выражении if . Также вам нужно будет изменить printf чтобы напечатать соответствующее сообщение.

     char check1[10], check2[10]; int foo; do{ printf(">> "); scanf(" %s", check1); foo = strtol(check1, NULL, 10); // convert the string to decimal number sprintf(check2, "%d", foo); // re-convert "foo" to string for comparison } while (!(strcmp(check1, check2) == 0 && 0 < foo && foo < 24)); // repeat if the input is not number 

    Если вход является номером, вы можете использовать foo качестве вашего ввода.