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 :

Vérifier si une entrée est bien un entier positif


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2015
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2015
    Messages : 15
    Par défaut Vérifier si une entrée est bien un entier positif
    Bonjour,

    Je viens demander de l'aide car je ne trouve pas de solution seul à mon "problème". J'ai écrit un programme qui fonctionne du coup je peaufine les détails. Mon programme vise à effectuer un certain nombre d'opérations de flou sur une image. Quand je lance le programme sur cygwin, je demande en 3ème argument le nombre d'itérations à effectuer (cas que je ne peux changer, le programme est demandé ainsi).

    Du coup voici mes variables déclarés et ce que j'ai fait pour le moment :

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     // Définition des différentes variables + images
      image im_ori, im_res;
      int x,y,h,l,a,i;
     
    ...
     
     // Vérification du nombre d'itérations à effectuer
          const char *s = (argv[3]);
          test_entier(s);
     
          sscanf(argv[3], "%d", &a);
     
        if (a < 0) {
          printf("Le nombre d'itérations saisi est négatif !\n");
          usage(argv[0]);
        } else if (a == 0) {
          printf("Aucune opération de flou effectuée.\n");
          usage(argv[0]);
        }
     
        if (a == (int)(a)) {
        } else {
        usage(argv[0]);
        }"
     
    La fonction test_entier :
     
    if(sscanf(s,"%d",&x) == 1){
        }
        else{
          printf("%s n'est pas un chiffre !\n",s);
          exit(1);
        }
    C'est à la fin qu'il y a un problème. J'ai bien réussi à bloquer le programme si le nombre est négatif, s'il commence par une lettre (d, d85 par exemple) mais je ne sais pas faire :
    - stopper le programme si on tape 10.5
    - stopper le programme si on tape 58ef

    Des idées ?

    Merci d'avance ! (je suis débutant en C)

  2. #2
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Bonjour,

    Premièrement tu te dois de tester le retour du sscanf. Si argv[3] est une chaine de caractères non numérique, sscanf doit te retourner 0, car elle n'a pas réussie à faire une conversion.

    Deuxièmement, comme tu passes un format "%d" à la fonction sscanf, elle te retournera que la valeur entière du nombre décimal ou de la première valeur numérique.
    Exemples
    1. pour "10.5" --> sscanf(...) = 1 --> a = 10
    2. pour "58bf" --> sscanf(...) = 1 --> a = 58
    3. pour "tt87ff" --> sscanf(...) = 0 --> Erreur de paramètre



    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
        // 1. Tester si argv[3] est renseigné
        if(argv[3]==NULL) {
            printf("Manque le paramètre n°3 !\n") ;
            return EXIT_FAILURE ;
        }
        // 2. Récupère la valeur numérique ENTIERE
        else if(sscanf(argv[3], "%d", &a)==1) {
            // Test la valeur négative ou nulle
            if(a<0 || a==0) {
                printf("Paramètre n°3 faux !\n") ;
                return EXIT_FAILURE ;
            }
            printf("Nombre d'itérations = %d\n", a) ;
        }
        // 3. Si erreur de paramètre n°3 si différent d'une valeur numérique
        else {
            printf("Erreur de paramètre n°3 ! \n") ;
            return EXIT_FAILURE ;
        }
    Si tu veux un filtrage plus poussé et arrêter le programme car les paramètres ne sont pas correctes, alors il te faut utiliser d'autres fonctions complémentaires (les tiennes ou celles déjà existante).

    Bonne continuation.

  3. #3
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    effectivement les regex qu'on peut passer dans la chaine de formatage de sscanf sont pas suffisantes pour valider l'intégralité de la chaine, à partir du moment où la fonction trouve au moins une occurrence elle va renvoyer ok

    perso j'aurais limite tendance à mettre sscanf de coté et faire une fonction maison, le principe est simple; le premier caractère de la chaine peut éventuellement être un signe -, tout le reste doit obligatoirement compris entre 0 et 9 inclus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int _isnum (char *s) {
       int i = 0;
       do {
          if (!(s[i] >= '0' && s[i] <= '9') /* si le caractere n'est pas compris entre 0 et 9 */
           && !(s[i] == '-' && i == 0))     /* et que ce n'est pas non plus un signe '-' en debut de chaine */
             return 1; /* alors on sort : ce n'est pas un nombre */
       } while (s[++i]);
       return 0; /* arrivé ici, c'est que tout s'est bien déroulé dans la boucle, donc la chaine est un nombre */
    }

  4. #4
    Membre chevronné
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Par défaut
    Citation Envoyé par BufferBob
    effectivement les regex qu'on peut passer dans la chaine de formatage de sscanf sont pas suffisantes pour valider l'intégralité de la chaine
    La chaîne de format de scanf n’a rien à voir avec les regexp…

    Citation Envoyé par BufferBob
    perso j'aurais limite tendance à mettre sscanf de coté
    Moi aussi, surtout que si le nombre en entrée est trop grand et fait un overflow c’est un undefined behavior.
    Citation Envoyé par ISO/IEC 9899:TC3, 7.19.6.2 §10
    […]If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
    On notera que l’implementation de la glibc positionne errno à ERANGE mais ça n’a rien de standard.

    Citation Envoyé par BufferBob
    faire une fonction maison
    Perso, j’utiliserait fgets + strtol (qui permet bien de détecter et gérer les différents cas d’erreurs), pas besoin de réinventer la roue en moins bien…

  5. #5
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    Citation Envoyé par grim7reaper Voir le message
    La chaîne de format de scanf n’a rien à voir avec les regexp…
    c'est un abus de langage c'est vrai, j'aurais sans doute du parler des possibilités offertes par les spécificateurs de format de la chaine de formatage ou similaire, au temps pour moi

    Citation Envoyé par grim7reaper Voir le message
    Perso, j’utiliserait fgets + strtol (...), pas besoin de réinventer la roue en moins bien…
    en plus d'être capable de faire bien mieux n'hésite pas si le coeur t'en dis à donner un exemple d'implémentation et/ou des explications supplémentaires, il semblerait que ce soit de nature à aider flo557

    je répond d'ailleurs ici à la question qu'il me posait par message privé plus tôt dans la journée :
    Citation Envoyé par flo557
    si j'utilise ta fonction avec mon argument, dans le main je peux mettre _instnum(argv[3]) ?
    oui (il suffisait de tester ^^)

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2015
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2015
    Messages : 15
    Par défaut
    Bonsoir,

    Merci à tous pour vos commentaires, j'ai un peu avancé sur le sujet mais ça bloque toujours... Voici le code (en partie sinon c'est long) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int _isnum (char *s) {
       int j = 0;
       do {
          if (!(s[j]) >= '0'){ /* si le caractere n'est pas compris entre 0 et 9 */
             printf("Ceci n'est pas un nombre !");
    		 usage(); /* alors on sort : ce n'est pas un nombre */
    	}else if ((s[j]) <= '9'){
    		 printf("test");
    		 usage();
    		 }
       } while (s[++j]);
       return 0; /* arrivé ici, c'est que tout s'est bien déroulé dans la boucle, donc la chaine est un nombre */
      return(0);
    }
    J'ai enlevé le && du code de BufferBob en essayant || à la place, ça n'a pas fonctionné ni en séparant les conditions comme ci-dessus... Savez-vous d'où provient mon problème ?

    Merci par avance pour votre temps

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 16/10/2012, 13h39
  2. Comment vérifier si une application est bien démarrée
    Par emile.coue dans le forum Weblogic
    Réponses: 1
    Dernier message: 28/05/2010, 17h39
  3. Vérifier qu'une hiérarchie est bien organisée
    Par tendre_amie007 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 04/08/2009, 16h43
  4. Vérifier qu'une partition est bien montée
    Par Olivier Regnier dans le forum Linux
    Réponses: 6
    Dernier message: 30/03/2008, 00h29
  5. Réponses: 3
    Dernier message: 12/10/2006, 16h39

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