Fiabilisation des lectures au clavier
Problèmes liés à scanf: rencontre de caractères invalides Sans arrêt prématuré: compte = scanf(``%d%c``;&n,&c); 12a donne: n=12, c=`a` et compte=2 compte = scanf(``%d%d``;&n,&p); 12 45e10 donne: n=12, p=45 et compte=2 Avec arrêt prématuré: compte = scanf(``%d%d %c``;&n,&p,&c); b donne: n=12, p=25, c=`b`, compte=3 12b donne: n=12, p inch., c inch., compte=2 b donne: tout inchangé et compte =0 Prog peut boucler sur caractère invalide
Problème lié à scanf caractère fin de ligne est ambiguë c’est à la fois un séparateur et un caractère. Valider une entrée au clavier reviens à introduire le caractère `\n`dans le buffer, où il est susceptible d’être lu comme tel: printf(``donner un nombre: \n``); scanf(``%d``,&n); printf(``merci pour %d\n``,n); printf(``donner un caractère: \n``); scanf(``%c``,&c);
Problème lié à scanf manque de synchronisation entre lecture et affichage Int n,p; printf(``donner une valeur pour n: ``); scanf(``%d``,&n); printf(``merci pour %d\n``,n); printf(``donner une valeur pour p: ``); scanf(``%d``,&p); printf(``merci pour %d\n``,p); Donner une valeur pour n: Merci pour 12 Donner une valeur pour p: Merci pour 25
Démarche: Remplacer une lecture par scanf dans un format donné par deux opérations successives Lecture d’une chaîne représentant une ligne complète censée correspondre aux informations à lire (sous un format) Conversion de cette chaîne en un certain nombre d’informations, en utilisant le format, associé à sscanf
Scanf seul int n,n_val_ok; float x; char mot[31]; do{ while(1){ printf(``donner un entier, un flottant et une chaîne: \n``); n_va_ok = scanf(``%d %e %30s``, &n, &x, mot); if (n_val_ok ==3) break; printf(```*** réponse incorrect ***\n``); } printf(``merci pour %d, %e et %s \n``, n, x, mot); } while( n!=0 );
Scanf seul: résultat Donner un entier, un flottant et une chaîne: salut Merci pour e+00 et salut Donner un entier, un flottant et une chaîne: bonjour 10 Merci pour e+00 et bonjour Donner un entier, un flottant et une chaîne: hello Merci pour e+01 et 7.5 Donner un entier, un flottant et une chaîne: *** reponse incorrecte *** Donner un entier, un flottant et une chaîne: *** reponse incorrecte *** Donner un entier, un flottant et une chaîne: *** reponse incorrecte *** Donner un entier, un flottant et une chaîne:
Utilisation de gets int n,n_val_ok; float x; char mot[31], ligne[41]; do{ while(1){ printf(``donner un entier, un flottant et une chaîne: \n``); gets(ligne); n_va_ok = sscanf(ligne,``%d %e %30s``, &n, &x, mot); if (n_val_ok ==3) break; printf(```*** réponse incorrect ***\n``); } printf(``merci pour %d, %e et %s \n``, n, x, mot); } while( n!=0 );
Utilisation de gets Donner un entier, un flottant et une chaîne: salut Merci pour e+00 et salut Donner un entier, un flottant et une chaîne: bonjour 10 Merci pour e+00 et bonjour Donner un entier, un flottant et une chaîne: hello Merci pour e+00 et hello Donner un entier, un flottant et une chaîne: bye *** reponse incorrecte *** Donner un entier, un flottant et une chaîne: Merci pour e+00 et 3 Donner un entier, un flottant et une chaîne: Merci 0 0 et 0
utilisation de fgets contre le débordement #define LG_LIGNE 41 int n,n_val_ok; float x; char mot[31], ligne[LG_LIGNE]; do{ while(1){ printf(``donner un entier, un flottant et une chaîne: \n``); fgets(ligne,LG_LIGNE, stdin); n_va_ok = sscanf(ligne,``%d %e %30s``, &n, &x, mot); if (n_val_ok ==3) break; printf(```*** réponse incorrect ***\n``); } printf(``merci pour %d, %e et %s \n``, n, x, mot); } while( n!=0 );
utilisation de fgets contre le débordement Donner un entier, un flottant et une chaîne: salut Merci pour e+00 et salut Donner un entier, un flottant et une chaîne: bonjour 10 Merci pour e+00 et bonjour Donner un entier, un flottant et une chaîne: hello Merci pour e+00 et hello Donner un entier, un flottant et une chaîne: Merci pour e+00 et 11 Donner un entier, un flottant et une chaîne: Merci pour e+02 et 666 Donner un entier, un flottant et une chaîne: Merci 0 0 et 0
Pour ignorer les caractères excédentaires #define LG_LIGNE 41 …. do{ while(1){ printf(``donner un entier, un flottant et une chaîne: \n``); fgets(ligne,LG_LIGNE, stdin); n_va_ok = sscanf(ligne,``%d %e %30s``, &n, &x, mot); if (n_val_ok ==3) break; printf(```*** réponse incorrect ***\n``); } printf(``merci pour %d, %e et %s \n``, n, x, mot); if((strlen(ligne)==LG_LIGNE-1) && (ligne[LG_LIGNE-2]!=`\n`)) do c=getchar(); while (c != `\n`); } while( n!=0 );
Pour ignorer les caractères excédentaires Donner un entier, un flottant et une chaîne: salut Merci pour e+00 et salut Donner un entier, un flottant et une chaîne: bonjour 10 Merci pour e+00 et bonjour Donner un entier, un flottant et une chaîne: hello Merci pour e+00 et hello Donner un entier, un flottant et une chaîne: Merci pour e+00 et 11 Donner un entier, un flottant et une chaîne: 9 9 Bye Merci pour e+00 et Bye Donner un entier, un flottant et une chaîne: Merci 0 0 et 0