[Résolu] Les pointeurs et les fonctions en C

Janot Membre non connecté
-
- Voir le profil du membre Janot
- Inscrit le : 18/02/2007
- Site internet
- Groupes :
-
Fondateur MLO

Voilà, j'ai une question pour Dark en particulier...

Je viens de recevoir la correction à un devoir de programmation en C et je suis content car j'ai eu une bonne note...

Mais (car il fallait bien un "mais", le monde est cruel) j'aimerais que vous m'expliquiez la remarque de mon prof car je ne parviens pas à comprendre... Donc Dark si tu pouvais m'expliquer stp?
Le but du programme est de simuler un jeu Pierre,Feuille et Ciseaux. Le joueur joue contre l'ordinateur.
Voici ce que j'ai fais:
Code :
/* File: HAYS-JEAN-GABRIEL-itere.c Auteurs: Jean-Gabriel HAYS cree le: 08/01/2008*/ #include <stdio.h> #include <stdlib.h> #include <time.h> //---------------------------------------------------------------------------------------------------- /*Voici l'algorithme auquel j'ai pensé: - Initiser les variable suivantes à 0: choixH, choixO, aleatoire, compteurH et compteurO. - Tant que compteurH inférieur à 10 et compteurO inférieur à 10 euros, faire: - Générer un nombre au hasard compris entre 0 et 2 inclus avec la fonction srand() et placer le nombre généré dans la variable choixO. - Afficher sur STDOUT "Faites votre choix selon 3 nombres: 0 représente les Ciseaux, 1 représente la Pierre, et 2 le Papier". - Le choix du joueur est placé dans la variable choixH. - Afficher choixH sur STDOUT. - Afficher choixO sur STDOUT. - Effectuer une comparaison entre choixH et choixO: - Si le choix de l'ordinateur est le même que le choix du joueur humain alors personne ne perd (choixH == choixO) - Sinon, - Si le choix du joueur humain est Pierre et le choix de l'odinateur est ciseaux, alors compteurH s'incrémente de 1. - Sinon, - Si le choix du joueur Humain est le papier et le choix de l'ordinateur est la pierre, alors compteurH s'incrémente de 1. - Sinon, - Si le choix du joueur humain est le ciseau et le choix de l'ordinateur est le papier, alors compteurH s'incrémente de 1. - Sinon, afficher sur STDOUT "Vous avez perdu". compteurH s'incrémente de 1. fsi fsi fsi fsi fait */ //---------------------------------------------------------------------------------------------------- void choixHumain(long *humain); void choixOrdi(long *ordi); void compare(long choixH, long choixO, long *pointeurHumain, long *pointeurOrdi); int main() { long aleatoire = 0; const long MAX = 3; const long eurosmax = 10; //Il est possible de modifier le montant sur une seule ligne long eurosHumain = 0, eurosOrdi = 0; while (eurosHumain < eurosmax && eurosOrdi < eurosmax) { srand(time(NULL)); //Initialisation du générateur de nombres aleatoire = rand() % MAX; //L'ordinateur génère un nombre compris entre 0 et 2 inclus. long selection = 0; printf("Veuillez faire votre choix:n0 = Ciseauxn1 = Pierren2 = PapiernVotre sélection: "); scanf("%ld", &selection); choixHumain(&selection); choixOrdi(&aleatoire); compare(selection, aleatoire, &eurosHumain, &eurosOrdi); printf("nVous avez %ld euros et l'ordinateur possède %ld eurosn", eurosHumain, eurosOrdi); } return 0; } void choixHumain(long *humain) { switch (*humain) { case 0: printf("nVous avez choisi les Ciseauxn"); break; case 1: printf("nVous avez choisi la Pierren"); break; case 2: printf("nVous avez choisi le Papiern"); break; } } void choixOrdi(long *ordi) { switch (*ordi) { case 0: printf("nL'ordinateur a choisi les Ciseauxn"); break; case 1: printf("nL'ordinateur a choisi la Pierren"); break; case 2: printf("nL'ordinateur a choisi le Papiern"); break; } } void compare(long choixH, long choixO, long *pointeurHumain, long *pointeurOrdi) { if (choixH == choixO) { printf("nEgalité! Personne ne perdnn"); } else { if (choixH == 1 && choixO == 0) { printf("nLa pierre casse les ciseaux.nVous avez gagné!nn"); *pointeurHumain += 1; } else { if (choixH == 2 && choixO == 1) { printf("nLe papier enveloppe la pierre.nVous avez gagné!nn"); *pointeurHumain += 1; } else { if (choixH == 0 && choixO == 2) { printf("nLe ciseau coupe le papier.nVous avez gagné!nn"); *pointeurHumain += 1; } else { printf("nVous avez perdu."); *pointeurOrdi += 1; } } } } }
Et mon prof me dit:
Citation :
Vous utilisez des fonctions (pas encore vu) et des pointeurs (pas au programme de cette année) alors que ça n'est pas vraiment utile. De plus elles sont dangereuses car elles fonctionnent par effet de bord: éviter ce type de fonctionnement l epllus possible.
Que veut-il dire par effet de bord? Merci!


