-
Code correct mais..
Bonjour,
Je fais une simulation de mon protocole dans NS2.
Mon programme en C++ est correct mais les résultats fournis lors de l'exécution ne sont pas ceux que je m'attendais :(. Je voudrais savoir comment résoudre ce problème.
Merci de me répondre.
-
En te creusant la tête.
Si deux résultats diffèrent, c'est qu'au moins l'un des deux est faux.
Si un résultat est faux, c'est soit qu'il est mal calculé, soit qu'il est calculé à partir de mauvaises données.
Garde tout de même en mémoire qu'il y a l'erreur inhérente aux nombres décimaux (float, double, etc...)
-
Quand tu écris tu code il y a 3 étapes,
1) Tu compiles le code
2) Tu le fais tourner sans qu'il plante
3) Tu t'assures que les résultats soit bons, et c'est souvent le plus dur !
Des codes qui tourne très bien malgré une erreur de signe dans un calcul, ou un Axe X qui devient un axe Y etc... c'est classique de chez classique.
Est-ce que tu fais des tests unitaires , a défaut est-ce que tu appliquer à chaque sous partie du code un cas simple calculable à la main. Est-ce que tu es sur que tu lis bien les données d'entrée ?
En général ca suffit à trouver ce qui déconne. Sinonh sans plus d'information je vois pas comment t'aider
-
Le problème c'est que dans NS2, on gère plusieurs fichiers (.h et .cc) qui sont liés entre eux et c'est ce qui est difficile pour moi.
Est ce que vous voulez que je vous montre le code ou je vous donne seulement le principe?
Est ce que vous avez des cours C++ ou des astuces pour résoudre ce genre de problème : code juste mais résultat faux ou inattendu ?
Je suis complètement étourdie :(
Merci pour les réponses.
-
>code juste mais résultat faux ou inattendu
Un code qui ne plante pas mais qui ne donne pas les résultats attendus, n'est pas juste, il est buggué.
L'approche la plus direct, c'est de faire des tests unitaires et de débugger pour voir où et pourquoi les résultats commencent à être faux.
-
Salut,
Si ton code devait respecter trois grands critères, ce serait, dans l'ordre :
- etre facilement compréhensible, appréhendable par quelqu'un qui pose les yeux dessus pour la première fois
- faire ce que l'on attend de sa part (fournir des résultats corrects et prévisibles au départ de données clairement établies)
- fonctionner rapidement
Pourquoi faut il qu'il respecte ces critères dans cet ordre bien particulier? me demanderas-tu peut être ?
Tout simplement parce qu'un code qui est facile à comprendre et à appréhender, même par quelqu'un qui pose les yeux pour la première fois dessus, c'est un code dans lequel nous pourrons facilement "voir ce qui ne va pas".
La suite, ca va de soi... Un code qui compile n'est pas (forcément) un code correct. C'est, au mieux, un code pour lequel le compilateur n'a rien trouvé à redire au niveau de la syntaxe et de certaines obligations propres au langage.
Quand tu t'attend à ce qu'une fonction renvoie 2 lorsque tu lui donne 1 en entrée, si elle te renvoie autre chose que 2 quand tu lui donne 1, le code compile peut-être, mais la logique n'est surement pas bonne (autrement, la fonction aurait -- effectivement -- renvoyé 2). Mais, pour savoir où la logique n'est pas correcte, il faut savoir comprendre le code que l'on a devant les yeux.
Enfin, lorsque l'on a un code qui fait ce que l'on attend de sa part (que la logique est correcte), on peut commencer à réfléchir au moyen d'améliorer la rapidité avec laquelle il arrive au résultat si (et seulement si) on se rend compte que cela bénéficiera à l'utilisateur : Il ne sert pas à grand chose d'apporter une modification qui permettra d'obtenir le résultat en 2jours et 5 minutes au lieu de l'obtenir en 2 jours et six minutes : on va se donner beaucoup de mal pour rien ;). Par contre, en choisissant mieux les types de collection utilisés, en évitant les copies ou encore en évitant de (re) faire des calculs lourds dont le résultat n'est pas utilisé (ou dont le résultat a déjà été calculé), il y a moyen de diminuer les temps d'exécution de manière significative ;)
Ceci étant dit : tu utilises plusieurs fichiers, tu as donc fait le premier pas. Intéresse-toi en priorité au fichiers d'en-tête (*.h) car c'est eux qui te dise "quoi faire" pour obtenir "quel résultat".
Qu'il s'agisse des fichiers d'en-tête d'une bibliothèque externe ou de ceux que tu as toi-même écrit ne change rien (si ce n'est que les comportements d'une bibliothèque externe sont sensés apporter une certaine garantie de fiabilité ;) ) : crées des tests qui te permettront de t'assurer que tu obtiens des résultats corrects à partir du moment où tu donne des données correctes en entrée.
Deux possibilités s'offriront alors à toi en face d'un résultat aberrant :
- Soit tes tests t'auront donné la garantie que la logique est respectée : c'est alors que les données que tu fournis en entrée sont incorrectes et que tu dois apporter plus de soin à leur récupération à la base
- Soit tes tests ne t'auront pas donné la garantie que la logique est respectée (ou, plutôt, il t'auront donné la preuve que la logique n'est pas respectée ;) ) : c'est alors que tu dois trouver en quoi la logique n'est pas correcte, et que tu dois corriger ton code.
Il existe de nombreux framework te permettant ce gérer des tests unitaires (boost, cppunits et bien d'autres), mais il faut avouer que l'on a généralement beaucoup plus facile à mettre une politique stricte de tests unitaires lorsqu'elle est initiée en même temps que le reste du projet. Comme on va -- généralement -- développer les fonctionnalités les plus simples en premier, on a "assez facile" les tester pour s'assurer qu'elles font ce que l'on attend de leur part et, du coup, on dispose de bases solides sur lesquelles faire reposer les fonctionnalités plus complexes : si ces fonctionnalités plus complexes ne donnent pas le résultat attendu, c'est au niveau de ces fonctionnalités complexes qu'il faut aller chercher, et non au niveau des fonctionnalités les plus simples ;)
-
En plus de ce qui a déjà été dit, l’usage d’un debugger peut grandement aider dans certains cas.