Voici le problème d'un jeune jeu avec le code C qui tente simplement d'empêcher l'utilisateur de saisir un caractère ou un entier inférieur à 0 ou supérieur à 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;
}
Je l'ai fait à mi-chemin et un petit Push Up sera apprécié.
Utilisez scanf("%d",&rows)
au lieu de scanf("%s",input)
Cela vous permet d'obtenir directement la valeur entière de stdin sans avoir besoin de convertir en int.
Si l'utilisateur entre une chaîne contenant des caractères non numériques, vous devez nettoyer votre stdin avant la prochaine scanf("%d",&rows)
.
votre code pourrait ressembler à ceci:
#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;
}
Explication
1)
scanf("%d%c", &rows, &c)
Cela signifie que l'utilisateur doit entrer un entier et un caractère non numérique.
Exemple1:Si l'utilisateur entre aaddk
puis ENTER
, le scanf retournera 0. Rien capturé
Exemple2:Si l'utilisateur entre 45
puis ENTER
, le scanf retournera 2 (2 éléments sont capturés). Ici %d
capture 45
et %c
capture \n
Exemple3:Si l'utilisateur entre 45aaadd
puis ENTER
, le scanf retournera 2 (2 éléments sont capturés). Ici %d
capture 45
et %c
capture a
2)
(scanf("%d%c", &rows, &c)!=2 || c!='\n')
Dans l'exemple1:cette condition est TRUE
car scanf renvoie 0
(!=2
)
Dans l'exemple2:cette condition est FALSE
car scanf renvoie 2
et c == '\n'
Dans l'exemple3:cette condition est TRUE
car scanf renvoie 2
et c == 'a' (!='\n')
3)
((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
clean_stdin()
est toujours TRUE
car la fonction renvoie toujours 1
Dans l'exemple1:Le (scanf("%d%c", &rows, &c)!=2 || c!='\n')
est TRUE
; la condition après le &&
doit donc être vérifiée pour que la clean_stdin()
soit exécutée et que la condition entière soit TRUE
Dans l'exemple2:Le (scanf("%d%c", &rows, &c)!=2 || c!='\n')
est FALSE
et la condition après le &&
ne sera pas cochée (car quel que soit le résultat, la condition entière sera FALSE
), de sorte que clean_stdin()
ne sera pas exécuté et que la condition entière est FALSE
Dans l'exemple3:Le (scanf("%d%c", &rows, &c)!=2 || c!='\n')
est TRUE
, la condition après le &&
doit donc être vérifiée pour que la clean_stdin()
soit exécutée et que la condition entière soit TRUE
Vous pouvez donc remarquer que clean_stdin()
sera exécuté uniquement si l'utilisateur entre une chaîne contenant un caractère non numérique.
Et cette condition ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
retournera FALSE
uniquement si l'utilisateur entre integer
et rien d'autre
Et si la condition ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
est FALSE
et que la integer
est comprise entre et 1
et 23
, la boucle while
sera interrompue, sinon la boucle while
continuera
#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]
dans scanf()
engloutit tout ce qui n'est pas entre 0
et 9
. Fondamentalement, il nettoie le flux d’entrée de chiffres non numériques et le met dans str
. La longueur de la séquence non numérique est limitée à 100. Le %d
suivant sélectionne uniquement les entiers dans le flux d'entrée et le place dans num
.
Vous pouvez créer une fonction qui lit un entier compris entre 1 et 23 ou renvoie 0 s'il n'est pas int
par exemple.
int getInt()
{
int n = 0;
char buffer[128];
fgets(buffer,sizeof(buffer),stdin);
n = atoi(buffer);
return ( n > 23 || n < 1 ) ? 0 : n;
}
Vous devrez répéter votre appel à strtol
dans vos boucles pour demander à l'utilisateur de réessayer. En fait, si vous faites de la boucle une do { ... } while(...);
au lieu de tout le temps, vous n'obtiendrez pas le même type de comportement.
Vous devez également formater votre code afin qu’il soit possible de voir où se trouve le code dans une boucle et non.
MOHAMED, votre réponse est excellente et m'a vraiment aidé. Ici, j'ai posté un code, que je pense un peu plus simple:
#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;
}
Dans mon cas, je veux que le nombre soit simplement positif. Si vous voulez que votre numéro soit compris entre 1 et 23, vous remplacez le number<0
par number<1 || number>23
dans l'instruction if . De plus, vous devrez changer la printf
pour imprimer un message approprié.
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
Si l'entrée est un nombre, vous pouvez utiliser foo
comme entrée.