Neophile Membre non connecté
-
- Voir le profil du membre Neophile
- Inscrit le : 07/12/2007
i = j ++; // J est d'abords transféré dans i puis incrémenté.
i = ++ j;// J est incrémenté puis transféré.
Dans ton cas , le risque majeur est d'aditionner 1 à l'addresse contenu dans le pointeur , et la , ca peu provoqué une erreure de segmentation (tentative d'accès en dehors de la mémoire allouée au prog par le systeme ) ou bien d'autre variables qui se trouves modifé, parfois le code lui même

*pointeurHumain += 1;
Le C dispose de certaines priorités sur les opérateurs arithmétiques lors de l'utilisation de l'effet de bord, je ne les connais pas de tête.
Mais une méthode simple qui garanti le bonne ordre, est de définir les priorité de lecture à l'aide de parenthèses:
(*pointeurHumain) += 1;

darkvodka Membre non connecté
-
- Voir le profil du membre darkvodka
- Inscrit le : 15/05/2007
- Groupes :

Citation :
J'ai eu une bonne note

Citation :
Que veut-il dire par effet de bord? Merci! 

Les effets de bords sont les effets non voulus du programme !
En général, on parle d'effet de bord quand on modifie la valeur d'une variable sans le vouloir ou en donnant une valeur incorrecte.
Dans ton cas, ton prof a peur que tu te trompe entre les pointeurs, les adresses, les valeurs.
Comme le dit néohpile, tu peux facilement arriver a une seg fault si tu fais pas attention.
Ton programme pouvait être réalisé sans fonction et donc sans utiliser les pointeurs.
MAIS utiliser des pointeurs n'est pas du tout déconseillé quand on s'est sans servir!
Si tu veux mon avis, ton prof a peur que tu veux aller trop vite et que tu utilise un des aspects les plus dur du C (pointeurs) sans ces cours!
Ton programme est beaucoup mieux structurées avec des fonctions que sans !
Par contre, ou tu as fait une erreur (que je n'avais pas vu l'autre fois

Tu ne modifie pas la valeur de ta variable passée en paramètre, il est donc inutile et déconseillé de passer par des pointeurs ...
Code :
void choixHumain(long humain)
Pour la fonction compare -> perfect !
Code :
void compare(long choixH, long choixO, long *pointeurHumain, long *pointeurOrdi)
Tu as utilisé des pointeurs ou il fallait !

En résumé, pour moi continue à utiliser fonctions et pointeurs ... mais quand il le faut

@Neophile
Code :
(*pointeurHumain) += 1;
Inutile...

Neophile Membre non connecté
-
- Voir le profil du membre Neophile
- Inscrit le : 07/12/2007
http://fr.wikibooks.org/wiki/Programmation_C/Pointeurs#Arithm.C3.A9tique_avec_effet_de_bord

Janot Membre non connecté
-
- Voir le profil du membre Janot
- Inscrit le : 18/02/2007
- Site internet
- Groupes :
-
Fondateur MLO

Merci à Dark et à Neophile pour ces explications!! J'ai compris grâce à vous!!!
![:]](/images/smileys/8.gif)
Jvais me méfier de tout ça maintenant...


Shad Membre non connecté
-
- Voir le profil du membre Shad
- Inscrit le : 29/10/2007
darkvodka :
Dans ton cas, ton prof a peur que tu te trompe entre les pointeurs, les adresses, les valeurs.
+ 1. Peut-être s'inquiète-t-il aussi de l'interprétation des compilateurs C (l'incrément portera sur la valeur pointée ou sur le handel ??).
darkvodka :
Ton programme pouvait être réalisé sans fonction et donc sans utiliser les pointeurs.
L'usage de fonctions (l'aspect modulaire est bien pour les futurs projets à plus grande échelle ou lors des travaux de groupes) n'est pas utile, certes, mais il est le signe d'une bonne réflexion dans la structuration de tes programmes.
Comme le dit Darkvodka, ton programme est très lisible (bel effort d'indentation et bien commenté). Tu pourrais également commencer à mettre un commentaire devant chacune de tes fonctions qui préciserait son rôle, ce dont elle a besoin comme paramètres ainsi que ses valeurs de retours. Fort pratique quand tu reçois l'entête d'une partie de code à utiliser (toujours mon optique du travail communautaire / modulaire).
Ton prof n'a pas à ce plaindre, tu aurais également pu poussé encore d'avantage l'affaire en réalisant un fichier par actions (de sorte à permettre une évolution extrêmement simple de ce petit jeu, en y incluant par exemple une interface graphique...). Ta position sur l'utilisation des fonctions est, comme tu peux le voir, largement justifiable

darkvodka :
MAIS utiliser des pointeurs n'est pas du tout déconseillé quand on s'est sans servir!
Si tu veux mon avis, ton prof a peur que tu veux aller trop vite et que tu utilise un des aspects les plus dur du C (pointeurs) sans ces cours!
Si tu veux mon avis, ton prof a peur que tu veux aller trop vite et que tu utilise un des aspects les plus dur du C (pointeurs) sans ces cours!
C'est peut être mieux de laisser ça pour les tables, listes et autres matrices (objets). Une erreur est si vite arrivée par distraction : l'oubli du petit adressage à l'envoi ' & ' ou l'étoile de pointage est bien délicat à repérer dans un programme de longue échelle. Après c'est galère pour débugger..... Mais avec une structuration fonctionnelle et/ou modulaire, on y gagne en temps.
Q° : la description de l'algorithme est une demande du prof d'ASD ou un point imposé par ton établissement ? (n'en avais encore jamais vu, il faut dire que cela va faire bien 15 ans que je n'ai plus côtoyé des lignes de codes<span style="font-size: 85%;"> (à par VBA pour ma gestion administrative...). C'est dingue comme le temps passe vite...</span>...
darkvodka :
Par contre, ou tu as fait une erreur (que je n'avais pas vu l'autre fois
) et ou ton prof n'as pas tord quand il te dis que tu "joue un jeu dangereux" pour rien c'est pour tes fonctions choixHumain et choixOrdi.
Tu ne modifie pas la valeur de ta variable passée en paramètre, il est donc inutile et déconseillé de passer par des pointeurs ...

Tu ne modifie pas la valeur de ta variable passée en paramètre, il est donc inutile et déconseillé de passer par des pointeurs ...
+ 1. Mais bon comme il est prudent et qu'il sait ce qu'il fait.....
darkvodka :
Pour la fonction compare -> perfect !
Les pointeurs peuvent également s'éviter avec un petit tour de passe passe comme je les aimais :
Code :
long compare(long choixH, long choixO)
valeurs de retour : -1 ; 0 ; +1 ( codage : - 1 => victoire humain ; 0 => match null ; 1 => victoire ordi )
Code :
if (compare(selection, aleatoire) > 0) then { eurosOrdi++; } else { eurosHumain++; }
Je ne me rappelle plus de la forme abrégée qu'il est possible d'employer pour le test : " (test-logique)?:__action-true___:___action-false____ ; ". Voilà ce que c'est quand on prend de l'âge

darkvodka :
En résumé, pour moi continue à utiliser fonctions et pointeurs ... mais quand il le faut 

+ 1
Shad.
Linux, il y a moins bien, mais c'est plus cher... 
La route est longue... mais la voie est libre


La route est longue... mais la voie est libre


Janot Membre non connecté
-
- Voir le profil du membre Janot
- Inscrit le : 18/02/2007
- Site internet
- Groupes :
-
Fondateur MLO

Pour l'algorithme en commentaire c'est imposé par le prof. Je me replongerai sur ton tour de passe passe demain quand j'aurais un peu plus de temps et surtout des neurones éveillés.


Shad Membre non connecté
-
- Voir le profil du membre Shad
- Inscrit le : 29/10/2007
Janot :
Pour l'algorithme en commentaire c'est imposé par le prof.
Après réflexion (mes neurones à moi aussi commencent à perdre de leur intensité dans la nuit

M'y replongerais à l'occasion...
Shad.
Linux, il y a moins bien, mais c'est plus cher... 
La route est longue... mais la voie est libre


La route est longue... mais la voie est libre


darkvodka Membre non connecté
-
- Voir le profil du membre darkvodka
- Inscrit le : 15/05/2007
- Groupes :
Shad :
Après réflexion (mes neurones à moi aussi commencent à perdre de leur intensité dans la nuit
), il existait un moyen d'extraire des balises de commentaires de fichiers sources et d'en générer automatiquement une documentation sous LaTeX (vient du monde Sun et des systèmes Unix, mais le portage a du être fait sous linux).
M'y replongerais à l'occasion...
Shad.
Janot :
Pour l'algorithme en commentaire c'est imposé par le prof.
Après réflexion (mes neurones à moi aussi commencent à perdre de leur intensité dans la nuit

M'y replongerais à l'occasion...
Shad.
OH


Shad Membre non connecté
-
- Voir le profil du membre Shad
- Inscrit le : 29/10/2007
Sinon, il devrait également être possible de faire de même par ses propres moyens avec : Lex et Yacc. Lex se chargeant de l'analyse lexicale (en gros retrouver les mots) et Yacc de la phase grammaticale (repérage de l'organisation des mots afin d'en extraire des phrases / commandes types (un peu comme : SUJET VERBE COMPLEMENTS avec définition préalable de SUJET = ARTICLE NOM par exemple (plusieurs définitions possibles) et la liste des mots acceptables sont dans le fichier lexical) à retraduire dans les termes du langage de sortie souhaité ou juste pour le fun...). Je m'étais éclaté à l'époque lors de la réalisation de mon post-processeur interpréteur chargé de réalisé l'interface entre les simulations du logiciel de modélisation et simulation (CATIA je crois...) et les divers langages des machines robots.
A priori, pour l'extraction des commentaires d'un langage de programmation (C étant déjà fortement structuré et géré par mots clés) le principe est simple : ignorer les textes avant la balise d'ouverture (possibilité de définir plusieurs styles de mises en commentaire), traiter le texte imbriqué et ignorer la suite jusqu'à la nouvelle balise.
Ensuite, en jouant les malins, on peut s'organiser les commentaires (juste une habitude à prendre) de sorte à faciliter le post-traitement (et pourquoi ne pas déjà y inclure les structures du formatage dans LaTeX, cela fera toujours ça de moins pour l'extracteur/interpréteur).
Pour plus d'infos sur Lex et Yacc : http://www.linux-france.org/article/devl/lexyacc/
A priori ça existe encore : " Documentation du source : comment documenter les sources (par exemple par des commentaires ou des outils d'extraction de documentation logicielle) " (vu sur Wikipédia).
Si le nom du soft me revient en mémoire, j'en glisse un mot ici.
Shad.
Linux, il y a moins bien, mais c'est plus cher... 
La route est longue... mais la voie est libre


La route est longue... mais la voie est libre


JackDaniels93 Membre non connecté
-
- Voir le profil du membre JackDaniels93
- Inscrit le : 03/03/2007
- Groupes :
-
Fondateur MLO

Mandriva, ça marche pas .... ça court, ça vole !!

darkvodka Membre non connecté
-
- Voir le profil du membre darkvodka
- Inscrit le : 15/05/2007
- Groupes :
Et puis ce qu'il y a avant le fenetré est essentiel pour pouvoir du fenetré !


Shad Membre non connecté
-
- Voir le profil du membre Shad
- Inscrit le : 29/10/2007
JackDaniels93 :
c'est que la route est longue avant pouvoir créer des programmes en c++ en fenetré... 

Tu peux toujours t'amuser un peu avec Visual C++ sous VirtualBox Windows... Tu cliques, tu remplis ta fenêtre en glissant des éléments que tu met en formes, tu renseignes quelques propriétes, tu affectes des actions (les fameuses fonctions) au composants et hop, tu as l'interface graphique.
Et rien ne t'empêche de regarder le code généré (voir de le pomper) et de t'en servir pour tes projets..... On ne va quand même pas tout refaire à chaque fois que l'on veut faire un p'tit truc en plus ou de nouveau (je dis pas qu'il ne faut pas y revenir parfois, mais pas systématiquement). Un module bien construit et bien pensé a une très longue espérance de vie <span style="font-size: 85%;">(le temps des programmeurs payés au nombre de lignes de code réalisées dans la journée et loin derrière

Et puis la programmation objet à quand même un gros avantage : chaque objet implémenté peut disposer de fonctions héritées du type dont il est issu ou personnalisées (redéfinition). Ainsi une première version de " monObjet.afficher" peut se limiter à une simple sortie en mode texte (printf) ou correspondre à une fonction revue qui exploite justement le code récupéré par le créateur d'interface (visual C++). Libre à toi d'en faire un module... <span style="font-size: 85%;">Tu peux donc faire un petit programme sans interface graphique pour le moment et juste utiliser une fonction d'affichage. Par la suite, il te suffira de juste développer d'avantage la ' beauté ' de l'affichage par exemple.</span>
Rassure-toi JackDaniels93, la route te semble peut être un peu longue, mais elle est justifiée. Mine de rien, le trivial " Hello world " apporte quand même pas mal de notions, surtout qu'on peut le décliner sous plusieurs formes et complexités.
Si tu veux éviter de te retrouver avec une tour de Pise en guise d'approche de C, il vaut mieux suivre les étapes. Et petit à petit, on est moins petit

JackDaniels93 :
Heu... mais dites-moi, combien y'a de programmeurs ici ??
On fait un p'tit tour d'horizon ????
<span style="font-size: 85%;">(bien que l'on puisse être un utilisateur de Linux sans être un ' geek ' ni ' un pisseur de code ' (nom donné aux programmeurs dans les premiers temps). Linux offre la possibilité à son utilisateur de se plonger dans le code des logiciels qu'il utilise pour ajouter des fonctions dont il a besoin mais cela n'en fait pas une obligation. La liberté, c'est aussi d'avoir le choix

</span>
Shad.
Linux, il y a moins bien, mais c'est plus cher... 
La route est longue... mais la voie est libre


La route est longue... mais la voie est libre


JackDaniels93 Membre non connecté
-
- Voir le profil du membre JackDaniels93
- Inscrit le : 03/03/2007
- Groupes :
-
Fondateur MLO
Mandriva, ça marche pas .... ça court, ça vole !!
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie