Jak zeskanować tylko liczbę całkowitą i powtórzyć odczyt, jeśli użytkownik wprowadzi znaki inne niż numeryczne?
Oto mały problem młodego tyro z kodem C, który próbuje po prostu uniemożliwić użytkownikowi wpisanie znaku lub liczby całkowitej mniejszej niż 0 lub większej niż 23.
#include <stdio.h>
#include <stdlib.h>
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;
}
Udało mi się w połowie i mały push up będzie mile widziany. 6 answers
Użyj scanf("%d",&rows)
zamiast scanf("%s",input)
To pozwala uzyskać bezpośrednio wartość całkowitą ze standardowego wejścia bez konieczności konwersji na int.
Jeśli użytkownik wprowadzi łańcuch zawierający znaki inne niż numeryczne, musisz wyczyścić swój stdin przed następnym scanf("%d",&rows)
.
Twój kod może wyglądać tak:
#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;
}
Wyjaśnienie
1)
scanf("%d%c", &rows, &c)
Oznacza to oczekiwanie od użytkownika wprowadzenia liczby całkowitej, a w pobliżu niej nieliczbowej charakter.
Przykład1: Jeśli użytkownik wprowadzi aaddk
, a następnie ENTER
, scanf zwróci 0. Nothing capted
Przykład2: jeśli użytkownik wprowadzi 45
, a następnie ENTER
, scanf zwróci 2 (2 elementy są podpisane). Tutaj %d
jest capting 45
i %c
jest capting \n
Przykład3: jeśli użytkownik wprowadzi 45aaadd
, a następnie ENTER
, scanf zwróci 2 (2 elementy są podpisane). Tutaj {[11] } jest capting 45
i %c
jest capting a
2)
(scanf("%d%c", &rows, &c)!=2 || c!='\n')
w przykładzie 1: warunek ten jest TRUE
ponieważ scanf zwraca 0
(!=2
)
w przykładzie 2: warunek ten jest FALSE
, ponieważ scanf zwraca 2
i c == '\n'
w przykładzie 3: warunek ten jest TRUE
, ponieważ scanf zwraca 2
i c == 'a' (!='\n')
3)
((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
clean_stdin()
jest zawsze TRUE
ponieważ funkcja zwraca zawsze 1
w przykładzie 1: (scanf("%d%c", &rows, &c)!=2 || c!='\n')
jest TRUE
więc warunek po &&
powinien być sprawdzony, więc clean_stdin()
zostanie wykonany, a cały warunek to TRUE
w przykładzie 2: (scanf("%d%c", &rows, &c)!=2 || c!='\n')
jest FALSE
, więc warunek po &&
nie będzie sprawdzany (ponieważ jego wynikiem będzie cały warunek będzie FALSE
), więc clean_stdin()
nie będzie wykonywany, a cały warunek będzie FALSE
w przykład3: (scanf("%d%c", &rows, &c)!=2 || c!='\n')
jest TRUE
więc warunek po &&
powinien być sprawdzony, więc clean_stdin()
zostanie wykonany, a cały warunek to TRUE
Można więc zauważyć, że clean_stdin()
zostanie wykonane tylko wtedy, gdy użytkownik wprowadzi ciąg zawierający znak nieliczbowy.
I ten warunek ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
zwróci FALSE
tylko wtedy, gdy użytkownik wprowadzi integer
i nic więcej
I jeśli warunek ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
jest FALSE
, A integer
jest pomiędzy i 1
i 23
, to pętla while
zostanie przerwana w przeciwnym razie pętla while
będzie kontynuowana
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 07:37:53
#include <stdio.h>
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]
w scanf()
pożera wszystko, co nie jest pomiędzy 0
A 9
. Zasadniczo czyści strumień wejściowy z niecyfrów i umieszcza go w str
. Długość sekwencji niecyfrowej jest ograniczona do 100. Poniższy %d
wybiera tylko liczby całkowite w strumieniu wejściowym i umieszcza je w num
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-22 11:20:29
Można utworzyć funkcję, która odczytuje liczbę całkowitą między 1 A 23 lub zwraca 0, jeśli nie-int
Np.
int getInt()
{
int n = 0;
char buffer[128];
fgets(buffer,sizeof(buffer),stdin);
n = atoi(buffer);
return ( n > 23 || n < 1 ) ? 0 : n;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-31 10:13:42
Musisz powtórzyć połączenie do strtol
wewnątrz pętli, w której prosisz użytkownika, aby spróbował ponownie. W rzeczywistości, jeśli zrobisz pętlę do { ... } while(...);
zamiast while, nie otrzymasz tego samego rodzaju powtarzania rzeczy dwa razy.
Powinieneś również sformatować swój kod tak, aby można było zobaczyć, gdzie kod znajduje się w pętli, a nie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-31 08:55:11
MOHAMED, Twoja odpowiedź jest świetna i naprawdę mi pomogła. Tutaj zamieściłem kod, który moim zdaniem jest nieco prostszy:
#include <stdio.h>
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.
// (i.e '\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 (i.e 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;
}
W moim przypadku chcę, aby liczba była tylko dodatnia. Jeśli chcesz, aby Twoja liczba wynosiła od 1 do 23, zamień number<0
na number<1 || number>23
w instrukcji if . Musisz również zmienić printf
, aby wydrukować odpowiednią wiadomość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-09 13:03:54
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
Jeśli dane wejściowe są number, możesz użyć foo
jako danych wejściowych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 02:41:49