IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Contrôle des saisies utilisateurs


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    novembre 2019
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : novembre 2019
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Contrôle des saisies utilisateurs
    Bonsoir à tous,

    dans le cadre de mon programme de chiffrement, j'ai voulu contrôler les saisies de l'utilisateur dans le cas où il ferait une mauvaise saisie qui provoquerait une boucle infinie ainsi que pour des problèmes de sécurité.

    Plus précisément, j'ai voulu contrôler l'input suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ... 
    do {
    printf("\nR : ");
    scanf("%d",&r);
    }while(r<0||r>1);
    Si l'utilisateur entre un caractère ou un string, une boucle infinie apparaît. J'ai cherché quelques heures et avec plusieurs essais de suite jusqu'à trouver le code suivant (concluant et qui a résout totalement le problème) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ...
    char buff[1024];
    int r;
    if(!fgets(buff,1024,stdin))
            {
                return 1;
            }
            char *endptr;
            errno=0;
            r=strtol(buff,&endptr,10);
     
            if(errno==ERANGE)
                success=0;
            else if(endptr==buff)
                success=0;
            else if(*endptr && *endptr != '\n')
                success=0;
            else
                success=1;
     
        }while(r<0||r>1||(!success));
    Cependant, je ne comprends pas quelques trucs dans le code :

    - Pourquoi déclarer un pointeur char sur endptr ? (je sais que c'est le premier caractère qui n'a pas pu être converti par la fonction atoi() mais est-il vraiment nécessaire de le déclarer?)
    - Je ne comprends pas ce que fait la condition - Et enfin, la troisième condition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    else if(*endptr && *endptr != '\n');
    ; pourquoi utiliser deux pointeurs à la fois ? pourquoi on écrit pas tout simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    else if(*endptr!='\n');
    Merci à vous

    PS : on peut faire plus simple et plus court que ce code ?

  2. #2
    Expert éminent
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    mai 2010
    Messages
    3 105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : mai 2010
    Messages : 3 105
    Points : 9 752
    Points
    9 752
    Par défaut
    - Pourquoi déclarer un pointeur char sur endptr ? (je sais que c'est le premier caractère qui n'a pas pu être converti par la fonction atoi() mais est-il vraiment nécessaire de le déclarer?)
    Oui vu que strtol demande un double pointeur en argument.

    else if(*endptr && *endptr != '\n');
    Le premier vérifie si *endptr est égal à NULL ou pas , (pour ça qu'il est mieux de faire des conditions explicites).
    C'est une bonne pratique de vérifier si le pointeur est valide.

    PS : on peut faire plus simple et plus court que ce code ?
    L'importance est la clarté du code , faire du code trop court peut empêcher le compilo d'optimiser.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    9 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 9 801
    Points : 26 732
    Points
    26 732
    Billets dans le blog
    1
    Par défaut
    Bonsoir
    Citation Envoyé par Grandstone Voir le message
    - Pourquoi déclarer un pointeur char sur endptr ? (je sais que c'est le premier caractère qui n'a pas pu être converti par la fonction atoi() mais est-il vraiment nécessaire de le déclarer?)
    Ce pointeur est destiné à pointer sur le premier caractère de la chaine qui n'a pas été converti. Ce caractère étant un "char", un pointeur sur ce caractère sera un "char *". Toutefois si tu n'as pas besoin de cette info tu as le droit de mettre "NULL" pour ce paramètre. Et c'est strtol(), pas atoi().

    Citation Envoyé par Grandstone Voir le message
    PS : on peut faire plus simple et plus court que ce code ?
    Oui. En utilisant sscanf(). Cette fonction récupère l'info non pas au clavier mais depuis une string. Et comme elle renvoie le nombre d'infos récupérées, tu peux utiliser ce retour pour vérifier que cette fonction a bien récupéré un truc.

    Toutefois je te conseillerais de sérialiser tes besoins. En effet, ils peuvent être découpés en 2
    1. obliger l'utilisateur à saisir un nombre
    2. évaluer ce nombre par rapport aux besoins de ton algo


    Le premier étant plus "universel", tu peux lui affecter une fonction dédiée ce qui te permettra de la réutiliser à différents moments de ton programme. Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int saisieNbr(char *prompt) {
    	char saisie[1024];
    	int nbr;
    	while (1) {
    		fputs(stdout, prompt);
    		fflush(stdout);
    		fgets(saisie, 1024, stdin);
    		if (sscanf(saisie, "%d", &nbr) == 1) return nbr;
    		fputs("Saisie incorrecte, recommencez !!!\n", stdout);
    	}
    }

    Et le second étant plus "spécifique" à un moment précis de ton algo, pourra alors être géré par l'appelant. Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while (1) {
    	nb=saisieNbr("Voulez-vous gagner 1M (0=non, 1=oui) ?");
    	if (nb == 0 || nb == 1) break;
    	fputs("Seulement 0 ou 1 !!!\n");
    }
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

Discussions similaires

  1. [Python 2.X] python raspberry -j'ai besoin d'aide à propos de mon code
    Par edeh roger dans le forum Général Python
    Réponses: 0
    Dernier message: 14/12/2017, 16h50
  2. [SFML 2.0] Aide à la compréhension d'un bout de code, pour tilemapping.
    Par Jeano81 dans le forum SFML
    Réponses: 3
    Dernier message: 20/10/2016, 18h24
  3. [AC-2003] Debutant - Besoin d'aide pour décrypter un bout de code
    Par jossdu39 dans le forum VBA Access
    Réponses: 2
    Dernier message: 25/09/2015, 11h44
  4. Aide pour un bout de code
    Par DeVit dans le forum Scripts/Batch
    Réponses: 6
    Dernier message: 17/05/2009, 15h23
  5. Besoin d'aide pour comprendre ce bout de code
    Par sorry60 dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 21/03/2009, 17h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo