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 :

Commentaires sur ma fonction isnumber(char *)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut Commentaires sur ma fonction isnumber(char *)
    Bonjour,

    Je me suis donné comme exercice de C d'écrire une petite calculatrice RPN. Le code pour le stack est écrit et semble bien fonctionner, je me suis donc attaqué à la tokenisation du input. Afin de savoir si un token est un nombre, j'ai écrit une fonction. J'ai écrit un douzaines de tests unitaires, et la fonction semble les passer tous, par contre je trouve ma fonction longue et un peu compliquée. J'apprécierais des commentaires de nature fonctionnelle, stylistique, de sécurité, de fiabilité, de portabilité, etc.

    Merci.

    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
    34
    35
    36
    37
    38
    39
     
    int isnumber(char *s)
    {
        size_t i;
        size_t len;
        int period = 0;
     
        /* Skip over white spaces. */
        while (isspace(*s))
            ++s;
     
        if (*s == '+' || *s == '-')
            s++;
     
        i = 0;
        len = strlen(s);
     
        if (len == 0)
            return 0;
     
        for (i = 0; i < len; ++i) {
            /* Only one period is allowed */
            if (!period && s[i] == '.') {
                period++;
            }
            else if (period && s[i] == '.') {
                return 0;
            }
            /* Ignore everything after a space */
            else if (isspace(s[i])) {
                return 1;
            }
            else if (!isdigit(s[i])) {
                return 0;
            }
        }
     
        return 1;
    }

  2. #2
    Membre très actif Avatar de Goundy
    Profil pro
    Étudiant
    Inscrit en
    Avril 2005
    Messages
    605
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2005
    Messages : 605
    Par défaut
    Salut,

    Vite fait tu peux réduire ton code en fesant appel à la bonne fonction sscanf.
    Donc tu fais des appels successifs de cette fonction (entiers et réels, 2 appels max?) et là c'est good
    Compil your life guy!
    The Aures Project

  3. #3
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Ton code ne fait pas toujours ce que tu veux. Notamment, il retourne vrai pour " .", "+ " ou "- ". Voici ton code remanié avec mes commentaires et quelques tests unitaires (Il y a probablement plus simple, mais c'est un point de départ):

    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
     
    /* -tc- Je recommande de passer un pointeur sur un tableau de caracteres
       non modifiable en argument. ATTENTION: les identificateurs ayant la 
       forme is[a-z]* sont reserves pour l'implantation. Je modifie le nom
       de ta fonction en is_number */
    int is_number(char const *s)
    {
        /* -tc- Attention: si s est NULL, tu obtiens une erreur de 
           segmentation. Je recommande de tester la valeur de s */
        int ret = 0;
     
        if (s != NULL)
        {
            size_t len = strlen(s);
     
            /* -tc- Si la chaine est vide chiffre, on sait que ce n'est pas 
               un nombre */
            if (len > 0)
            {
                int err = 0;
     
                /* -tc- perso, je suis contre modifier la valeur de s. 
                   Si un jour tu veux modifier ta fonction et que, pour 
                   une raison x ou y, tu as besoin de recuperer l'adresse 
                   du debut de ta chaine... */
                char const *pc = s;
     
                /* Skip over white spaces. */
                /* -tc- C'est une question de gouts, mais je recommande de tjs
                   utiliser les accolades, meme pour les blocs de 1 
                   instruction */
                /* -tc- Il est conseille de convertir les caracteres passes aux
                   fonctions is*() en unsigned char declarees dans ctype.h avant 
                   la conversion implicite en int */
                while (isspace((unsigned char) *pc))
                {
                    ++pc;
                }
     
                if ((*pc == '+' || *pc == '-'))
                {
                    ++pc;
                }
     
                /* -tc - Le probleme de ton implantation, c'est qu'elle accepte
                   comme nombre les chaines "+ ", "- ", ".". Voila l'algo que
                   j'implanterais */
                if (isdigit((unsigned char) *pc))
                {
                    while (isdigit((unsigned char) *pc))
                    {
                        ++pc;
                    }
     
                    if (*pc == '.')
                    {
                        ++pc;
                    }
     
                    while (isdigit((unsigned char) *pc))
                    {
                        ++pc;
                    }
                }
                else if (*pc == '.')
                {
                    ++pc;
                    /* -tc- Pour avoir un nombre, '.' doit etre au moins suivit
                       d'un chiffre. */
                    if (isdigit((unsigned char) *pc))
                    {
                         while (isdigit((unsigned char) *pc))
                        {
                            ++pc;
                        }
                    }
                    else
                    {
                        err = 1;
                    }
                }
                else
                {
                    err = 1;
                }
     
     
                if (!err && (*pc == 0 || isspace((unsigned char) *pc)))
                {
                    ret = 1;
                }
            }
        }
     
        return ret;
    }
     
    /* -tc- test unitaire */
    struct test {
        char const *data;
        int result;
    };
     
    int main(void)
    {
        struct test tdata[] = {
            {"123.1234", 1},
            {"   123.1234", 1},
            {"+123.1234", 1},
            {"   +123.1234", 1},
            {"   + 123.1234", 0},
            {"   -123.1234", 1},
            {"  +", 0},
            {"  + ", 0},
            {"  .", 0},
            {"  . ", 0},
            {"  +.", 0},
            {"  +. ", 0},
            {"  +.0", 1},
            {"   a123.1234", 0},
            {"   123a.1234", 0},
            {"   123.1234a", 0},
            {"   +123.1234a", 0},
            {"+123.1234 a", 1}
        };
        size_t i;
        int err = 0;
     
        for (i = 0; i < sizeof tdata / sizeof *tdata; i++)
        {
            int rv = is_number(tdata[i].data);
            printf("Test %02u: %-15s... ", (unsigned int) i, tdata[i].data);
     
            if (rv == tdata[i].result)
            {
                printf("passed!\n");
            }
            else
            {
                printf("failed!\n");
                err = 1;
            }
        }
        printf("\n");
     
        if (err == 0)
        {
            printf("P A S S E D!\n");
        }
     
        return EXIT_SUCCESS;
    }
    Note que si ton but est autre que pédagogique, tu peux faire plus simple à l'aide de strtol() ou sscanf(), comme cela déjà été dit.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

Discussions similaires

  1. fonctions de char sur nbre
    Par zdagzdag dans le forum C
    Réponses: 4
    Dernier message: 12/07/2006, 18h03
  2. doc sur les fonctions
    Par masterfab dans le forum C
    Réponses: 18
    Dernier message: 23/06/2005, 17h55
  3. [VB6] Ajouter un commentaire à une fonction d'une DLL
    Par Ace303 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 05/06/2003, 08h14
  4. PerlDoc sur une fonction d'un module
    Par lesouriciergris dans le forum Modules
    Réponses: 2
    Dernier message: 13/03/2003, 20h50

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