Partage
  • Partager sur Facebook
  • Partager sur Twitter

zIdentificator

Exercice de niveau intermédiaire

    14 juin 2010 à 16:39:12

    Oui, c'est les résultat du test. Mais on voit les chaînes testées, non?
    • Partager sur Facebook
    • Partager sur Twitter
    Zeste de Savoir, le site qui en a dans le citron !
    Anonyme
      14 juin 2010 à 16:39:50

      Alors qu'appels-tu donc un test ? Et qu'appels-tu alors, écrire les tests ?
      • Partager sur Facebook
      • Partager sur Twitter
        14 juin 2010 à 16:49:24

        Tu prends les chaines testés, tu les rentres dans un taleau, puis tu appliques ta fonction sur chaque chaine en notant le résultat (comme indiqué).
        • Partager sur Facebook
        • Partager sur Twitter
          14 juin 2010 à 16:58:47

          Citation : GurneyH

          candide l'ai a montré un peu plus haut.

          toto       : 1
          toto42     : 1                                                                                                
          Toto       : 1
          c          : 1
          to         : 1                                                                                                
          _          : 1                                                                                                
          _t         : 1
          _toto      : 1                                                                                                
          _bool      : 1                                                                                                
          _4         : 1
          _42_toto   : 1
                     : 0                                                                                                
          4          : 0
          42         : 0
          4_         : 0
          to-to      : 0
          __         : 0
          __toto     : 0                                                                                                
          _Toto      : 0
          _____      : 0
          goto       : 0
          return     : 0
          _Bool      : 0


          Exactement, rien de mystérieux ni decompliqué (pas d'assert ni de protocole de test):


          void test(char *id)
          {
            printf("%-10s : %d\n", id, zIdentificator(id));
          }
          
          
          int main(void)
          {
            char *z[] =
                 { "toto", "toto42", "Toto", "c", "to", "_", "_t", "_toto", "_bool", "_4","_42_toto", "", "4", "42", "4_","to-to","__",
          "__toto",
              "_Toto", "_____", "goto", "return", "_Bool"
            };
            int i;
          
            int n = sizeof z / sizeof *z;
          
            for (i = 0; i < n; i++)
              test(z[i]);
          
            return 0;
          }
          
          • Partager sur Facebook
          • Partager sur Twitter
            15 juin 2010 à 8:30:23

            Citation : candide

            Exactement, rien de mystérieux ni decompliqué (pas d'assert ni de protocole de test)



            Merci Candide. C'est marrant, parce que parle de tests, on s'imagine que je ne sais pas faire un test, comme si c'était trivial, honteux ou méprisable de d'intéresser aux tests. Alors que ma préoccupation est plutôt de tout tester afin de fournir un code robuste. J'ai l'habitude d'utiliser assert. Je crois que c'est Fvirtman qui dit souvent que "toute tâche répétitive est automatisable". Alors tu vas effectivement me dire que ce n'est pas ta préoccupation première, ce que je comprends tout à fait dans un cadre scolaire. Mais tu es quand même obligé d'analyser les résultats à la main et tu ne testes pas toutes les règles que tu as données.

            Pour ce programme de test, il faut un fichier c "test_cname.c" avec le corps de la fonction et un fichier "test_cname.h" avec son prototype. Et là, tout le processus de test est automatisé.

            #include "test_cname.h"
            // anti multi include test
            #include "test_cname.h"
            
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
            #include <assert.h>
            #include <ctype.h>
            
            int test_zIdentificator(const char* word_under_test)
            {
                printf("\r                                                                             ");
                printf("\rTesting %s ", word_under_test);
                return zIdentificator(word_under_test);
            }
            
            int unit_tests(void)
            {
                const char* invalid_cnames[] =
                {
                    "auto", "break", "case", "char", "const", "continue", "default",
                    "do", "double", "else", "enum", "extern", "float", "for", "goto",
                    "if", "inline", "int", "long", "register", "restrict", "return",
                    "short", "signed", "sizeof", "static", "struct", "switch", "typedef",
                    "union", "unsigned", "void", "volatile", "while", "_Bool", "_Complex", "_Imaginary",
                    "_", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                    "__", "_A", "_B", "_C", "_D", "_E", "_F", "_G", "_H", "_I", "_J",
                    "_K", "_L", "_M", "_N", "_O", "_P", "_Q", "_R", "_S", "_T", "_U",
                    "this_is_a_long_invalid Cname", NULL, "",
                    "_V", "_W", "_X", "_Y", "_Z",
                    "__", "_A", "_B", "_C", "_D", "_E", "_F", "_G", "_H", "_I", "_J",
                    "_K", "_L", "_M", "_N", "_O", "_P", "_Q", "_R", "_S", "_T", "_U",
                    "_V", "_W", "_X", "_Y", "_Z",
                    "__this__is__not__a__long__valid__Cname__",
                    "_This__is__not__a__long__valid__Cname__",
                    "42_toto", "__toto", "to-to", "_Toto"
            
                };
                const char* valid_cnames[] =
                {
                    "_0", "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9",
                    "A", "B", "r", "D", "E", "F", "G",
                    "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
                    "S", "T", "U", "V", "W", "X", "Y", "Z",
                    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
                    "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
                    "w", "x", "y", "z",
                    "_a", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "_k",
                    "_l", "_m", "_n", "_o", "_p", "_q", "_r", "_s", "_t", "_u", "_v",
                    "_w", "_x", "_y", "_z",
                    "this__is_a_long_valid_Cname",
                    "_this__is__a__long__valid__Cname__",
                    "toto42", "toto_42", "_toto", "_42toto_", "goto_toto"
                };
                size_t index;
                size_t index_max;
            
            
                assert(test_zIdentificator("42_toto") == EXIT_FAILURE);
            
                // test of invalid words
                index = 0;
                index_max = sizeof invalid_cnames / sizeof(char*);
                while(index < index_max)
                    assert(test_zIdentificator(invalid_cnames[index++]) == EXIT_FAILURE);
            
                // test of some valid words
                index = 0;
                index_max = sizeof valid_cnames / sizeof(char*);
                while(index < index_max)
                    assert(test_zIdentificator(valid_cnames[index++]) == EXIT_SUCCESS);
            
                puts("\n\nA L L   T E S T S   P A S S E D !");
                return EXIT_SUCCESS;
            }
            
            int main(void)
            {
                return unit_tests();
            }
            



            J'ai bien évidemment écrit la fonction zIdentificator, mais de façon industrielle, donc plus avec un souci de lisibilité que de performances. Je pense que ça n'a aucun intérêt de la poster. Il reste le problème de la taille max des cnames. J'ai déjà utilisé en embarqué des compilos qui tronquent purement et simplement au dessus de 32 octets sans le moindre warning.
            • Partager sur Facebook
            • Partager sur Twitter
              15 juin 2010 à 13:45:26

              Citation : pfeuf


              Merci Candide. C'est marrant, parce que parle de tests, on s'imagine que je ne sais pas faire un test, comme si c'était trivial, honteux ou méprisable de d'intéresser aux tests. Alors que ma préoccupation est plutôt de tout tester afin de fournir un code robuste. J'ai l'habitude d'utiliser assert.


              J'ai tendance également à écrire les tests AVANT le code...
              Je ne crois pas que quelqu'un est avancé ici, que tester était honteux. o_O

              Regarde sur la première page(ma proposition pour cet exo), il me semble que je testes... Pas le tests de candide, mais des tests tout de même...

              Tu en penses quoi?






              • Partager sur Facebook
              • Partager sur Twitter
              Zeste de Savoir, le site qui en a dans le citron !
                15 juin 2010 à 14:02:08

                Citation : pfeuh

                C'est marrant, parce que parle de tests, on s'imagine que je ne sais pas faire un test



                Je n'ai jamais imaginé cela par contre en te lisant je me doutais que tu allais me suggérer ce que tu fais plus loin (les tests en mode -ed-)



                Citation : pfeuh


                C'est marrant, parce que parle de tests, on s'imagine que je ne sais pas faire un test, comme si c'était trivial, honteux ou méprisable de d'intéresser aux tests. </secret>



                Non c'est essentiel mais c'est aussi essentiellement simple.


                Citation : pfeuh


                J'ai l'habitude d'utiliser assert.



                Visiblement c'est comme cela qu'on fait les tests dans le milieu industriel.


                Citation : pfeuh

                Je crois que c'est Fvirtman qui dit souvent que "toute tâche répétitive est automatisable"



                Suf que justement la partie significative du test n'est pas automatisable. Après on peut se donner des illusions.

                Citation : pfeuh

                Alors tu vas effectivement me dire que ce n'est pas ta préoccupation première, ce que je comprends tout à fait dans un cadre scolaire.



                C'est en effet une préocupation secondaire dans un cadre d'apprentissage.

                Citation : pfeuh

                Mais tu es quand même obligé d'analyser les résultats à la main



                Ta phrase est ambiguë (comment interpréter le "quand même" ou le "tu" ?).


                Citation : pfeuh

                tu ne testes pas toutes les règles que tu as données.



                Quand tu dis "tu", tu veux dire que le test que j'ai proposé plus haut ne teste pas toutes les règles ? c'est ça ? Par définition, un programme de test ne teste pas tout. Par définition, on traite un échantillon.

                Citation : pfeuh


                Pour ce programme de test, il faut un fichier c "test_cname.c" avec le corps de la fonction et un fichier "test_cname.h" avec son prototype. Et là, tout le processus de test est automatisé.



                Tu as la réaction assez typique de pas mal d'informaticiens qui confondent le contenant et le contenu : t'as juste mis en place une usine à gaz qui tourne à vide ou qui accouche d'une souris.

                Ton code donc :

                Citation : pfeuh


                #include "test_cname.h"
                // anti multi include test
                #include "test_cname.h"
                
                #include <stdio.h>
                #include <stdlib.h>
                #include <string.h>
                #include <assert.h>
                #include <ctype.h>
                
                int test_zIdentificator(const char* word_under_test)
                {
                    printf("\r                                                                             ");
                    printf("\rTesting %s ", word_under_test);
                    return zIdentificator(word_under_test);
                }
                
                int unit_tests(void)
                {
                    const char* invalid_cnames[] =
                    {
                        "auto", "break", "case", "char", "const", "continue", "default",
                        "do", "double", "else", "enum", "extern", "float", "for", "goto",
                        "if", "inline", "int", "long", "register", "restrict", "return",
                        "short", "signed", "sizeof", "static", "struct", "switch", "typedef",
                        "union", "unsigned", "void", "volatile", "while", "_Bool", "_Complex", "_Imaginary",
                        "_", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                        "__", "_A", "_B", "_C", "_D", "_E", "_F", "_G", "_H", "_I", "_J",
                        "_K", "_L", "_M", "_N", "_O", "_P", "_Q", "_R", "_S", "_T", "_U",
                        "this_is_a_long_invalid Cname", NULL, "",
                        "_V", "_W", "_X", "_Y", "_Z",
                        "__", "_A", "_B", "_C", "_D", "_E", "_F", "_G", "_H", "_I", "_J",
                        "_K", "_L", "_M", "_N", "_O", "_P", "_Q", "_R", "_S", "_T", "_U",
                        "_V", "_W", "_X", "_Y", "_Z",
                        "__this__is__not__a__long__valid__Cname__",
                        "_This__is__not__a__long__valid__Cname__",
                        "42_toto", "__toto", "to-to", "_Toto"
                
                    };
                    const char* valid_cnames[] =
                    {
                        "_0", "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9",
                        "A", "B", "r", "D", "E", "F", "G",
                        "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
                        "S", "T", "U", "V", "W", "X", "Y", "Z",
                        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
                        "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
                        "w", "x", "y", "z",
                        "_a", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "_k",
                        "_l", "_m", "_n", "_o", "_p", "_q", "_r", "_s", "_t", "_u", "_v",
                        "_w", "_x", "_y", "_z",
                        "this__is_a_long_valid_Cname",
                        "_this__is__a__long__valid__Cname__",
                        "toto42", "toto_42", "_toto", "_42toto_", "goto_toto"
                    };
                    size_t index;
                    size_t index_max;
                
                
                    assert(test_zIdentificator("42_toto") == EXIT_FAILURE);
                
                    // test of invalid words
                    index = 0;
                    index_max = sizeof invalid_cnames / sizeof(char*);
                    while(index < index_max)
                        assert(test_zIdentificator(invalid_cnames[index++]) == EXIT_FAILURE);
                
                    // test of some valid words
                    index = 0;
                    index_max = sizeof valid_cnames / sizeof(char*);
                    while(index < index_max)
                        assert(test_zIdentificator(valid_cnames[index++]) == EXIT_SUCCESS);
                
                    puts("\n\nA L L   T E S T S   P A S S E D !");
                    return EXIT_SUCCESS;
                }
                
                int main(void)
                {
                    return unit_tests();
                }
                




                Dans le genre code cliquant, tu atteins des sommets, je pense en plus que tu dois être fier de toi. Typiquement le genre de code que je n'aime pas voir sur le sdz car ça assome le débutant ainsi même que celui qui est déjà bien avancé alors que c'est du creux. Et j'adore le très naïf puts("\n\nA L L T E S T S P A S S E D !"); qui croit qu'après ça on a tout résolu.

                L'intelligence des tests n'est pas dans cette carapace formelle, elle est dans le choix des exemples de test et ça c'est un processus qui ne peut pas s'automatiser ou alors ça nécessite des moyens considérables avec un risque de surenchère et de complexification du code dont la seule gestion va conduire à de nouvelles erreurs.


                Tes exemples de tests sont très naïfs, la production des exemples n'est pas automatisée, tu as fait un gros copié-collé de la liste des mots-clés, tu as écrit à la main "_0", "_1", etc, "a", "b", "c" , etc bref tu fais toi aussi du bricolage, tu sauves seulement les apparences. Si tu veux des tests plus fiables, il faut créer des générateurs aléatoires de mots-clés, et encore, faut-il que le générateur prenne en compte certaines lois de construction des mots clés pour garder un certain réalisme aux tests.

                Venons-en au contenu de ton code.

                *) Le code contient deux en-têtes inutiles (ctype et string ).
                *) Tu te trompes quant au fait que _ serait un identificateur invalide. De même, il est incorrect de tester le pointeur NULL (comme valide ou invalide), en tous cas, cela va à l'encontre des pratiques reeconnues.
                *) Tes utilisations de assert contiennent des effets de bord (++ est un effet de bord), c'est une mauvaise pratique car assert est une macro, pas une fonction, qu'est-ce qui t'assure que l'implémentation de assert ne provoque pas plusieurs évaluation de son argument ?
                *) Ta définition de index_max n'est pas très pro (ton code, vu sa complexité, est censé être pro, non ?). On écrira plutôt : index_max = sizeof invalid_cnames / sizeof * invalid_cnames;
                *) Le choix d'un index_max n'est "pas très C". Il me semble plus idiomatique de placer un NULL dans le tableau comme condition d'arrêt. C'est d'autant plus embêtant que tu définis index_max à deux endroits différents avec des syntaxes indentiques (tu fais à nouveau de la duplication de code). Ton code compliqué risque de faire faire des erreurs pendants les tests, un comble quand même, ça obligerait pour un peu à tester tes tests !!
                *) Tu supposes que zIdentificator() peut renvoyer EXIT_FAILURE . Or, il a bien été dit que
                zIdentificator renvoie 0 ou 1. Tu ne crois quand même pas que EXIT_FAILURE vaut l'un des deux, si ?
                Et quand bien même ne le croirais-tu pas, c'est extrêmement maladroit. Les macros EXIT_FAILURE et EXIT_SUCCESS ont une sémantique "système", on ne va donc pas les utiliser pour répondre à un test de format de chaîne de caractère. C'est à peu après aussi étrange que si la fonction standard isdigit renvoyait l'un ou l'autre. Résultat des courses : avec ton usine à gaz de test, ma fonction zIdentificator() qui a la bonne spécification ne passe pas un seul de tes tests, quelle réussite ! Pour que ton code de test marche, il faut que j'écrive :

                assert(test_zIdentificator(invalid_cnames[index++]) == EXIT_SUCCESS);
                

                ce qui va contre l'intuition.




                Citation : pfeuh


                J'ai bien évidemment écrit la fonction zIdentificator, mais de façon industrielle, donc plus avec un souci de lisibilité que de performancines.



                Comprends rien à ce que tu dis. Qu'est-ce que ça vient faire cette histoire de "façon industrielle" ? Et ça veut dire quoi "avec un souci de lisibilité que de performancines" (ça peut s'interpréter de deux façons différentes).

                De toutes façons, tu aurais été infiniment plus clair, au lieu de nous poster ton code de tests, de répondre à la question posée dans ce post et de nous proposer ton fameux code industriel de zIdentificator .



                Citation : pfeuh

                Je pense que ça n'a aucun intérêt de la poster.



                Ah bon ? Et c'est quoi le thème de ce topic ?



                Citation : pfeuh

                Il reste le problème de la taille max des cnames. J'ai déjà utilisé en embarqué des compilos qui tronquent purement et simplement au dessus de 32 octets sans le moindre warning.



                La question peut en effet se poser, je te le concède. Et c'est d'ailleurs ce que dit la Norme en 5.2.4.1 Translation limits.
                • Partager sur Facebook
                • Partager sur Twitter
                  15 juin 2010 à 17:16:36

                  Bonjour !
                  Voici mon essai :) :

                  #include <stdio.h>
                  #include <string.h>
                  #include <ctype.h>
                  
                  #define N 37
                  #define M 13
                  
                  static const char *mc[N] = {"auto", "break", "case", "char", "const", "continue", "default", "do",
                                               "double", "else", "enum", "extern", "float", "for", "goto", "if",
                                               "inline", "int", "long", "register", "restrict", "return", "short",
                                               "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
                                               "unsigned", "void", "volatile", "while", "_Bool", "_Complex", "_Imaginary"};
                  
                  int isKeyWord(const char *id)
                  {
                      int i = 0;
                      for (i = 0 ; i < N ; i++)
                          if (!strcmp(id, mc[i]))
                              return 1;
                      return 0;
                  }
                  
                  int isValid(const char *id)
                  {
                      for ( ; *id ; id++)
                          if (!isalnum(*id) && *id != '_')
                              return 0;
                      return 1;
                  }
                  
                  int zIdentificator(const char *id)
                  {
                      if (*id == '_' && (*(id+1) == '_' || isupper(*(id+1))))
                          return 0;
                      return strlen(id) && !isdigit(*id) && isValid(id) && !isKeyWord(id);
                  }
                  
                  int main(void)
                  {
                      int i = 0;
                      const char *s[M] = {"toto_42", "_toto", "_42toto_", "goto_toto", "42_toto",
                                           "__toto", "to-to", "_ Toto", "_Toto", "goto", "_Imaginary",
                                           "with space", ""};
                      for (i = 0 ; i < M ; i++)
                          printf("%s : %s\n", s[i], zIdentificator(s[i]) ? "Valide" : "Non Valide");
                      return 0;
                  }
                  

                  • Partager sur Facebook
                  • Partager sur Twitter
                    15 juin 2010 à 17:32:53

                    _Imaginary : Non Valide

                    :)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      15 juin 2010 à 17:40:07

                      Citation : HighTam


                      return strlen(id) && !isdigit(*id) && isValid(id) && !isKeyWord(id);
                      




                      Pourquoi ne pas écrire *id au lieu de strlen(id) ce qui est bien moins couteux et en plus te libère de l'inclusion de string.h.

                      Sinon, je trouve qu'il n'est pas pratique de mettre des constantes de taille (genre M ou N chez toi) à des tableaux initialisés définitivement.

                      En principe, on caste les arguments aux fonctions de ctype.h (c'est ce que les bons font en tout cas).
                      • Partager sur Facebook
                      • Partager sur Twitter
                        15 juin 2010 à 18:13:39

                        Citation : Pouet_forever

                        _Imaginary : Non Valide


                        :)


                        C'est juste ! Non ? _Imaginary est un mot clé !

                        Citation : candide

                        Pourquoi ne pas écrire *id au lieu de strlen(id) ce qui est bien moins couteux et en plus te libère de l'inclusion de string.h.


                        Effectivement ! Ça m'a échappé !

                        Citation : candide

                        Sinon, je trouve qu'il n'est pas pratique de mettre des constantes de taille (genre M ou N chez toi) à des tableaux initialisés définitivement


                        Je n'ai pas trop compris ce que tu veux dire ! Qu'est ce que je fais alors ?

                        Citation : candide

                        En principe, on caste les arguments aux fonctions de ctype.h (c'est ce que les bons font en tout cas).


                        Conversion char <==> int n'est elle pas implicite ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          15 juin 2010 à 18:20:38

                          @pfeuh: tu t'es emballé je crois. Reviens quelques pages en arriève et regarde ce que chacun de nous a réalisé: la fonction plus le programme de test qui appel la fonction réalisée... beaucoup de bruit pour rien.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            15 juin 2010 à 19:00:13

                            Citation : HighTam


                            Citation : candide

                            Sinon, je trouve qu'il n'est pas pratique de mettre des constantes de taille (genre M ou N chez toi) à des tableaux initialisés définitivement


                            Je n'ai pas trop compris ce que tu veux dire ! Qu'est ce que je fais alors ?



                            Comme la plupart font, tu récupères la taille en faisant un quotient de sizeof.



                            Citation : HighTam


                            Citation : candide

                            En principe, on caste les arguments aux fonctions de ctype.h (c'est ce que les bons font en tout cas).


                            Conversion char <==> int n'est elle pas implicite ?



                            C'est pas le problème. La Norme dit :

                            Citation : C99, <ctype.h>

                            In all cases the argument is an int, the value of which shall be
                            representable as an unsigned char or shall equal the value of the macro EOF. If the
                            argument has any other value, the behavior is undefined.



                            Donc pour être sûr qu'une valeur (int) qui ne serait pas dans la bonne plage te fasse pas planter le programme, tu castes en unsigned char. Au moins, tu n'as pas un bug. Mais en même temps, ça peut masquer un problème de conception, c'est pour ça que j'ai jamais trop aimé cette méthode.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              15 juin 2010 à 19:07:44

                              Citation : candide

                              Citation : HighTam


                              Citation : candide

                              Sinon, je trouve qu'il n'est pas pratique de mettre des constantes de taille (genre M ou N chez toi) à des tableaux initialisés définitivement


                              Je n'ai pas trop compris ce que tu veux dire ! Qu'est ce que je fais alors ?



                              Comme la plupart font, tu récupères la taille en faisant un quotient de sizeof.


                              Je n'ai pas vu ! Merci ;)


                              Citation : candide

                              Citation : HighTam


                              Citation : candide

                              En principe, on caste les arguments aux fonctions de ctype.h (c'est ce que les bons font en tout cas).


                              Conversion char <==> int n'est elle pas implicite ?



                              C'est pas le problème. La Norme dit :

                              Citation : C99, <ctype.h>

                              In all cases the argument is an int, the value of which shall be
                              representable as an unsigned char or shall equal the value of the macro EOF. If the
                              argument has any other value, the behavior is undefined.



                              Donc pour être sûr qu'une valeur (int) qui ne serait pas dans la bonne plage te fasse pas planter le programme, tu castes en unsigned char. Au moins, tu n'as pas un bug. Mais en même temps, ça peut masquer un problème de conception, c'est pour ça que j'ai jamais trop aimé cette méthode.


                              J'ai bien compris maintenant :)
                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 juin 2010 à 19:33:27

                                Citation : candide

                                Citation : pfeuh

                                C'est marrant, parce que parle de tests, on s'imagine que je ne sais pas faire un test



                                Je n'ai jamais imaginé cela


                                Ah, je vois que tu l'as pris pour toi... Dommage, car ce n'était pas le cas.

                                Citation : candide


                                Citation : pfeuh

                                Mais tu es quand même obligé d'analyser les résultats à la main



                                Ta phrase est ambiguë (comment interpréter le "quand même" ou le "tu" ?).


                                pour tester la fonction:
                                - Tu regardes chaque ligne de tes résultats.
                                - tu te demandes si le mot est valide ou pas.
                                - s'il est valide, la fonction doit retourner 1...Est-ce 1 qui a été retourné?

                                C'est de ça que je parlais quand je parlais d'automatisation.

                                Citation : candide

                                t'as juste mis en place une usine à gaz qui tourne à vide ou qui accouche d'une souris.


                                une liste de chaines valides, une autre de chaines non valides et un test qui affiche la première chaine rencontrée qui passe et qui ne devrait pas ou qui ne passe pas et qui devrait, appelle ça une usine à gaz si tu veux. Et c'est vrai que "A L L T E S T S P A S S E D" a un coté quasi pavlovien... Mais c'est fait pour.

                                Citation : candide

                                la production des exemples n'est pas automatisée, tu as fait un gros copié-collé de la liste des mots-clés,


                                Si le programme de test doit vérifier que la chaine n'est pas un mot-clé, il lui faut cette liste.

                                Citation : candide

                                il faut créer des générateurs aléatoires de mots-clés, et encore, faut-il que le générateur prenne en compte certaines lois de construction des mots clés pour garder un certain réalisme aux tests.


                                Je le fais de temps en temps quand le jeu en vaut la chandelle. Mais par expérience, même en bouclant sur un million d'itérations des choses peuvent passer à travers.

                                Citation : candide

                                Or, il a bien été dit que zIdentificator renvoie 0 ou 1.
                                Tu te trompes quant au fait que _ serait un identificateur invalide.


                                Oui, c'est clair, j'ai raté ces informations. isdigit par contre est un nom de fonction contenant une affirmation, on s'attend clairement à recevoir quelque chose de différent de zéro en retour si on lui a passé un digit.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  15 juin 2010 à 22:48:54

                                  Citation : HighTam

                                  Citation : Pouet_forever

                                  _Imaginary : Non Valide


                                  :)


                                  C'est juste ! Non ? _Imaginary est un mot clé !

                                  Fatigué, désolé. :-°
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    17 juin 2010 à 13:22:33

                                    Bonjour,

                                    Voilà ma tentative pour cet exercice :


                                    #include <stdio.h>
                                    #include <stdlib.h>
                                    #include <string.h>
                                    #include <ctype.h>
                                    
                                    #define N_CLE(tab) (sizeof (tab) / sizeof (*tab))
                                    
                                    int
                                    _is_keyword (char const * const keywords[], char const * keyword, int bg, int bd) {
                                        int pivot = (bg+bd)/2;
                                        int cond = strcmp(keyword, keywords[pivot]);
                                    
                                        if (cond == 0)
                                            return 1;
                                        else if (cond < 0 && bd != pivot)
                                            return _is_keyword(keywords, keyword, bg, pivot);
                                        else if (cond > 0 && bg != pivot)
                                            return _is_keyword(keywords, keyword, pivot, bd);
                                        else
                                            return 0;
                                    }
                                    
                                    int
                                    is_keyword (const char * keyword) {
                                        char const * const keywords[] = {"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", "long", "register", "restrict", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while"};
                                    
                                        return _is_keyword(keywords, keyword, 0, N_CLE(keywords));
                                    }
                                    
                                    int
                                    is_word (const char * word) {
                                        if (isdigit((unsigned int)*word))
                                            return 0;
                                        else
                                            while (*word)
                                                if (!isalnum((unsigned int)*word++))
                                                    return 0;
                                        return 1;
                                    }
                                    
                                    int
                                    zIdentificator(const char * id) {
                                        return *id && !is_keyword(id) && (is_word(id) || (*id == '_' && (id[1] != '_' && !isupper((unsigned int)id[1]))));
                                    }
                                    
                                    int
                                    main (void) {
                                        char const * const tests[] = {"toto", "toto42", "Toto", "c", "to", "_", "_t", "_toto", "_bool", "_4", "_42_toto", "", "4", "42", "4_", "to-to", "__", "__toto", "_Toto", "____", "goto", "return", "_Bool"};
                                        char const * const valid[] = {"ko", "ok"};
                                        int i;
                                    
                                        for (i=0; i<23; i++)
                                            printf("%-10s : %-2s\n", tests[i], valid[zIdentificator(tests[i])]);
                                    
                                        return EXIT_SUCCESS;
                                    }
                                    

                                    #include <stdio.h>
                                    #include <stdlib.h>
                                    #include <string.h>
                                    #include <ctype.h>
                                    
                                    #define N_CLE(tab) (sizeof (tab) / sizeof (*tab))
                                    
                                    int
                                    _is_keyword (const char * keyword, int bg, int bd) {
                                        char const * const keywords[] = {"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", "long", "register", "restrict", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while"};
                                        int pivot;
                                        int cond;
                                    
                                        if (bg == -1 && bd == -1) {
                                            bg = 0;
                                            bd = N_CLE(keywords);
                                        }
                                    
                                        pivot = (bg+bd)/2;
                                        cond = strcmp(keyword, keywords[pivot]);
                                    
                                        if (cond == 0)
                                            return 1;
                                        else if (cond < 0 && bd != pivot)
                                            return _is_keyword(keyword, bg, pivot);
                                        else if (cond > 0 && bg != pivot)
                                            return _is_keyword(keyword, pivot, bd);
                                        else
                                            return 0;
                                    }
                                    
                                    int
                                    is_keyword (const char * keyword) {
                                        _is_keyword(keyword, -1, -1);
                                    }
                                    
                                    int
                                    is_word (const char * word) {
                                        if (isdigit((unsigned int)*word))
                                            return 0;
                                        else
                                            while (*word)
                                                if (!isalnum((unsigned int)*word++))
                                                    return 0;
                                        return 1;
                                    }
                                    
                                    int
                                    zIdentificator(const char * id) {
                                        return *id && !is_keyword(id) && (is_word(id) || *id == '_' && (id[1] != '_' && !isupper((unsigned int)id[1])));
                                    }
                                    
                                    int
                                    main (void) {
                                        char const * const tests[] = {"toto", "toto42", "Toto", "c", "to", "_", "_t", "_toto", "_bool", "_4", "_42_toto", "", "4", "42", "4_", "to-to", "__", "__toto", "_Toto", "____", "goto", "return", "_Bool"};
                                        char const * const valid[] = {"ko", "ok"};
                                        int i;
                                    
                                        for (i=0; i<23; i++)
                                            printf("%-10s : %-2s\n", tests[i], valid[zIdentificator(tests[i])]);
                                    
                                        return EXIT_SUCCESS;
                                    }
                                    
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      17 juin 2010 à 15:45:47

                                      J'ai du mal à comprendre comment est construit _is_keyword
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        17 juin 2010 à 16:26:53

                                        La fonction _is_keyword effectue une recherche dichotomique sur le tableau de mot clé trié alphabétiquement plutôt que de tester un à un chaque mot clé présent dans le tableau j'en élimine la moitié à chaque récursion.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Anonyme
                                        Anonyme
                                          17 juin 2010 à 17:13:48

                                          Le KISS façon ArchLinux ?

                                          Fin bon, j'ajouterais quand même que faire une dichotomie sur aussi peu d'éléments n'est peut-être pas un gain énorme.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            17 juin 2010 à 17:20:01

                                            Bien que sur un nombre d'éléments aussi petit le temps gagné soit négligeable je fais dans le pire des cas 5 comparaisons contre 34 (sans _Imaginary, _Complex et _Bool) ou 37 avec un algo naïf.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Anonyme
                                              17 juin 2010 à 17:54:04

                                              Ah ouais quand même... bon alors je retire ce que j'ai dit :-°
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                17 juin 2010 à 18:16:04

                                                Et tu crées un tableau de tous tes mots à chaque appel. :-°
                                                Petit détail aussi : main.c:35: warning: control reaches end of non-void function
                                                Comme t'aimes bien les cast, tu peux rendre ton code un peu plus propre en faisant des macros :

                                                #define ISDIGIT(c) isdigit((unsigned int)(c))
                                                #define ISALNUM(c) isalnum((unsigned int)(c))
                                                

                                                Un autre petit détail : main.c:50: warning: suggest parentheses around && within ||
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  17 juin 2010 à 18:41:43

                                                  Citation : Pouet_forever

                                                  Comme t'aimes bien les cast, tu peux rendre ton code un peu plus propre en faisant des macros :


                                                  "Propre" et "macro" sont des mots qui ne vont pas bien ensemble. :o
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Anonyme
                                                    17 juin 2010 à 18:42:54

                                                    Mouais, le truc des parenthèses c'est pas important, ya les règles du calcul booléen derrière qui se charge du reste.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      18 juin 2010 à 5:31:22

                                                      Pouet_forever: Pourquoi il crée un tableau à chaque appel ? C'est simplement l'adresse du premier élément qui est passé en paramètre, ou bien j'ai raté quelque chose ?
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        18 juin 2010 à 10:18:08

                                                        Citation : mob

                                                        Pouet_forever: Pourquoi il crée un tableau à chaque appel ? C'est simplement l'adresse du premier élément qui est passé en paramètre, ou bien j'ai raté quelque chose ?


                                                        Il me semble que lorsqu'on définit une variable automatique (aussi dite non statique) dans une fonction
                                                        void f(void) { int t[] = { 1, 2, 3}; }
                                                        

                                                        elle est créée sur la pile, y compris si la variable est un tableau. Cela dit, si le compilateur voit que c'est inutile, je pense qu'il peut créer statiquement le tableau ailleurs, mais je ne sais pas si ce type d'optimisation de compilation existe.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Anonyme
                                                          18 juin 2010 à 10:30:56

                                                          Si elle existe, mais c'est quand même moche de coder comme un pied en comptant sur le compilateur.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          zIdentificator

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown