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é.
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.
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.
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...
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.
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=sizeofinvalid_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 :
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.
@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.
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.
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.
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.
La fonction _is_keywordeffectue 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.
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.
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 :
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 ?
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.
× 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.