Используйте scanf("%d",&rows)
вместо scanf("%s",input)
Это позволяет вам напрямую получать целочисленное значение из стандартного ввода без необходимости преобразования в int.
Если пользователь вводит строку, содержащую нечисловые символы, вам необходимо очистить стандартный ввод перед следующим scanf("%d",&rows)
.
ваш код может выглядеть так:
#include <stdio.h>
#include <stdlib.h>
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
, сканирование вернет 0. Ничего не перехвачено.
Пример 2. Если пользователь введет 45
, а затем ENTER
, функция сканирования вернет 2 (2 элемента захвачены). Здесь %d
ловит 45
, а %c
ловит \n
Пример 3. Если пользователь введет 45aaadd
, а затем ENTER
, функция сканирования вернет 2 (2 элемента захвачены). Здесь %d
ловит 45
, а %c
ловит a
2)
(scanf("%d%c", &rows, &c)!=2 || c!='\n')
В примере 1: это условие равно TRUE
, так как scanf возвращает 0
(!=2
)
В примере 2: это условие равно FALSE
, так как scanf возвращает 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
продолжится.
person
Community
schedule
31.12.2012
scanf
вызовов? в настоящее время они считывают адрес, содержащийся в неинициализированном указателе (input
), что является неопределенным поведением. Я почти уверен, что если его значенияint
вы ищете, вы должны использовать%d
и сканировать адрес переменнойint
. Кроме того, проверьте возвращаемые значения вашихscanf
вызовов, которые сообщат вам, сколько полей было успешно получено. - person WhozCraig   schedule 31.12.2012[0..23]
правильно? Просто отсканируйте доint
и проверьте на успешный синтаксический анализ и значение в диапазоне, если только нет каких-то специальных символов, которые вы также хотите получить. Возможно, стоит прочитать больше оscanf()
? - person WhozCraig   schedule 31.12.2012scanf("%d")
, чтобы получить целое число, и если пользователь не вводит числовые символы, вы можете снова выполнить сканирование с помощьюscanf("%s)
, чтобы освободитьstdin
до следующегоscanf("%d")
. Обратитесь к моему ответу, я обновил его этим - person MOHAMED   schedule 31.12.2012while (count != rows);
. это блокирует вашу программу - person MOHAMED   schedule 31.12.2012"%[^\n]"
означает: ожидается ввод строки, содержащей любые символы, кроме"\n"
(новая строка). Это означает прочитать и очистить все содержимое стандартного ввода (берака Аллах фик) - person MOHAMED   schedule 31.12.2012clean_stdin
вместоscanf("%[^\n]",input)
, чтобы избежать переполнения буфераinput
. Пожалуйста, обратитесь к ответу, чтобы увидеть обновление - person MOHAMED   schedule 02.01.2013input
и заменили его наc
типа char?! это потому, что мы хотим сохранить как можно больше памяти? - person 7kemZmani   schedule 04.01.2013while
; Я бы предпочел разбить его на несколько и напечатать соответствующее сообщение, связанное с недопустимым пользовательским вводом. Я думаю, что это улучшит читаемость кода, а также улучшит взаимодействие с пользователем. вы можете поправить меня, если я ошибаюсь. Спасибо брат. - person 7kemZmani   schedule 04.01.2013scanf("%[^\n]", input)
, который возникает в том случае, если пользователь вводит строку, превышающую размер входного буфера, поэтому вы получите переполнение буфера. Вот почему я заменил это цикломwhile
иgetchar()
.getchar()
позволяет читать из стандартного ввода 1 символ. и если вы повторитеgetchar()
много раз, пока не получите\n
, вы очистите стандартный ввод - person MOHAMED   schedule 04.01.2013while
. Я обновил свой ответ для получения дополнительных объяснений. Пожалуйста, обратитесь к ответу. Добро пожаловать Брат - person MOHAMED   schedule 04.01.2013