Débutant en C >>> veux obliger une saisie en int sans que ça plante

Débutant en C >>> veux obliger une saisie en int sans que ça plante - Programmation

Marsh Posté le 20-04-2001 à 09:00:00    

mon problème va vous sembler tout simple :
 
j'ai un int appelé reponse;
 
reponse doit être compris entre 3 et 21
 
je demande à l'utilisateur de saisir un nombre compris entre ces valeurs
 
à côté, j'ai un tableau d'int contenant toutes ces valeurs, une fois reponse mis à jour par le mec, je vérifie que la valeur saisie corresponde bien à l'une des valeurs de mon tableau de concordance
 
si le mec tape 3, ça fonctionne
si le mec tape 3.2, ça fonctionne aussi (normal)
si le mec tape 2, je l'envoie bouler
si le mec tape 34, je l'envoie bouler
 
quand reponse == int, ça marche
 
si maintenant le mec tape 2.2, ça plante (je suis dans une boucle, je n'en sors pas)
si le mec s'amuse à taper 'c' (enfin, un char quoi), même problème
 
pour une saisie en float, je pense faire un cast pour forcer la conversion en int avant de tester la valeur avec le tableau de concordance
 
mais si c'est un caractère non numérique ?
 
Z'avez une 'tite idée toute simple ?


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 20-04-2001 à 09:00:00   

Reply

Marsh Posté le 20-04-2001 à 09:14:51    

ben tu lis une chaine de caracteres et ensuite tu fais toi meme la conversion. Je  crois que dans ce cas c'est la solution la plus simple.

Reply

Marsh Posté le 20-04-2001 à 09:20:13    

Voici le bout de code actuel, comment verriez-vous le truc ?
 
int tablo[19] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21},
 reponse = 0,
 i,
 etat;
 
etat = 0;
do
{
 printf ("Donnez un nombre compris entre 3 et 21 : " );
 scanf ("%d", &reponse);
 i = 0;
 while (i < 19)
 {
  if (reponse != tablo[i])
   ++i;
  else
  {
   etat = 1;
   break;
  }
 }
} while (etat != 1);


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 20-04-2001 à 10:21:03    

up


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 20-04-2001 à 10:35:28    

Tu te complique la vie ou g pas compris ce ke tu veux faire:
 
do {  
  printf ("Donnez un nombre compris entre 3 et 21 : " );  
  scanf ("%d", &reponse);  
} while ((reponse < 3) || (reponse > 21));
 
Ca devrais suffire.
 
Y'aura peut-êrte une conversion float->int à faire, je sais pû trop !

Reply

Marsh Posté le 20-04-2001 à 10:38:51    

Mog, à la base, j'avais fait mon do while exactement comme l'exemple que tu as montré
 
C'est quand j'ai vu que ça plantait par exemple en tapant 2.1 que j'ai cru qu'avec un tableau pour comparer, le problème allait disparaître
 
donc oui, je me complique la vie avec mon propre exemple, puisque lui comme le tiens ne fonctionnent pas


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 20-04-2001 à 10:51:12    

en fait je crois que la solution est :
 

Code :
  1. int lire=0;
  2. do {
  3.   lire=Lire_Nombre_3_21();
  4. } while (lire==0);
  5. int Lire_Nombre_3_21(void) {
  6.   char s[255];
  7.   int  l;
  8.   cahr c;
  9.   int  n;
  10.   scanf("%s",s);
  11.   l=strlen(s);
  12.   if (l<1) return(0); 
  13.   c=s[0];
  14.   if ((c>47) && (c<58)) {
  15.     n=c-48;
  16.     }
  17.   else {
  18.     return(0);
  19.     }
  20.   if (l>1) {
  21.     c=s[1];
  22.     if ((c>47) && (c<58)) {
  23.       n=n*10+(c-48);
  24.       }
  25.     else {
  26.       return(0);
  27.       }   
  28.     }
  29.   if (n<3) return(0);
  30.   if (n>23) return(0);
  31.   return(n);
  32. }


 
voila qqc qui devrait marcher, ca fait un peu bidouille et jepense qu'il existe surement de meilleure solution, mais c'est deja une solution

Reply

Marsh Posté le 20-04-2001 à 10:54:07    

