[.C]saisir uniquement un nombre

Hello les geeks, je bloque dans un petit programme à coder pour un dossier. Le problème est le suivant: je dois premettre à l’utilisateur d’encoder le nombre de lignes et de colonnes d’un tableau, mais si l’utilisateur appuie bêtement sur une lettre au lieu de rentrer un nombre ça cause une boucle infinie. Voici mon code:
[codebox]printf(“Combien de lignes doit comporter le tableau?\n”);
scanf("%d",&lig);
while(lig<0 || lig>20)
{
printf(“Choississez entre 1 et 20 lignes:\n”);
scanf("%d",&lig);
}
printf("\n");[/codebox]

Quel serait le moyen le plus simple de mettre un message d’erreur quand l’utilisateur rentre une lettre ou un bombre trop grand/trop petit? Je suis obligé d’utiliser le scanf aussi.

Tu peut peut etre utiliser la fonctin atoi …

j’ essaye et j’ edite

edit :

[code]char char_ligne[3];
int int_ligne =-1;

while(int_ligne<0 || int_ligne>20 || int_ligne == 0)
{
if(int_ligne==0) {printf(“tsss tsss un nombre on a dit !\n”);}
else {printf(“Choississez entre 1 et 20 lignes:\n”);}
scanf("%s",&char_ligne);
int_ligne=atoi(char_ligne);
}
printf("\n");[/code]

atoi converti les caractere ascii en entier , si le caractere n’ ets pas un entier alors elle renvoie 0 .
Ya peut etre plus elegant masi ca marche.

edit2: rajoue de message d’ erreur

Utilises plutot fgets:
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fgetc

Si tu initialise lig a -1 avant de faire ton scanf, et qu’il n’y a pas de nombre dans la chaine passer, ca devrait marcher, normalement.

@ vorkosigan et alt3 : Merci pour vos réponses, je les garde pour plus tard, mais on est censé travailler uniquement avec scanf ou, à la limite, getch. :slight_smile:

@ c0unt0: j’ai le même problème si je rentre une lettre: boucle infinie

cheloud, j’aurais pense que ca aurait marche…

pour moi le pb est que tu tests pas le retour de ton scanf.
Donc quand tu passes autres choses qu’une valeur non valide, ca fait n’importe quoi.

La solution de c0unt0 est la bonne finalement :slight_smile: il manquait juste un fflush(stdin) avant chaque scanf. Je vais tester dans un autre programme où j’ai un problème similaire mais ça devrait marcher.

Gargl, oublie ce qu’on peut raconter sur ce genre de pratiques et fais une cure de désyntoxication sur les pages qu’a linkées alt3, vite ! scanf() est overkill et mal utilisée dans 99,9% des cas, atoi() est dépréciée et fflush() ne doit pas être utilisée avec des flux sur lesquels la dernière opération était entrante, donc sûrement pas stdin.
Ça prend un peu de temps pour comprendre comment faire des saisies correctes mais ça t’évitera de traîner des bugs et du code non portable dans tous tes programmes. :crying:

Relis mon premier post: je suis OBLIGE d’utiliser cette fonction, c’était dans le cadre d’un dossier à rendre pour un cours :slight_smile: Enfin on avance dans la matière et on devrait arrêter d’utiliser scanf d’ici peu de toute façon

[autocongrat on]
Ca me rassure, je ne suis pas tant a la ramasse que ca donc :crying:
[autocongrat off]

toutafé :crying: un grand merci :slight_smile:

Je déterre ce thread car j’ai un petit souci avec la fameuse fonction atoi (oui on a enfin arrêté l’usage du scanf aux cours :)).

Elle marche parfaitement pour convertir une chaîne de caractères en entier, mais ça ne marche pas si j’essaie de convertir un seul caractère, exemple:

[codebox]chiffre[0]=getchar();
choix=atoi(chiffre);[/codebox]

[codebox]chiffre=getchar();
choix=atoi(chiffre);[/codebox]

La première solution marche, pas la deuxième. Est-ce que atoi peut convertir un seul caractère ou bien faut-il utiliser une autre fonction (et laquelle svp)?

[quote=« Lupuss, post:13, topic: 46688 »]Je déterre ce thread car j’ai un petit souci avec la fameuse fonction atoi (oui on a enfin arrêté l’usage du scanf aux cours :crying:).

