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 :

Expression régulière


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 126
    Par défaut Expression régulière
    Bonjour,

    J'ai trouvé cet article sur les expressions régulières en C mais je n'ai pas réussi à faire ce que je voulais, peut-être m'y suis-je mal pris, peut-être aussi que la réponse à ma question ne figure pas dans l'article. En tout cas je remercie ceux et celles qui essaieront de m'aider.

    http://nicolasj.developpez.com/articles/regex/#LIV-A

    J'ai écrit un programme simple qui reçoit 5 arguments en ligne de commande argv[1], argv[2], argv[3], argv[4] et argv[5]

    Les 4 premiers paramètres attendus sont des entiers (car j'utilise dans le programme la fonction atoi sur ces 4 arguments). Je voudrais m'assurer que mon programme ne s'exécute jusqu'au bout que si ces 4 arguments sont bien des entiers, car je ne veux pas de résultats inattendus retournés par atoi.

    J'ai donc essayé ceci :

    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
    int err;
        regex_t preg;
        const char *str_regex = "[1-9][:digit:]*";
        const char *str_request = argv[1];
     
        err = regcomp (&preg, str_regex, REG_NOSUB );
     
       if (err == 0)
       {
          int match;
     
    /* (2) */
          match = regexec (&preg, str_request, 0, NULL, 0);
    /* (3) */
          regfree (&preg);
    /* (4) */
          if (match == 0)
          {
             printf ("Les arguments sont valides\n");
          }
    /* (5) */
          else if (match == REG_NOMATCH)
          {
             printf ("Les arguments sont invalides\n");
          }
        }
    Le problème c'est qu'il laisse passer ./test l4 5 5 2 mat.data mais aussi ./test 5.72 6 2 4 mat.data pour simplifier je ne teste que le premier dans le programme pour l'instant.

    Mon but final c'est que si l'un des 4 paramètres n'est pas un entier donc de la forme un chiffre de 1 à 9 suivi de n'importe quel nombre de chiffres de 0 à 9 alors j'aimerai m'en apercevoir et arrêter l'exécution.

    Quelqu'un a-t-il une idée ? Que ce soit en remplaçant atoi par une fonction plus performante, en se servant mieux des expressions régulières ou en utilisant une stratégie différente ? Merci beaucoup

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut
    Bonjour,

    ça ne marcherait pas mieux comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char str_regex[] = "^[1-9][:digit:]*$";
    Il y a un intérêt à interdire les nombres commençant par 0 ? Si ce n'est pas le cas, la déclaration suivante devrait fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char str_regex[] = "^[0-9]+$";

    PS : c'est plus court et explicite d'écrire [0-9] à la place de [:digit:]

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    est-ce que par hasard, tu ne pourrais pas plutot faire un avec un sscanf?

    exemple avec un seul argument à tester.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main (int argc, char * argv[]) {
        if (argc< <ce qui te va bien>) return false;
    
        int a;
        if (sscanf(argv[1], "%d", &a) !=1) {
            fprintf(stderr, "zut, %s n'est pas un entier", argv[1]);
            return 1;
        }
        //utiliser a.
        return 0;
    }

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Et je crois que "[:digit:]" est une classe à inclure dans un []*, ce qui donnerait plutot "^[1-9][[:digit:]]*$"Et cela n'acceptera pas le nombre 0.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 126
    Par défaut
    Merci Leternel de ta réponse,

    Ton code permet de filtrer des entrées commençant par des lettres mais sinon ça ne fonctionne pas. Par exemple : 3.4 il prend la troncature et a vaut 3 et il ne me dit pas qu'il y a un problème.

    Pareil si je rentre 3fefeafeakfa. En revanche il filtre bien quelque chose comme p3kfefe. Par ailleurs je ne l'ai peut-être pas précisé mais en fait ces paramètres sont des dimensions de matrices, aussi je veux filtrer 0. (mais à la rigeur ça peut-être filtré a posteriori).

    C'est pour ça que mon expression régulièr c'était [1-9][0-9]*

    Une autre idée ?


    -> en fait j'ai regardé la valeur de retour de sscanf et j'ai vu que ça comptait le nombre de caractères correctement lus donc j'ai modifié ton code pour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int a;
        if (sscanf(argv[1], "%d", &a) != strlen(argv[1])) {
            fprintf(stderr, "zut, %s n'est pas un entier", argv[1]);
            return 1;
        }
    et ça fait ce que je veux je n'ai plus qu'à faire un dernier test qui check si la valeur n'est pas 0.

    Merci beaucoup


    -> Ah non au temps pour moi maintenant il n'apprécie pas que je mette 343... car ce n'est pas le nombre de caractères mais le nombre d'arguments.

    Du coup j'entrevois une solution il faudrait que je loop sur les caractères de ma chaine et que je vérifie que la somme des valeurs retournées par les appels à sscanf soit égale au nombre de caractères de la chaine ?

    Ca doit marcher mais ce n'est pas très élégant.

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Effectivement, j'avais omis cette partie.

    Nous avons sur le site (mais je ne sais plus où exactement, il convient de chercher) un cours C sur la validation des entrées utilisateurs.
    Il est très bien fait.

  7. #7
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    pour t'assurer qu'une chaîne contient un entier il serait peut-être bien plus simple de passer par la fonction long long int strtoll(const char *nptr, char **endptr, int base);. La man page indique :

    If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
    Il y a également une gestion d'over/underflow et ce serait moins lourd à utiliser que les regexp.

  8. #8
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 126
    Par défaut
    Merci de ta réponse Picodev mais je n'arrive pas à me servir de la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char* pEnd;
        long long int a;
        a = strtoll(argv[1], &pEnd, 10);
    je voudrais faire un if sur pEnd pour voir si l'adresse d'un caractère a été mis mais je ne m'en sors pas. Ca ne marche pas de faire la comparaison avec une chaine vide par exemple.

Discussions similaires

  1. [RegEx] Expression régulières : Balises <SCRIPT>
    Par Gwipi dans le forum Langage
    Réponses: 2
    Dernier message: 24/04/2006, 23h25
  2. Expression réguliére
    Par Mad_Max dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 16/09/2003, 18h17
  3. [expression régulière] mon cerveau fait des noeuds..
    Par nawac dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 27/05/2003, 10h06
  4. Expressions réguliéres
    Par Tooms dans le forum Langage
    Réponses: 4
    Dernier message: 06/12/2002, 18h42
  5. Réponses: 5
    Dernier message: 11/06/2002, 15h21

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