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

while double conditions

4 réponses
Avatar
clapannac
Bonjour,

J'ai casi terminé mon programme cependant, dans mon main.c, j'éprouve quelque difficulté a cerner la raison pour laquelle ma boucle while refuse de considérer ma seconde condition...
Donc je vous soumet le code suivent :
merci

############################################################
main.c #
######

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Proto.h"

int main()
{
Mot_Secr();
char lettreTap;
int score = 0;
int cmp = 0;

printf("Longueur du mot secre : ");
Etoile_Secr(Mot_Secr());

do{

printf("Propose une lettre : ");
lettreTap = lireCaractere();

printf("Etat du mot secre : ");
printf("%s\n",Result_Trouve_Cache_Save(Mot_Secr(),lettreTap));

score = tentative(Mot_Secr(),lettreTap);
cmp = strcmp(Mot_Secr(), Result_Trouve_Cache_Save(Mot_Secr(),lettreTap));
printf("%d",score);

}while((cmp != 0) || (score != 4));

printf("%d",tentative(Mot_Secr(),lettreTap));

free(Result_Trouve_Cache_Save(Mot_Secr(),lettreTap));
free(Mot_Secr());

return 0;
}

###############################################
fonction.c#
########

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include "Proto.h"

char* Mot_Secr()
{
static int init = 0;
char caractereActuel = 0;
char enter = '\n';

int nbDEnter = 0;
int nbSorti = 0;
int nbMist = 0;
int nbDChar =0;
int i = 0;

int positionUn = 0;

static char* motSecrTab = 0;

while(init != 1)
{
FILE* fichier = NULL;
fichier = fopen("list.txt", "r+");

if (fichier != NULL)
{
caractereActuel = fgetc(fichier);

while (caractereActuel != EOF)
{
caractereActuel = fgetc(fichier); // On lit le caractère suivant
if (caractereActuel == enter)
nbDEnter++;
}

rewind(fichier);

srand(time(NULL));
nbMist = (rand() % (nbDEnter - 0)) + 0;

while (nbMist != nbSorti)
{
caractereActuel = fgetc(fichier);
if (caractereActuel == enter)
nbSorti++;
}

positionUn = (int)ftell(fichier);
caractereActuel = 0;

while (caractereActuel != enter)
{
caractereActuel = fgetc(fichier);
nbDChar++;
}

//allocation dinamique
motSecrTab = calloc(nbDChar,2);
if ( motSecrTab == 0)
{
exit(0);
}

fseek(fichier,-nbDChar-1,SEEK_CUR);
caractereActuel = 0;
nbDChar--;

while(i != nbDChar )
{
caractereActuel = fgetc(fichier);
motSecrTab[i] = caractereActuel;
i++;

}

fclose(fichier);
}

else
{
printf("Impossible d'ouvrir le fichier list.txt");
}

init++;

}

return motSecrTab;

}

char lireCaractere()
{
char caractere = 0;

caractere = getchar(); // On lit le premier caractère
caractere = toupper(caractere); // On met la lettre en majuscule si elle ne l'est pas déjà

// On lit les autres caractères mémorisés un à un jusqu'à l'\n (pour les effacer)
while (getchar() != '\n') ; // il y a un ";" car c'est une boucle minimaliste "Technique de programmeur"

return caractere; // On retourne le premier caractère qu'on a lu

}

void Etoile_Secr(char* Tab)
{
int i;

for(i=0;i<(int)strlen(Tab);i++)
{
printf("*");
}

printf("\n");
}

