Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[débutant] 1er programme, j'aimerais vos commentaires.

91 réponses
Avatar
Beware
Bonjour,

D=E9butant dans l'apprentissage du langage C, j'ai cr=E9e un petit
programme, un jeu du pendu. Le jeu =E0 l'air de fonctionner. Je dis
"l'air de", car il est probable qu'il reste des bugs que je dois
corriger.
Cependant ce n'est pas l'objet de ma question. En effet, dans un souci
de m'am=E9liorer je d=E9sirerais avoir les commentaires de personnes
connaissant et maitrisant mieux le langage C que moi.

Les fichiers du programme (main.c, pendu.h et dico.txt) sont
disponible ici :
http://beware007.free.fr/Projet_C/Pendu/


Merci d'avance pour votre aide, vos commentaire et critiques.

10 réponses

Avatar
Alexandre BACQUART
Antoine Leca wrote:
Le 14/03/2009 22:50, Alexandre BACQUART écrivit :
Antoine Leca wrote:
Le 14/03/2009 9:47, candide écrivit :
printf( "nt Vous avez perdu. Le mot a trouver etait : %s",
On peut utiliser sans souci les accents dans les messages (sauf si on
s'appelle Marc E. et que l'on travaille sur des terminaux zarbi), c'est
quand même plus lisible.


Avec la console Windows vaut mieux s'abstenir des accents.


Voilà une drôle de remarque ! À quoi est-elle due ? Aurais-tu des
problèmes d'affichage en console Windows d'un programme ? Est-ce que
cela viendrait-il d'un compilateur en particulier ?


J'ai déjà eu ce problème dans de nombreux cas de développement. Mais
pour ma part, je suis configuré par défaut en anglais, peut-être que ça
joue. Je suppose que ça doit se configurer quelque-part pour que ce soit
spécifique à certains outils, mais ça ne me dérange pas suffisamment
pour que je cherche la manière de faire.



Premier résultat d'une recherche Google :



Oui rooh, ça va, j'ai dis que ça ne me dérangeait pas suffisamment :)

http://mail.nl.linux.org/linux-utf8/2004-11/msg00009.html, 1er alinéa



Par contre, je n'ai pas parlé de GCC, mais "d'outils". On a pas toujours
la chance que ce soit du libre... donc je pensais plutôt à quelque-chose
pour dire au système "quand tu lances tel programme, passe en telle locale".


--
Alex
Avatar
candide
Antoine Leca a écrit :


Voilà une drôle de remarque ! À quoi est-elle due ? Aurais-tu des
problèmes d'affichage en console Windows d'un programme ? Est-ce que
cela viendrait-il d'un compilateur en particulier ?




Hum, tu parles (aussi) assez souvent de Windows dans tes posts donc j'ai peine a
croire que tu ignores le problème que pose l'affichage des caractères spéciaux
dans une console Windows. Donc je ne vois pas à quoi tu fais allusion. Le
problème de l'affichage n'est pas lié à un problème de compilateur, c'est lié à
l'encodage de la console Windows, cf. par exemple :

http://www.siteduzero.com/forum-83-125906-1292635-faq-c.html#r1292635


Je suis repassé sous Windows juste le temps de faire une copie d'écran :

http://s610.photobucket.com/albums/tt181/candide256/?action=view&current¬cents.png

On a un résultat analogue avec la console qu'ouvre Visual Express.


Et si tu compiles sous Linux avec un locale (précisant un certain
encodage) donné, puis que tu changes de locale (avec un *autre*
encodage), est-ce que le programme affiche correctement les accents ?



Pas trop compris la manip. Tu veux dire, entrer en console par exemple :

export LC_CTYPE=fr_FR.ISO-8859-1

puis, par exemple,

export LC_CTYPE=fr_FR.fr_FR.UTF-8

?

Sinon, sans avoir trop cherché à comprendre, jamais eu de problème majeur sous
Linux pour avoir des accents en console.
Avatar
Sylvain SF
Beware a écrit :

Les fichiers du programme (main.c, pendu.h et dico.txt) sont
disponible ici :
http://beware007.free.fr/Projet_C/Pendu/



remarque sur la forme (donc sans intérêt):

pourquoi cette indentation des switch ?
je tombe parfois sur de telles mise en forme
(30 ou 50 espaces) et elles m'étonnent tjrs.

la forme:

switch (type_affichage){
case AFF_MENU_JEU:
printf("nn");
...
break;
}

n'a pas l'aval de l'éducation nationale ??

Sylvain.
Avatar
Alexandre BACQUART
candide wrote:
Antoine Leca a écrit :

Voilà une drôle de remarque ! À quoi est-elle due ? Aurais-tu des
problèmes d'affichage en console Windows d'un programme ? Est-ce que
cela viendrait-il d'un compilateur en particulier ?




Hum, tu parles (aussi) assez souvent de Windows dans tes posts donc j'ai peine a
croire que tu ignores le problème que pose l'affichage des caractères spéciaux
dans une console Windows. Donc je ne vois pas à quoi tu fais allusion. Le
problème de l'affichage n'est pas lié à un problème de compilateur, c'est lié à
l'encodage de la console Windows, cf. par exemple :

http://www.siteduzero.com/forum-83-125906-1292635-faq-c.html#r1292635


Je suis repassé sous Windows juste le temps de faire une copie d'écran :

http://s610.photobucket.com/albums/tt181/candide256/?action=view&current¬cents.png

On a un résultat analogue avec la console qu'ouvre Visual Express.



Essaye plutôt :

swprintf(L"La fête de Noël où ? à Bécon les Bruyères.n");



--
Alex
Avatar
Alexandre BACQUART
Alexandre BACQUART wrote:
candide wrote:
Antoine Leca a écrit :

Voilà une drôle de remarque ! À quoi est-elle due ? Aurais-tu des
problèmes d'affichage en console Windows d'un programme ? Est-ce que
cela viendrait-il d'un compilateur en particulier ?




Hum, tu parles (aussi) assez souvent de Windows dans tes posts donc
j'ai peine a
croire que tu ignores le problème que pose l'affichage des caractères
spéciaux
dans une console Windows. Donc je ne vois pas à quoi tu fais
allusion. Le
problème de l'affichage n'est pas lié à un problème de compilateur,
c'est lié à
l'encodage de la console Windows, cf. par exemple :

http://www.siteduzero.com/forum-83-125906-1292635-faq-c.html#r1292635


Je suis repassé sous Windows juste le temps de faire une copie d'écran :

http://s610.photobucket.com/albums/tt181/candide256/?action=view&current¬cents.png


On a un résultat analogue avec la console qu'ouvre Visual Express.



Essaye plutôt :

swprintf(L"La fête de Noël où ? à Bécon les Bruyères.n");



Heu... wprintf() pardon.


--
Alex
Avatar
Antoine Leca
Le 14/03/2009 23:35Z, candide écrivit :
Antoine Leca a écrit :

Voilà une drôle de remarque ! À quoi est-elle due ? Aurais-tu des
problèmes d'affichage en console Windows d'un programme ? Est-ce que
cela viendrait-il d'un compilateur en particulier ?



Hum, tu parles (aussi) assez souvent de Windows dans tes posts donc j'ai peine a
croire que tu ignores le problème que pose l'affichage des caractères spéciaux
dans une console Windows. Donc je ne vois pas à quoi tu fais allusion.



Je n'ignore pas le problème ; mais lorsqu'il est devenu vraiment pénible
(càd quand GCC a commencé à me cracher de l'UTF-8 dans ma session
CP850), j'ai trouvé l'explication technique et la solution en quelques
heures.


Le problème de l'affichage n'est pas lié à un problème de compilateur, c'est
lié à l'encodage de la console Windows,



C'est vrai que l'encodage de la console Windows est une donnée
fondamentale du problème ; mais tu ne peux pas dédouanner le compilateur
aussi facilement : toutes les consoles sont forcément encodées d'une
façon ou d'une autre, et là le problème ne se pose QUE quand le
compilateur ne génère pas l'encodage que la console attend.
C'est un peu ce que j'essayais d'expliquer avec ma tirade sur Linux
(mais je n'ai pas assez développé) : en gros, quand Linux/*BSD avait des
encodages variables pour les consoles (époque glorieuse où la console
texte était en 850/437 pour cause de matériel, et la console X en 8859-x
pour cause de compatibilité Unix/VT100), on avait les mêmes problèmes et
les mêmes conséquences, pas d'accents (n'est-ce pas Marc?)
Depuis, les gars de Linux ont standardisé sur UTF-8 (et ceux de Windows
sur UTF-16), et ensuite les auteurs de GCC ont décidé de forcer tout le
monde à les suivre dans la voie de l'UTF ; MS n'est pas allé aussi loin,
au prix d'une complexité de l'API, et aussi parce que UTF-16 n'a pas de
compatibilité binaire avec l'ASCII ; mais à la même époque (VS2005), ils
ont aussi implanté des trucs « plus Unicode », avec des choses bien (on
peut maintenant utiliser UTF-8 dans les sources) et d'autres moins
(c'est plus difficile de recoder dans un autre encodage, au hasard 850).

cf. par exemple :
http://www.siteduzero.com/forum-83-125906-1292635-faq-c.html#r1292635



Oh que je n'aime pas les affirmations genre « l'encodage IBM 850 [...]
ne permet pas d'afficher les caractères accentués ».

Bon, je suis d'accord avec leur solution de contournement, mais le fait
d'utiliser 1252 comme standard est purement arbitraire... par exemple on
peut aussi bien utiliser 850 (!) et au passage on y gagne le fait de ne
pas avoir besoin de rajouter du code bizarre, et le désavantage c'est
que l'on est alors obligé d'utiliser un éditeur de textes qui permet de
manipuler du 850, ce qui dans la pratique signifie souvent ou bien un
éditeur MS-DOS (donc noms de fichiers au format 8.3), ou bien un IDE ou
un traitement de textes de l'époque 1995, dernier successeur d'une
lignée qui ait été passé sur le tard à Windows et ensuite adapté à la
marge pour les noms longs... bref pas très croustillant.


Je suis repassé sous Windows juste le temps de faire une copie d'écran :
http://s610.photobucket.com/albums/tt181/candide256/?action=view&current¬cents.png

On a un résultat analogue avec la console qu'ouvre Visual Express.



Le problème devrait être clair maintenant, tu utilises deux encodages
différents, et qui plus est tu utilises un compilateur (quel qu'il soit)
qui sert _aussi_ pour compiler du code GUI, qui lui n'utilise qu'un seul
encodage, donc par défaut le compilateur n'a pas de raison de faire de
transcodage (encodages différents pour le jeu source et le jeu
d'exécution, norme C alinéas 5.1 ss).

Pour GCC, un condensé des pistes se trouve dans
http://mail.nl.linux.org/linux-utf8/2004-11/msg00009.html, et il n'y a
rien d'impossible à partir de là !

Pour VC++, je n'ai pas les solutions (IDE et ligne de commande CL) sous
la main, mais il me semble que j'avais réussi à forcer le compilo CL à
émettre un binaire encodé en 850 (ou probablement 437) à partir d'un
source en 1252... seulement je ne me rappelle plus sur le coup comment
j'ai fait (et il n'est pas impossible que j'ai utilisé le truc du site
du Zéro, ou un coup de sed -e y/// ou de tr pour faire le boulot, ou
wprintf; ou encore que la solution de l'époque soit avec CL v13 et non
compatible v14). Sinon avec un peu de chance, l'IDE Visual Studio permet
toujours dans un coin de sauvegarder les fichiers source en codepage OEM
850 ?



Antoine
Avatar
Pierre Maurette
Antoine Leca, le 14/03/2009 a écrit :

[...]

Le contexte:
while (indice_tableau < strlen(motSecret)) {



Il y a là un truc qui me semble embêtant avant de s'intéresser au
warning, et qui n'a pas été signalé sous réserve de lecture plus
attentive de toutes les réponses. C'est l'appel multiple à une fonction
dans une boucle, inutilement. Car même dans le cas de strlen(saisie),
le résultat ne changera pas. strlen() est même appelé avant la boucle,
et cet appel devrait suffire.
A mon avis on ne doit pas laisser ce genre de chose, quel que soit le
langage, et le fait que "dans le contexte ça va assez vite, pas
d'optimisation avant d'en avoir besoin" n'y change rien, c'est l'algo
qui est boîteux. Et compter sur le compilateur pour optimiser ne change
rien. Ici, il évitera paut-être l'appel dans le cas de
strlen(motSecret), mais certainement pas pour strlen(saisie), au motif
que va sans doute lui échapper que forcer une lettre d'une chaîne en
upper ne modifie pas sa longueur.

On peut n'appeler strlen() qu'une fois par fonction. Mais on pourrait
lors de l'acquisition des mots renseigner une structure composée d'un
char* et d'un int. Dans le contexte, un TAILLE_MOT_MAX + 1 qui tient
dans un int, on vérifie à ce moment-là. Personnellement, je ne m'embête
pas avec strlen(), je scanne jusqu'à trouver '' ou le (TAILLE_MOT_MAX
+ 1) ème char, mais je crois que ce n'est pas bien. A ce moment-là,
surtout si on découpe en plus nombreuses fonctions, il n'est pas
coûteux de passer la structure, par pointeur ou même par copie de
valeur. Ou un tableau de deux structures, saisie et motSecret, là c'est
carrément économique...

Et le problème du warning est résolu en même temps...

--
Pierre Maurette
Avatar
Richard Delorme
Marc Espie a écrit :

- Il y a des commentaires inutiles, je pense en particulier a
/* Declaration des variables */
ou le tres inutile:
/* on retourne le choix du joueur */
return (choix_rejouer);

Regle d'or: un commentaire a une valeur ajoutee. Si tu paraphrases
ce que fait le code, sans explication supplementaire, un commentaire
ne sert a rien !



Je suis d'accord avec ce qui précède. Je rajouterai qu'il manque aussi
des commentaires. Il faudrait un commentaire en début de fichier pour
expliquer ce que fait le programme, qui l'a écrit, quand, etc. P.ex:

/*
* programme du Jeu de pendu
*
* auteur: Beware
* date: mars 2009
* version: 0.1
*/

Il faudrait aussi des commentaires en tête de chaque fonction qui
explique ce qu'elle fait. Au minimum :

/* Écrit les lettres trouvées dans motJoue */
void test_lettre(char lettre, char *motSecret, char *motJoue) {

- il y a quelques lourdeurs algorithmiques. Lorsque tu regardes le mot
en cours pour y trouver la lettre jouee... ben tu vois combien d'instances
tu en trouves: tu ne devrais pas avoir a compter les etoiles restantes,
parce que c'est quelque chose que tu peux garder en memoire.
Pareil pour le fichier de mots possibles, tu ne devrais pas avoir a le
relire totalement pour savoir combien il contient de mots.



Je suis aussi d'accord avec ça. Ainsi, beaucoup de boucle while()
pourraient être avantageusement remplacer par des boucles for(;;)
Par exemple, la fonction suivante:

void test_lettre(char lettre, char *motSecret, char *motJoue) {

int indice_tableau = 0;

while (indice_tableau <= strlen(motSecret)) {
if (lettre == motSecret[indice_tableau])
motJoue[indice_tableau] = lettre;
indice_tableau++;
}
}

pourrait s'écrire, AMHA :

void test_lettre(char lettre, char *motSecret, char *motJoue) {

int i;
int n = strlen(motSecret);

for (i = 0; i <= n; ++i) {
if (lettre == motSecret[i]) motJoue[i] = lettre;
}
}

La boucle for permet d'écrire en une ligne là où le while demande trois
lignes.
Mettre strlen en dehors de la boucle simplifie la complexité
algorithmique de cette fonction d'O(n^2) en O(n).

Encore plus dans l'esprit du langage C, serait:

void test_lettre(char lettre, const char *motSecret, char *motJoue) {

while (*motSecret) {
if (lettre == *motSecret) *motJoue = lettre;
++motJoue; ++motSecret;
}
}

On a supprimé l'appel à strlen, ce qui doit légèrement améliorer
l'efficacité du programme ; et on utilise directement des pointeurs au
lieu des indices de tableau, ce qui ne doit rien changer en terme de
performance mais rend le programme peut-être plus lisible pour un
programmeur C (et moins lisible pour les autres).

--
Richard
Avatar
candide
Pierre Maurette a écrit :
Antoine Leca, le 14/03/2009 a écrit :

[...]

Le contexte:
while (indice_tableau < strlen(motSecret)) {



Il y a là un truc qui me semble embêtant avant de s'intéresser au
warning, et qui n'a pas été signalé sous réserve de lecture plus
attentive de toutes les réponses. C'est l'appel multiple à une fonction
dans une boucle, inutilement.



Oui, tout à fait.
Avatar
-ed-
On 14 mar, 14:14, (Marc Espie) wrote:
In article <C5E16B98.E4589%,
Eric Levenez   wrote:



>Quel serait ton conseil alors ?

Ignorer l'avertissement et envoyer gcc se faire cuire un oeuf.



Impossible dans un projet industriel. Les messages 'ignorés' sont bel
et bien présents dans la liste et peuvent empêcher de voir des
messages importants signalant de vrais problèmes...