Int et char sont dans un bateau
Résolu/Fermé
Gouager
-
Modifié par pijaku le 5/02/2014 à 12:37
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 6 févr. 2014 à 22:46
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 6 févr. 2014 à 22:46
A voir également:
- Int et char sont dans un bateau
- Coco char - Accueil - Réseaux sociaux
- Simulateur bateau - Télécharger - Loisirs créatifs
- Int converter - Télécharger - Bureautique
- Code gta vice city psp avion et bateau ✓ - Forum PSP
- Int(input()) - Forum Python
4 réponses
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié par [Dal] le 4/02/2014 à 20:03
Modifié par [Dal] le 4/02/2014 à 20:03
Salut,
Ton problème vient du fait que tu ne peux pas spécifier
Alors, la solution est d'utiliser un spécificateur de taille avec
en C89, cela marche donc mieux comme cela :
le spécificateur de taille
si tu tiens vraiment à utiliser des
http://www.cplusplus.com/reference/cstdio/scanf/
Dal
Ton problème vient du fait que tu ne peux pas spécifier
%ccar ce n'est pas un caractère que tu veux, mais un nombre décimal, et que si tu spécifies
%dsans autres précisions, c'est un int * qui doit être en paramètre.
Alors, la solution est d'utiliser un spécificateur de taille avec
%d.
en C89, cela marche donc mieux comme cela :
#include <stdio.h> int main(void) { short int nombre = 0; short int nombre1 = 0; short int nombre2 = 0; printf("saisir nombre1:\n"); scanf("%hd", &nombre1); printf("saisir nombre2:\n"); scanf("%hd", &nombre2); nombre = nombre1 + nombre2; printf("%d+%d=%d", nombre1, nombre2, nombre); return 0; }
%ddoit être utilisé, car ce que tu attends, c'est bien un nombre décimal, et pas un caractère
le spécificateur de taille
hpermet d'indiquer à scanf qu'il doit accueillir un
short int.
si tu tiens vraiment à utiliser des
char(des
signed charselon ce que tu dis), il te faudra utiliser du C99 et le spécificateur
hh, qui te permet de gérer des
signed charavec
%d.
http://www.cplusplus.com/reference/cstdio/scanf/
Dal
sambia39
Messages postés
610
Date d'inscription
vendredi 31 juillet 2009
Statut
Membre
Dernière intervention
9 février 2023
49
5 févr. 2014 à 22:30
5 févr. 2014 à 22:30
Dal à raison, scanf est un des plus complexes et dangereux, il faut contrôler ce quand passe à scanf, cependant tu peux également utilisé scanf avec les expressions pour ne vouloir ce que tu veux.
Mais il est préférable de créer une fonction par le quelle tu pourras contrôler ta saisie et en plus tu pourras les réutiliser dans d'autres projets.
Mais il est préférable de créer une fonction par le quelle tu pourras contrôler ta saisie et en plus tu pourras les réutiliser dans d'autres projets.
Ok.
Mais je pense que vu les programmes tout simple (une addition par exemple) que je rédige (ça fait seulement une semaine que j'apprends le langage C) scanf est suffisant. J'espère pouvoir le plus rapidement possible vous dire que j'arrive à m'en passer (après avoir créer ma propre fonction) :))
Enfin, peut être que bien comprendre les limites et la complexité de scanf permettra d'éviter d'autres erreurs de débutant, ou pas, par la suite sur d'autres sujets?
Gouager.
Mais je pense que vu les programmes tout simple (une addition par exemple) que je rédige (ça fait seulement une semaine que j'apprends le langage C) scanf est suffisant. J'espère pouvoir le plus rapidement possible vous dire que j'arrive à m'en passer (après avoir créer ma propre fonction) :))
Enfin, peut être que bien comprendre les limites et la complexité de scanf permettra d'éviter d'autres erreurs de débutant, ou pas, par la suite sur d'autres sujets?
Gouager.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
6 févr. 2014 à 07:13
6 févr. 2014 à 07:13
Limite de scanf ? Il n'y en a pas. Complexité ? Là oui.
Parmi les trucs les plus dangereux si on utilise mal scanf, la chaine de caractère trop grande => plantage ou modification de variables dans le code... Écriture d'un caractère au lieu d'un nombre => boucle infinie. Et j'en passe :-)
Parmi les trucs les plus dangereux si on utilise mal scanf, la chaine de caractère trop grande => plantage ou modification de variables dans le code... Écriture d'un caractère au lieu d'un nombre => boucle infinie. Et j'en passe :-)
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
6 févr. 2014 à 11:27
6 févr. 2014 à 11:27
@Gouager: bien comprendre scanf peut prendre du temps, mais te fera indéniablement progresser sur une multitude de sujets et comprendre beaucoup de finesses (ou de pièges selon les points de vue) du C. Ne te tracasse pas si tu ne comprend pas tout tout de suite, cela viendra.
@fiddy: pour une saisie sécurisée et avec un contrôle d'erreur de texte, scanf est effectivement utilisable, comme tu as pu me le montrer par le passé. Pour une saisie numérique, je ne trouve pas de moyen fiable de sécuriser une saisie sur le dépassement de capacité.
Que proposes-tu d'ajouter au code suivant :
pour éviter ceci :
comment sait-on si l'utilisateur n'a pas réellement tapé -31073 ? y a-t-il un autre contrôle d'erreur possible qui m'échappe (limiter la saisie en caractères ici n'aide pas vraiment) ?
ce sont ces difficultés qui me font préférer fgets et strtol pour valider une saisie numérique.
Dal
@fiddy: pour une saisie sécurisée et avec un contrôle d'erreur de texte, scanf est effectivement utilisable, comme tu as pu me le montrer par le passé. Pour une saisie numérique, je ne trouve pas de moyen fiable de sécuriser une saisie sur le dépassement de capacité.
Que proposes-tu d'ajouter au code suivant :
#include <stdio.h> #include <stdlib.h> #include <limits.h> int main(void) { short int nombre1 = 0; char c; int code; printf("Les valeurs acceptables pour un short int " "sont de %d à %d\n", SHRT_MIN, SHRT_MAX); printf("saisir nombre1:\n"); code = scanf("%hd", &nombre1); if (code != 1) { printf("Erreur, je n'ai pas pu lire 1 short int\n"); } if (code == EOF) { printf("Erreur : je n'ai rien pu lire\n"); code = -1; } if (feof(stdin) != 0) { printf("Erreur : le flux stdin s'est arrêté\n"); code = -1; } if (ferror(stdin)) { perror("L'erreur suivante s'est produite"); code = -1; } if (code != 1) { return EXIT_FAILURE; } else { printf("La saisie est apparemment correcte, " "vous avez entré : %d\n", nombre1); } while ((c = getchar()) != '\n' && c != EOF) /* purge de stdin pour le prochain scanf */; /* ici scanf suivant, etc. */ return 0; }
pour éviter ceci :
Les valeurs acceptables pour un short int sont de -32768 à 32767
saisir nombre1:
99999
La saisie est apparemment correcte, vous avez entré : -31073
comment sait-on si l'utilisateur n'a pas réellement tapé -31073 ? y a-t-il un autre contrôle d'erreur possible qui m'échappe (limiter la saisie en caractères ici n'aide pas vraiment) ?
ce sont ces difficultés qui me font préférer fgets et strtol pour valider une saisie numérique.
Dal
sambia39
Messages postés
610
Date d'inscription
vendredi 31 juillet 2009
Statut
Membre
Dernière intervention
9 février 2023
49
6 févr. 2014 à 15:19
6 févr. 2014 à 15:19
Bonjour, ou faire comme ceci
#include <stdio.h> const int fFormatSaisie(void){ int iVal=0; char pChar[10]={'\0'}; fgets(pChar,sizeof(pChar),stdin); sscanf(pChar, "%d", &iVal); return iVal; }
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
6 févr. 2014 à 15:47
6 févr. 2014 à 15:47
@sambia : si l'utilisateur tape "toto", tu es bien avancé avec ton code ;-)
Sur les autres questions, en testant la valeur de retour de sscanf on tombe sur les mêmes problèmes que scanf, les fonctions étant de la même famille, c'est à dire un contrôle d'erreur difficile.
@fiddy : y a-t-il quelque chose à faire avec scanf qui m'échappe ?
Dal
Sur les autres questions, en testant la valeur de retour de sscanf on tombe sur les mêmes problèmes que scanf, les fonctions étant de la même famille, c'est à dire un contrôle d'erreur difficile.
@fiddy : y a-t-il quelque chose à faire avec scanf qui m'échappe ?
Dal
sambia39
Messages postés
610
Date d'inscription
vendredi 31 juillet 2009
Statut
Membre
Dernière intervention
9 février 2023
49
6 févr. 2014 à 17:37
6 févr. 2014 à 17:37
Bonjour, je ne suis pas du tout d'accord avec toi sur certains point, et le choix de sscanf à son importance contrairement à une utilisation simple de scanf (comme le cas dans les derniers posts). Dans le cas de mon code, il fait une conversion de la chaine ou du caractère en un entier, si la chaine saisie ou le caractère tapé n'est un chiffre, alors de fait, la conversion ne pourra pas ce faire et renverra 0 grace à la valeur initialisée avec notre variable locale, et en plus cela nous permet indirectement de contrôler la saisie et laisser le temps à l'utilisateur de comprendre pourquoi le résultat de l'addition est incorrect (parce qu'il a saisi un caractère).
Et pour info scanf ou sscanf renvoient le nombre d'éléments d'entrée correctement mis en correspondance, ce nombre peut-être plus petit que le nombre d'éléments attendus, et même être nul, s'il y a une erreur de mise en correspondance.
Et l'on remarquera que je n'ai pas utilisé scanf mais bien fgets dans ma fonction puis sscanf pour transtyper et ainsi contrôler la saisie, et je me préoccupe pas du retour d'erreur de sscanf car s'il n'a pas transtypé il renverra 0 la valeur de ma variable.
Et pour info scanf ou sscanf renvoient le nombre d'éléments d'entrée correctement mis en correspondance, ce nombre peut-être plus petit que le nombre d'éléments attendus, et même être nul, s'il y a une erreur de mise en correspondance.
Et l'on remarquera que je n'ai pas utilisé scanf mais bien fgets dans ma fonction puis sscanf pour transtyper et ainsi contrôler la saisie, et je me préoccupe pas du retour d'erreur de sscanf car s'il n'a pas transtypé il renverra 0 la valeur de ma variable.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
6 févr. 2014 à 21:26
6 févr. 2014 à 21:26
Bonjour,
@[Dal],
Il n'y a hélas pas de moyen standard de contrôler finement une saisie numérique avec scanf() comme tu le souhaites. La norme ne requiert pas le placement de ERANGE dans errno en cas de nombre en dehors des bornes (contrairement à strtol()).
Il faut donc lire la chaîne au format texte et utiliser strtol() pour conversion.
Mais même, l'utilisation de fgets() (ou scanf() en faisant attention)/strtol()des deux n'est pas si simple. Il y a pas mal de piège. D'où l'intérêt de se faire une bonne fois pour toute une fonction de lecture sécurisée pour la réutiliser comme tu l'as indiqué ;-).
Cdlt,
@[Dal],
Il n'y a hélas pas de moyen standard de contrôler finement une saisie numérique avec scanf() comme tu le souhaites. La norme ne requiert pas le placement de ERANGE dans errno en cas de nombre en dehors des bornes (contrairement à strtol()).
Il faut donc lire la chaîne au format texte et utiliser strtol() pour conversion.
Mais même, l'utilisation de fgets() (ou scanf() en faisant attention)/strtol()des deux n'est pas si simple. Il y a pas mal de piège. D'où l'intérêt de se faire une bonne fois pour toute une fonction de lecture sécurisée pour la réutiliser comme tu l'as indiqué ;-).
Cdlt,
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
6 févr. 2014 à 22:46
6 févr. 2014 à 22:46
ok, j'espérais que tu aies dans ton escarcelle une astuce avec scanf de derrière les fagots dont tu as le secret :-D
merci de ton feedback fiddy
Dal
merci de ton feedback fiddy
Dal
5 févr. 2014 à 12:07
Sous Linux, en revanche, le code suivant marche bien en passant à gcc l'option -std=c99 :
Cela dit, scanf ne te permettra qu'un très faible contrôle d'erreur. C'est mieux de faire autrement pour lire un nombre de façon robuste.
Lis ceci à ce sujet pour comprendre pourquoi.
Dal
5 févr. 2014 à 12:33
Le lien de la première réponse va beaucoup m'aider je pense car en fait je pense ne pas avoir compris ce que signifie char. Pour moi mettre char devant une variable signifie OBLIGATOIREMENT et UNIQUEMENT que cette variable est un entier compris entre -127 et +128.
Donc mettre %c+%c je voyais cela comme la "simple addition " de deux nombres entiers. Or cela peut être le cas (Cf votre exemple) mais ce n'est pas SYSTEMATIQUEMENT le cas.
Pouvez vous juste me préciser à quoi corresponde dans le tableau qui s'appelle specifiers les termes de la ligne suivante:
length d i u o x f e g a c s [] [^] p n
Je suis qu'au début de la leçon (une dizaine de page) sur C mais je me rends compte qu'on pourrait déjà écrire un livre sur ces quelques pages :))
Modifié par [Dal] le 5/02/2014 à 15:05
Le standard définit comme étant un type entier, devant être suffisamment grand pour stocker tous les éléments du codage de caractères utilisé par défaut à l'exécution. La valeur entière représentant un caractère est alors garantie comme étant positive.
La taille d'un peut varier selon l'implémentation (le compilateur et l'environnement pour lequel le compilateur est sensé produire des exécutables).
le standard définit des valeurs minimales pour les limites d'un , qui sont effectivement -127 et +127 (pas 128).
Cependant, chaque implémentation peut définir des limites supérieures.
Les valeurs effectivement pertinentes pour ton compilateur sont définies dans qui doit contenir un et un .
2.
Il faut aussi comprendre la différence entre le caractère et sa valeur numérique (son code ASCII dans le codage de caractères ASCII).
voilà une illustration de ce que je te dis ci-avant :
chez moi ce code produit :
3.
Le tableau auquel tu fais référence sur la page http://www.cplusplus.com/reference/cstdio/scanf/ et qui contient une colonne dénommée "length" est le 3ème tableau présent sur cette page, qui est un tableau explicatif des sous-spécificateurs ("length sub-specifier") de taille utilisables avec les spécificateurs de type mentionnés dans le 1er tableau.
Les différentes colonnes " " visent ces spécificateurs de type utilisés par scanf, et le tableau permet de déterminer les types C correspondants effectivement attendus lorsque tu les combines avec des sous-spécificateurs de taille tels que , , , , etc. (qui sont les lignes du tableau)
est une des instructions les plus complexes du C.
Dal
5 févr. 2014 à 20:28
5 févr. 2014 à 21:00
Encore merci de la qualité de tes explications.
Gouager