char* Result_Trouve_Cache_Save(char* Tab,char lettre)
{
int i;
char* copieTab = 0;
static int initialised = 0;
static char* copieTabClone = 0;

copieTab = calloc((int)strlen(Tab),2);
if (copieTab == 0)
{
exit(0);
}

for (i = 0 ; i < (int)strlen(Tab) ; i++)
{
if (lettre == Tab[i])
{
copieTab[i] = lettre;
}
else
{
copieTab[i] = '*';
}

}

while (initialised != 1)
{
copieTabClone = calloc((int)strlen(Tab),2);
if (copieTabClone == 0)
{
exit(0);
}

for (i = 0 ; i < (int)strlen(copieTab) ; i++)
copieTabClone[i] = '*';

initialised = 1;
}

for (i = 0 ; i < (int)strlen(copieTab) ; i++)
{
if (lettre == copieTab[i] && copieTab[i] == Tab[i])
{
copieTabClone[i] = lettre;
}
}

free(copieTab);

return copieTabClone;
}

int tentative(char* tab,char lettre)
{
int i = 0;
int lmot = 0;
static int erreur = 0;
int check = 0;

lmot = (int)strlen(tab);

for(i=0;i<(int)strlen(tab);i++)
{
if(lettre != tab[i])
{
check++;
}
}

if(check == lmot)
{
erreur++;
}

return erreur;
}

#############################################
proto.h #
#######

#ifndef _PROTO_
#define _PROTO_

char* Mot_Secr();
char lireCaractere();
void Etoile_Secr(char* Tab);
char* Result_Trouve_Cache_Save(char* Tab,char lettre);
int tentative(char* tab,char lettre);

#endif

############################################################

4 réponses

Avatar
espie
In article ,
clapannac wrote:
Bonjour,

J'ai casi terminé mon programme cependant, dans mon main.c, j'éprouve quelque
difficulté a cerner la raison pour laquelle ma boucle while refuse de considérer
ma seconde condition...
Donc je vous soumet le code suivent :
merci

do{
}while((cmp != 0) || (score != 4));



Le plus simple pour resoudre ce genre de souci, c'est de se mettre a la
place de la machine et de faire soit-meme le calcul.

-> la boucle que tu as ecrite continuera tant que cmp n'est pas 0 OU tant
que score n'est pas 4. Il suffit qu'une de ces conditions soient vraies
pour ne pas sortir.

-> je soupconne que tu as des petits problemes avec les conditions.
Reformule avec une seule negation, essaie un

do {
} while (!(...));

Tu te melanges les pinceaux sur ce qui arrive a une negation si on la
distribue sur deux conditions: !(a || b) -> !a && !b ...
Avatar
Samuel DEVULDER
Le 12/01/2012 01:41, clapannac a écrit :
Bonjour,

J'ai casi terminé mon programme cependant, dans mon main.c, j'éprouve quelque
difficulté a cerner la raison pour laquelle ma boucle while refuse de considérer
ma seconde condition...



Hum.. pourquoi dis tu cela ? parce que tu ne sors pas de la boucle
alors que score==4? Oui bon, ben c'est normal, pour sortir de ton
while() il faut *à la fois* que cmp==0 et score==4. Je suppose que tu
avais en tête (repeat...until) un autre test que celui que tu as
réellement écrit (do...while). Relis le message de Marc si tu ne
comprends pas pourquoi.

Bon sinon sur le code, quelques remarques:

do{


...
score = tentative(Mot_Secr(),lettreTap);


^^^^^^^^^^
cmp = strcmp(Mot_Secr(),


^^^^^^^^^^^
....
}while((cmp != 0) || (score != 4));

printf("%d",tentative(Mot_Secr(),lettreTap));


^^^^^^^^^^

free(Result_Trouve_Cache_Save(Mot_Secr(),lettreTap));


^^^^^^^^^^
free(Mot_Secr());


^^^^^^^^^^^

Es tu bien sur qu'il faille appeler Mot_Secr() autant de fois? Perso
j'utiliserais une variable locale. Le code en serait bien plus clair.

char* Mot_Secr()
{
static int init = 0;



Cela d'autant plus que cette fonction semble avoir un état interne. Ca
n'est pas une très bonne pratique car rien ne permet de mettre à jour
cette variable interne.

char caractereActuel = 0;
char enter = 'n';

int nbDEnter = 0;
int nbSorti = 0;
int nbMist = 0;
int nbDChar =0;
int i = 0;

int positionUn = 0;

static char* motSecrTab = 0;

while(init != 1)



Pourquoi un while? Un if() suffit et est plus clair du point de vue
de ton intention. C'est important quand on code d'écrire précisément
ce qu'on a en tête sans chercher tromper le relecteur. Car cela cache
souvent un bug. Typiquement un while() semble indiquer que tu pensais
boucler ici alors que le code à cause du init++ non conditionnel ne peut
en réalité que faire un seul passage.

{
FILE* fichier = NULL;
fichier = fopen("list.txt", "r+");

if (fichier != NULL)
{
caractereActuel = fgetc(fichier);



Bug possible car caractèreActuel est un char alors que fgetc() te
retourne un int.


while (caractereActuel != EOF)



EOF étant un int, tu risques d'avoir des trucs bizarres avec certains
caractères. Typiquement, mets 'ÿ' (y tréma) au tout début du fichier.
Je pense que tu va avoir droit à une surprise. (il vaut 255 sur beaucoup
de systèmes, soit la même chose que (char)EOF sur beaucoup de systèmes
aussi).


{
caractereActuel = fgetc(fichier); // On lit le caractère
suivant
if (caractereActuel == enter)
nbDEnter++;
}

rewind(fichier);

srand(time(NULL));



Perso je trouve bizarre de ré-initialiser le générateur aléatoire dans
une boucle. Généralement, sans besoin spécifique, on ne l'initialise
qu'une fois. (Bon ici ca passe car le while() est en fait un if()).

nbMist = (rand() % (nbDEnter - 0)) + 0;



C'est curieux ces "-0" "+0" qui trainent. C'est pour du débug?

...


//allocation dinamique
motSecrTab = calloc(nbDChar,2);



pourquoi ",2" ?

...
void Etoile_Secr(char* Tab)
{
int i;

for(i=0;i<(int)strlen(Tab);i++)



essaye
for(i=0; Tab[i]; i++)

C'est pareil mais bien plus économe en CPU

{
printf("*");
}

printf("n");
}

char* Result_Trouve_Cache_Save(char* Tab,char lettre)
{
int i;
char* copieTab = 0;
static int initialised = 0;
static char* copieTabClone = 0;

copieTab = calloc((int)strlen(Tab),2);



Pourquoi ce ",2"? Tu alloues deux fois trop de mémoire pour ton traitement.

if (copieTab == 0)



préfère if(copieTab == NULL). C'est plus clair pour le relecteur.

{
exit(0);
}

for (i = 0 ; i< (int)strlen(Tab) ; i++)
{
if (lettre == Tab[i])
{
copieTab[i] = lettre;
}
else
{
copieTab[i] = '*';
}

}

while (initialised != 1)
{
copieTabClone = calloc((int)strlen(Tab),2);



idem il y a un ",2" bizzare.

if (copieTabClone == 0)



== NULL c'est mieux (tm).

{
exit(0);
}

for (i = 0 ; i< (int)strlen(copieTab) ; i++)
copieTabClone[i] = '*';

initialised = 1;
}

for (i = 0 ; i< (int)strlen(copieTab) ; i++)
{
if (lettre == copieTab[i]&& copieTab[i] == Tab[i])
{
copieTabClone[i] = lettre;
}
}

free(copieTab);

return copieTabClone;



/! Attention, ici ta copieTabClone ne contient le '' final que parce
que tu alloue 2 fois trop de mémoire et que tu as utilisé un calloc()
qui initialise tout à zéro. Du coup ca ne marche pas si ta chaine est
vide (i.e. ne contient qu'un seul char, le '' final). Ajoute 1 au
strlen() lors des malloc et remplace le 2 par un sizeof(char) et ca
sera mieux.

}

int tentative(char* tab,char lettre)
{
int i = 0;
int lmot = 0;
static int erreur = 0;
int check = 0;

lmot = (int)strlen(tab);

for(i=0;i<(int)strlen(tab);i++)



vu que tu as déjà strlen(tab) dans lmot pourquoi ne fais tu pas simplement
for(i=0; i<lmot; i++)

Quand je vois cela, je me dis que tu as assemblé des bouts de codes
(lmot pour le calcule du score; et strlen() pour l'itération de tous
les caractères de la chaine) sans voir/comprendre la logique globale
de ta méthode. Ca fait un peu travail à l'arrache, pas vraiment
propre, pas vraiment fini.

sam (c'est pas parce que des pro ont étudiés à la Rache qu'il faut
faire pareil! http://www.risacher.com/la-rache/).
Avatar
Samuel DEVULDER
Le 12/01/2012 01:41, clapannac a écrit :
Bonjour,

J'ai casi terminé mon programme cependant, dans mon main.c, j'éprouve


quelque
difficulté a cerner la raison pour laquelle ma boucle while refuse de


considérer
ma seconde condition...



Hum.. pourquoi dis tu cela ? parce que tu ne sors pas de la boucle
alors que score==4? Oui bon, ben c'est normal, pour sortir de ton
while() il faut *à la fois* que cmp==0 et score==4. Je suppose que tu
avais en tête une autre boucle (repeat...until) que celle que tu as
réellement écrite (do...while). Relis le message de Marc si tu ne
comprends pas bien.

Bon sinon sur le code, quelques remarques:

do{


...
score = tentative(Mot_Secr(),lettreTap);


^^^^^^^^^^
cmp = strcmp(Mot_Secr(),


^^^^^^^^^^^
....
}while((cmp != 0) || (score != 4));

printf("%d",tentative(Mot_Secr(),lettreTap));


^^^^^^^^^^

free(Result_Trouve_Cache_Save(Mot_Secr(),lettreTap));


^^^^^^^^^^
free(Mot_Secr());


^^^^^^^^^^^

Es tu bien sur qu'il faille appeler Mot_Secr() autant de fois? Perso
j'utiliserais une variable locale. Le code en serait bien plus clair.

char* Mot_Secr()
{
static int init = 0;



Cela d'autant plus que cette fonction semble avoir un état interne. Ca
n'est pas une très bonne pratique car rien ne permet de mettre à jour
cette variable interne.

char caractereActuel = 0;
char enter = 'n';

int nbDEnter = 0;
int nbSorti = 0;
int nbMist = 0;
int nbDChar =0;
int i = 0;

int positionUn = 0;

static char* motSecrTab = 0;

while(init != 1)



Pourquoi un while? Un if() suffit et est plus clair du point de vue
de ton intention. C'est important quand on code d'écrire précisément
ce qu'on a en tête sans chercher tromper le relecteur. Car cela cache
souvent un bug. Typiquement un while() semble indiquer que tu pensais
boucler ici alors que le code à cause du init++ non conditionnel ne peut
en réalité que faire un seul passage.

{
FILE* fichier = NULL;
fichier = fopen("list.txt", "r+");

if (fichier != NULL)
{
caractereActuel = fgetc(fichier);



Bug possible car caractèreActuel est un char alors que fgetc() te
retourne un int.


while (caractereActuel != EOF)



EOF étant un int, tu risques d'avoir des trucs bizarres avec certains
caractères. Typiquement, mets 'ÿ' (y tréma) au tout début du fichier.
Je pense que tu va avoir droit à une surprise. (il vaut 255 sur beaucoup
de systèmes, soit la même chose que (char)EOF sur beaucoup de systèmes
aussi).


{
caractereActuel = fgetc(fichier); // On lit le caractère
suivant
if (caractereActuel == enter)
nbDEnter++;
}

rewind(fichier);

srand(time(NULL));



Perso je trouve bizarre de ré-initialiser le générateur aléatoire dans
une boucle. Généralement, sans besoin spécifique, on ne l'initialise
qu'une fois. (Bon ici ca passe car le while() est en fait un if()).

nbMist = (rand() % (nbDEnter - 0)) + 0;



C'est curieux ces "-0" "+0" qui trainent. C'est pour du débug?

...


//allocation dinamique
motSecrTab = calloc(nbDChar,2);



pourquoi ",2" ?

...
void Etoile_Secr(char* Tab)
{
int i;

for(i=0;i<(int)strlen(Tab);i++)



essaye
for(i=0; Tab[i]; i++)

C'est pareil mais bien plus économe en CPU

{
printf("*");
}

printf("n");
}

char* Result_Trouve_Cache_Save(char* Tab,char lettre)
{
int i;
char* copieTab = 0;
static int initialised = 0;
static char* copieTabClone = 0;

copieTab = calloc((int)strlen(Tab),2);



Pourquoi ce ",2"? Tu alloues deux fois trop de mémoire pour ton traitement.

if (copieTab == 0)



préfère if(copieTab == NULL). C'est plus clair pour le relecteur.

{
exit(0);
}

for (i = 0 ; i< (int)strlen(Tab) ; i++)
{
if (lettre == Tab[i])
{
copieTab[i] = lettre;
}
else
{
copieTab[i] = '*';
}

}

while (initialised != 1)
{
copieTabClone = calloc((int)strlen(Tab),2);



idem il y a un ",2" bizzare.

if (copieTabClone == 0)



== NULL c'est mieux (tm).

{
exit(0);
}

for (i = 0 ; i< (int)strlen(copieTab) ; i++)
copieTabClone[i] = '*';

initialised = 1;
}

for (i = 0 ; i< (int)strlen(copieTab) ; i++)
{
if (lettre == copieTab[i]&& copieTab[i] == Tab[i])
{
copieTabClone[i] = lettre;
}
}

free(copieTab);

return copieTabClone;



/! Attention, ici ta copieTabClone ne contient le '' final que parce
que tu alloue 2 fois trop de mémoire et que tu as utilisé un calloc()
qui initialise tout à zéro. Du coup ca ne marche pas si ta chaine est
vide (i.e. ne contient qu'un seul char, le '' final). Ajoute 1 au
strlen() lors des malloc et remplace le 2 par un sizeof(char) et ca
sera mieux.

}

int tentative(char* tab,char lettre)
{
int i = 0;
int lmot = 0;
static int erreur = 0;
int check = 0;

lmot = (int)strlen(tab);

for(i=0;i<(int)strlen(tab);i++)



vu que tu as déjà strlen(tab) dans lmot pourquoi ne fais tu pas simplement
for(i=0; i<lmot; i++)

Quand je vois cela, je me dis que tu as assemblé des bouts de codes
(lmot pour le calcule du score; et strlen() pour l'itération de tous
les caractères de la chaine) sans voir/comprendre la logique globale
de ta méthode. Ca fait un peu travail à l'arrache, pas vraiment
propre, pas vraiment fini.

sam (c'est pas parce que des pro ont étudiés à la Rache qu'il faut
faire pareil! http://www.risacher.com/la-rache/).
Avatar
Alexandre Bacquart
On 01/12/2012 09:38 PM, Samuel DEVULDER wrote:
sam (c'est pas parce que des pro ont étudiés à la Rache qu'il faut
faire pareil! http://www.risacher.com/la-rache/).



Mouarf, connaissais pas celui-là, c'est assez savoureux :) Bon, dans la
rubrique "En images", il manque le fameux "Keyboard not found. Press a
key to continue..." du bios, pourtant monument de la méthode La RACHE.
Je suppose que depuis le temps, il a dû disparaître dans une faille
spatio-temporelle...

J'ai bien envie de faire un truc similaire pour vanter les mérites
d'USINAGAZ, une méthode dérivée pour les grosses chaînes de production,
qui a aussi fait ses preuves dans le génie logiciel alimentaire. Pour la
maintenance du bouzin notamment, c'est le top niveau.


--
Alexandre