Elle marche parfaitement pour convertir une chaîne de caractères en entier, mais ça ne marche pas si j’essaie de convertir un seul caractère, exemple:

[codebox]chiffre[0]=getchar();
choix=atoi(chiffre);[/codebox]

[codebox]chiffre=getchar();
choix=atoi(chiffre);[/codebox]

La première solution marche, pas la deuxième. Est-ce que atoi peut convertir un seul caractère ou bien faut-il utiliser une autre fonction (et laquelle svp)?[/quote]
putain je repond a cette heure la moi, pfiou
tu devrais lire la doc ou le manpage lupuss, et tu verrais:
int atoi(const char *nptr);
Oh, y a une netoile? ca veut dire que je doit passer un pointeur, dinnnngue
donc
[codebox]chiffre=getchar();
choix=atoi(&chiffre);[/codebox]
Revision, pointeur, passage par valeur, et tout ca, ca te fera pas de mal :cry:

LoneWolf
c’est quand meme la base, il fait quoi votre prof la? :slight_smile:

Les pointeurs ont été vus, les pointeurs de pointeurs aussi. C’est pas le prof, c’est moi qui ne lis pas correctement le prototype de la fonction. Désolé :slight_smile:

atoi() est dépréciée parce qu’elle ne permet pas de traiter correctement les erreurs, utilise strtol() :

[code]#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
char chaine[] = “123”;
char *p_carInv;
long resConversion;

errno = 0;
resConversion = strtol (chaine, &p_carInv, 10);

/* si débordement */
if (errno == ERANGE)
{

}
/* si tous les caractères sont valides et qu’il n’y a pas de débordement */
else if (p_carInv == ‘\0’)
{
printf ("%ld\n", resConversion);
}
/
si caractères invalides */
else
{

}

return 0;
}[/code]

Si tu veux convertir un seul caractère retranche-lui la valeur qui représente le caractère ‘0’.

[quote=“LoneWolf, post:14, topic: 46688”]putain je repond a cette heure la moi, pfiou
tu devrais lire la doc ou le manpage lupuss, et tu verrais:
int atoi(const char *nptr);
Oh, y a une netoile? ca veut dire que je doit passer un pointeur, dinnnngue
donc

chiffre=getchar(); choix=atoi(&chiffre);
Revision, pointeur, passage par valeur, et tout ca, ca te fera pas de mal :crying:

LoneWolf
c’est quand meme la base, il fait quoi votre prof la? :)[/quote]
L’adresse doit être celle d’une chaîne, c’est dans la documentation aussi…

ça marche aussi avec un caractère unique je t’assure (comme dans l’exemple de LoneWolf). Et pour la vérification, il a un switchcase plus loin donc si la valeur entrée ne correspond pas à une option du menu l’utilisateur a droit à un message d’erreur. Merci quand même!

Ça marche dans certains cas si par chance le byte qui suit le caractère vaut zéro :

[code]#include <stdio.h>
#include <stdlib.h>

int main (void)
{
char c = ‘1’;
char *p;

p = &c;
*(p+1) = ‘2’;
*(p+2) = 0;

/* affiche 12 au lieu de 1 */
printf ("%d\n", atoi(&c));

return 0;
}[/code]

Ou il y a un truc qui m’échappe…
Apparemment atoi() peut faire l’affaire si tu ne veux pas que l’utilisateur entre zéro, sinon tu ne pourras pas savoir si il a bien entré zéro ou si c’est une erreur de conversion. Elle ne t’avertit pas non plus si il y a un débordement ou si il y a des caractères anormaux après un nombre :

[code]#include <stdio.h>
#include <stdlib.h>

int main (void)
{
char c[] = “123pouet”;

/* affiche 123 */
printf ("%d\n", atoi©);

return 0;
}[/code]

Justement il ne peut pas entrer zéro ici: ça va seulement de 1 à 5. Mais je note cette restriction pour les cas futurs!

kineox me signale que je dis des conneries dans ce thread et c’est vrai, il etait plus de 23h et j’ai faute.

lupuss, ecoute dap, il a raison et je vais me planquer dans la foret et m’autoflageller avec des branches de pin des landes

LoneWolf
Maxi Honte Powered