Sinon il y a d'autres fonctions pour ce que tu veux faire
 deja isdigit pour savoir si c'est un chiffre ( plus sympa qu'un tableau)
 sinon atoi qui permet egalement de convertir une chaine en entier sans planter.


---------------
[:seblamb] Moi aussi je veux grater dédé!!!
Reply

Marsh Posté le 20-04-2001 à 10:57:41    

Pourquoi tu n'utiliserais pas un compteur qui terminera la boucle au bout d'un certain nb d'essais :
int nb_essais=10;
do  
{  
printf ("Donnez un nombre compris entre 3 et 21 : " );  
scanf ("%d", &reponse); /*<- la conversion en int est implicite ici (%d) : 2.2 devient 2 */
if (reponse>=3 && reponse<=21) { break; }
} while (nb_essais-- > 0);
if (nb_essais) { printf("Ok\n" ); }

Reply

Marsh Posté le 20-04-2001 à 11:09:53    

Merci pour les 3 exemples les gars, cool ! doit bien y avoir l'une de vos méthodes qui fonctionne :)
 
pour le isdigit(), j'y avais pensé mais ne voyait pas trop comment le mettre en oeuvre
 
par contre, pour le atoi(), je vais essayer !


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 20-04-2001 à 11:09:53   

Reply

Marsh Posté le 20-04-2001 à 18:25:55    

Dans l'idée, c'est darkoli qui présente la meilleure solution. Maintenant pour le code lui-même, désolé, mais il est à s'arracher les cheveux... Je te propose de modifier son code comme suit :
 

Code :
  1. #include <string.h>
  2. #include <ctype.h>
  3. typedef int BOOL;
  4. #define TRUE  1
  5. #define FALSE 0
  6. int  entier = lis_entier(3, 21);
  7. int lis_entier(int borneMin, int borneMax) {
  8.     char  chaine[255];
  9.     int   entier = 0;
  10.     BOOL  OK;
  11.     int   i;
  12.     do {
  13.         OK = TRUE;
  14.         scanf("%s", chaine);
  15.         /* On déchiffre l'entier. */
  16.         for (i = 0; i < strlen(chaine); i++) {
  17.             if (!isdigit(chaine[i])) {
  18.                 /* Si un des caractères lus n'est pas un chiffre, on arrête de déchiffrer. */
  19.                 OK = FALSE;
  20.                 break;
  21.             }
  22.             entier = 10 * entier + (chaine[i] - '0');
  23.         }
  24.         /* Si on a bien lu un entier, on teste s'il est dans les bornes. */
  25.         if (OK  &&  (entier < borneMin  ||  entier > borneMax)) {
  26.             OK = FALSE;
  27.         }
  28.         /* On affiche un message d'erreur si la saisie est incorrecte. */
  29.         if (!OK) {
  30.             printf("Saisie incorrecte. Veuillez entrer un nombre entier compris entre %d et %d.\n",
  31.                    borneMin, borneMax);
  32.         }
  33.     } while (!OK);
  34.     return entier;
  35. }
 

[edit]--Message édité par BifaceMcLeOD--[/edit]

Reply

Marsh Posté le 20-04-2001 à 18:32:16    

Moi je pencherais plutôt pour un atoi comme seb. Il y a des fonctions dédiées, autant les utiliser !

Reply

Marsh Posté le 20-04-2001 à 21:45:57    

Salut Aricoh !
Quoi de neuf ?
 
Désolé, j'ai pas de réponse pour toi..


---------------
FHR
Reply

Marsh Posté le 21-04-2001 à 00:08:28    

Pourquoi convertir du char en int ?
 
On peut utiliser la valeur retournée par scanf pour tester la saisie :
 
 - 0 si char  
 - 1 si int ou float
 
Si l'utilisateur saisi des caractères on vide le buffer clavier pour ne pas planter scanf :
 
void main()
 
{float reponse;
 int r;
 reponse=1;
 r=0;
 
 while(reponse)
 
        {printf("Saisir une valeur (0 pour terminer) : " );
 
         r=scanf("%f",&reponse);
 
         if(r && reponse>=3 && reponse<=21)
 
            printf("Valeur OK\n" );
 
         else
 
            {printf("Valeur impossible\n" );
             while(getchar()!='\n'); /*Vidage buffer*/
            }
        }
}

Reply

Marsh Posté le 21-04-2001 à 00:18:05    

trasfract a écrit a écrit :

Moi je pencherais plutôt pour un atoi comme seb. Il y a des fonctions dédiées, autant les utiliser !




atoi marche très bien tant que la chaine en entrée est correcte.

Reply

Marsh Posté le 21-04-2001 à 12:56:37    

Ok, le code ci-dessous fonctionne :
 
char tablo[20];
int reponse;
 
do
{
    tablo[0] = "";
    reponse = 0;
    printf ("Donnez une valeur comprise entre 3 et 21 : " );
    gets(tablo);
    reponse = atoi(tablo);
    if (reponse < 3 || reponse > 21)
        printf ("valeur incorrecte\n" );
    printf ("reponse vaut %d\n", reponse);
}    while (reponse < 3 || reponse > 21);
    printf ("résultat OK, boucle terminée\n" );
 
 
Quelques exemples de fonctionnement :  
 
Donnez une valeur comprise entre 3 et 21 : c
valeur incorrecte
reponse vaut 0
Donnez une valeur comprise entre 3 et 21 : 1221
valeur incorrecte
reponse vaut 1221
Donnez une valeur comprise entre 3 et 21 : 2.75
valeur incorrecte
reponse vaut 2
Donnez une valeur comprise entre 3 et 21 : 134d kyz
valeur incorrecte
reponse vaut 134
Donnez une valeur comprise entre 3 et 21 : 12.27x
reponse vaut 12
résultat OK, boucle terminée
 
C'était donc bien atoi() qu'il fallait que j'utilise pour faire au + simple
 
oui oui, je sais, avec mon tablo, je ne suis pas protégé d'un fou qui taperait 50 caractères, vi vi, je sais :)
 
j'y travaille, merci à tous pour vos conseils, vous m'avez mis sur la piste qu'il fallait, cool !
 
Salut FHR, ça roule ? ;)


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 22-04-2001 à 11:07:03    

J'm'a gourré dans le code ci-dessus, l'initialisation du tableau de char est fausse, il faut plutôt lire :
 
tablo[0] = '\0';


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 23-04-2001 à 00:11:54    

Question bête : si tu tapes "10a", ton filtrage, il marche toujours ? Je n'en suis pas si sûr...

Reply

Marsh Posté le 23-04-2001 à 08:28:00    

BifaceMcLeOD a écrit a écrit :

Question bête : si tu tapes "10a", ton filtrage, il marche toujours ? Je n'en suis pas si sûr...




 
deux exemples :
 
si le bourrin tape a10, la fonction atoi s'arrête au 'a' et retourne 0
si le bourrin tape 10a, la fonction prend '10' et retourne 10, le 'a' passe à la trappe
 
j'ai testé et ça marche


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 23-04-2001 à 13:21:09    

Voici ma fonction qui utilise le ascii to int (atoi, oui oui, je sais que vous le savez, c'est juste pour me la pêter un dixième de sec :p  ) :
 
void verif_int (int *a, int nbre)
{
 char buffer[80],
      tablo[nbre+1];
 
 buffer[0] = '\0';
 tablo[0] = '\0';
 
 gets(buffer);
 strncpy(tablo, buffer, nbre);
 *a = atoi(tablo);
 return;
}
 
J'utilise cette fonction pour deux cas de figure :
 
je ne veux en retour qu'un seul nombre, ou bien deux chiffres
 
La variable nbre que je transmet en paramètres à ma fonction peut prendre 1 comme valeur ou 2
 
le tout fonctionne


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le 23-04-2001 à 18:25:00    

Aricoh a écrit a écrit :

 
 
deux exemples :
 
si le bourrin tape a10, la fonction atoi s'arrête au 'a' et retourne 0
si le bourrin tape 10a, la fonction prend '10' et retourne 10, le 'a' passe à la trappe
 
j'ai testé et ça marche




Oui, c'est exactement ce à quoi je m'attendais. Mais je ne considère pas "10a" et "a10" comme des saisies correctes...
 
Ceci dit, tu fais ce que tu veux...  :)

Reply

Marsh Posté le 24-04-2001 à 08:40:32    

BiFace, chacun son opinion
 
je n'ai besoin de cette fonction, uniquement pour que mon programme se prémunisse d'une saisie incorrecte par un abruti, rien de +
 
Le programme demande un int et le type tape des lettres, c'est lui qui se fait jeter et pas mon programme qui plante !


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed