[C / gcc] Liste chainée d'une structure [RESOLU]

Salut a tous
J’essaye pour mon othello de reférencer tous les coups valides pour un coup donné.
Je parcours donc tout l’othellier et regarde si la case est un coupValide à l’aide de ma fonction coupValide(char camp,char * grille,int ligne, int colonne), et si il est bon le rajoute a la tete de ma liste chainé.

Je crée donc une fonction donneTousLesCoupsValides(char * grille, char camp, Maillon * teteMaillon) qui rend ma liste chainé via mon pointeur sur teteMaillon.
La fonction compile mais je l’ai pas téstée.
C’est pour cela que je crée la deuxieme fonction:
char * donneStringCoupsValides(char -grille, char +camp)
qui elle me renvoie a la compile:


>make
gcc -Wall -pedantic -c representation.c
representation.c: In function `donneStringCoupsValides':
representation.c:237: erreur: type incompatibles dans affectation
make: *** [representation.o] Erreur 1

La ligne etant

[cpp]teteMaillon->coup=NULL; (ligne 76 de representation.c pour vous)[/cpp]

il y a donc un probleme a l’initialisation, mais quesqui va pas ???

Dans representation.h
[cpp]

typedef struct _StrCoup {

                       int ligne;
                       int colonne;
                       char camp;   

                    } StrCoup;

typedef struct _Maillon {

                      StrCoup coup;
                      struct _Maillon * suivant;

                    } Maillon;

[/cpp]

Dans representation.c
[cpp]
/*******************************************************************
*

  • Nom : int donneTousLesCoupsValides(
  •                                      char * grille, 
    
  •                                      char camp,
    
  •                                      Maillon * teteMaillon
    
  •                                  )
    
  • Entrée : char * grille,
  •      char camp,
    
  •      Maillon * teteMaillon
    
  • Sortie : nombre de coups valides pour camp
  •      Liste tous les coups valides pour camp 
    
  •      et les enregistrent dans la liste chainée
    

******************************************************************/

int donneTousLesCoupsValides(char * grille, char camp, Maillon * teteMaillon)
{
int i,j,cpt;

cpt=0;
for(i=0;i<DIMENSION_MAX;i++)
for(j=0;j<DIMENSION_MAX;j++)
if(coupValide(camp,grille,i,j))
{
Maillon * newMaillon = (Maillon *)malloc(sizeof(Maillon));

              StrCoup newStrCoup;
              newStrCoup.ligne=i;
              newStrCoup.colonne=j;
              newStrCoup.camp=camp;
              
              newMaillon->coup=newStrCoup;
              newMaillon->suivant=teteMaillon;

              cpt++;
          }

return cpt;
}

/*******************************************************************
*

  • Nom : char * donneStringCoupsValides(char -grille, char +camp)
  • Entrée : char * grille, char camp
  • Sortie : char * representant la liste des coups suivit de \0
  •      Liste tous les coups valides pour camp 
    
  •      et les retournes dans un char *
    

******************************************************************/

char * donneStringCoupsValides(char * grille, char camp)
{

Maillon tmp;
Maillon * teteMaillon;
char * coups;
int index=0;

teteMaillon = (Maillon *)malloc(sizeof(Maillon));

teteMaillon->coup=NULL;

printf(“Entrée donneStringCoupsValodes\n”);
donneTousLesCoupsValides(grille,camp,teteMaillon);
printf(“Sortie donneTousLesCoupsValides\n”);

coups=(char *)malloc(sizeof(char)*10000);

do
{ tmp.coup=teteMaillon->coup;
tmp.suivant=teteMaillon->suivant;
*(coups+index)=’(’; index++;
*(coups+index)=tmp.coup.colonne+‘a’; index++;
*(coups+index)=’ ‘; index++;
*(coups+index)=tmp.coup.ligne+1; index++;
*(coups+index)=’)’; index++;
*(coups+index)=’ '; index++;

} while(tmp.suivant!=NULL);

*(coups+index)=’\0’;

return coups;

}

[/cpp]

Cordialement

coup est une structure, tu ne peux pas le mettre à null, tu peux seulement faire coup.ligne=NULL; coup.colonne=NULL;…

ou alors tu créés un pointeur sur ta structure: StrCoup *coup; et là tu peux faire coup=NULL;
(en n’oubliant pas de faire un malloc dès que tu en auras besoin)

Ok merci, jai mis carrement teteMaillon=NULL;
Mais maintenant j’ai une erreur de segmentation pendant l’execution, apres la ligne 80 il semblerais. (Dailleur un printf rajouter ligne 38 montre bien quil rentre 4 fois dnas la boucle)
Quelqu un maitrise les listes chainéS?
Je crois que je fait pas le bon algo, jajoute en tete de chaine, il vaut mieux que je fasse l’inverse non ?

Apres toutes les modifs que j’ai fait, il compile, aucune erreur de segmentation mais il affiche pas les coups :frowning:
il n’ affiche pas les printf("while ") dans le while (ligne 55 pour vous) donc il semble que je fait mal les affectation dans la 1ere fonction
et qu’il a apres l’apel toujours teteMaillon a null. :o

si join mon code
[cpp]
int donneTousLesCoupsValides(char * grille, char camp, Maillon * teteMaillon)
{
int i,j,cpt;

cpt=0;
for(i=0;i<DIMENSION_MAX;i++)
for(j=0;j<DIMENSION_MAX;j++)
if(coupValide(camp,grille,i,j))
{
Maillon * newMaillon = (Maillon *)malloc(sizeof(Maillon));

              StrCoup newStrCoup;
              newStrCoup.ligne=i;
              newStrCoup.colonne=j;
              newStrCoup.camp=camp;
                             
              newMaillon->coup=newStrCoup;
              newMaillon->suivant=teteMaillon;
              teteMaillon=newMaillon;

              cpt++;
              printf("1 coup, ");
          }

return cpt;
}

char * donneStringCoupsValides(char * grille, char camp)
{

/* Maillon tmp;

*/
Maillon * teteMaillon;
char * coups;
int index=0;

teteMaillon = (Maillon *)malloc(sizeof(Maillon));

teteMaillon=NULL;

printf(“Entrée donneStringCoupsValodes\n”);
donneTousLesCoupsValides(grille,camp,teteMaillon);
printf(“Sortie donneTousLesCoupsValides\n”);

coups=(char *)malloc(sizeof(char)*10000);

while(teteMaillon!=NULL)
{
printf("while 1 fois, ");

   *(coups+index)='(';                        index++;
   *(coups+index)=teteMaillon->coup.colonne+'a';       index++;  
   *(coups+index)=' ';                        index++; 
   *(coups+index)=teteMaillon->coup.ligne+1;           index++;
   *(coups+index)=')';                        index++; 
   *(coups+index)=' ';                        index++;

   teteMaillon=teteMaillon->suivant;

};

*(coups+index)=’\0’;

return coups;

}
[/cpp]

en général on parcourt la liste chaninée et dès qu’on est au dernier, on ajoute.

pour le seg fault, tu dois certainement tenter d’accaeder à un pointeur null.

pour les listes, un petit tuto pour comprendre le principe:

Je veux pas parcourir toute la liste, sinon j’aurais fait un tableau.
Il est possible d’ajouter en tete non ?
On a vu ca en cours mais c’est pas si simple a appliquer :confused:

typedef struct _Maillon {

StrCoup* coup;

struct _Maillon * suivant;

} Maillon;

manque un * avant coup

Pour les seg fault, y a pas que les pointeurs NULL.

Le mieux c’est de faire

gcc -ansi -Wall -g -c representation.c

(ou sur tout le programme)

puis gdb Othello
puis ‘run’
puis tu essayes d’avoir ton seg. fault
puis ‘bt’
tu auras là le traçage des appels de fonction, avec en sus là où ça a planté

J’ai plus de Seg fault la les mecs :slight_smile:
Ca doit etre dans mon algo lors de l’ajout d’un maillon

EDit: je compile avec -Wall -pedantic

a l’execution j’ai
Entrée donneStringCoupsValides
1 coup
Pointeur de tete: 0x8845090
valeur: b 1
1 coup
Pointeur de tete: 0x88450a8
valeur: a 2
1 coup
Pointeur de tete: 0x88450c0
valeur: d 3
1 coup
Pointeur de tete: 0x88450d8
valeur: c 4
Sortie donneTousLesCoupsValides
Pointeur de tete: (nil)

Bon bah resolu :slight_smile:

cf: la preuve
[fixed]
a b c d e f g h
±–±--±–±--±–±--±–±--+
1 | | | | | | | | |
±–±--±–±--±–±--±–±--+
2 | | o | | | | | | |
±–±--±–±--±–±--±–±--+
3 | o | o | o | x | | | | |
±–±--±–±--±–±--±–±--+
4 | | | x | x | x | | | |
±–±--±–±--±–±--±–±--+
5 | | | | x | o | | | |
±–±--±–±--±–±--±–±--+
6 | | | | | | | | |
±–±--±–±--±–±--±–±--+
7 | | | | | | | | |
±–±--±–±--±–±--±–±--+
8 | | | | | | | | |
±–±--±–±--±–±--±–±--+

Il y a 6 CoupsValides: (a 1) (a 2) (c 2) (f 5) (e 6) (f 6)
Veuillez entrez un coup x (format: a 1,…,h 8)
puis appuyer sur Entrée

[/fixed]

et le codes des fonctions:

[cpp]
int donneTousLesCoupsValides(char * grille, char camp, Maillon * teteMaillon)
{
int i,j,cpt;
Maillon * courantMaillon;
Maillon * newMaillon;
StrCoup newStrCoup;

courantMaillon=teteMaillon;
cpt=0;

for(i=0;i<DIMENSION_MAX;i++)
for(j=0;j<DIMENSION_MAX;j++)
if(coupValide(camp,grille,i,j))
{

              newMaillon=(Maillon *)malloc(sizeof(Maillon));
              
              newStrCoup.ligne=i;
              newStrCoup.colonne=j;
              newStrCoup.camp=camp;
       
              courantMaillon->coup=newStrCoup;
              courantMaillon->suivant=newMaillon;
              courantMaillon=newMaillon;
              
              cpt++;
          }

return cpt;
}

char * donneStringCoupsValides(char * grille, char camp)
{

Maillon * teteMaillon;
Maillon * courantMaillon;
char * coups;
int index;

teteMaillon=(Maillon *)malloc(sizeof(Maillon));
coups=(char *)malloc(sizeof(char)*100);
index=0;

printf("Il y a %i ",donneTousLesCoupsValides(grille,camp,teteMaillon));

courantMaillon=teteMaillon;

while(courantMaillon->suivant!=NULL)
{

   *(coups+index)='(';                                      index++;
   *(coups+index)=courantMaillon->coup.colonne+'a';         index++;  
   *(coups+index)=' ';                                      index++; 
   *(coups+index)=(courantMaillon->coup.ligne)+'1';         index++;
   *(coups+index)=')';                                      index++;  
   *(coups+index)=' ';                                      index++;

   courantMaillon=courantMaillon->suivant;

};

*(coups+index)=’\0’;

return coups;

}

[/cpp]

J’aimerai pas être à la place du programme si un cochon éxécute subtilement un sbrk quelque part… Au passage, juste comme ça :

  1. quand on alloue, … on vérifie que ça s’est bien passé. La mémoire, c’est pas infini
  2. quand on connaît le nombre total des éléments de la liste (eg: tu peux jouer DIMENSION_MAX^2 fois, je pense) on ne fait pas une liste par pointeur, mais par tableau (gain de place, de temps, etc).

Ce sont des conseils, c’est pas une critique.

C’est juste qu’il faut remarquer que ton malloc c’est par un truc léger: c’est gourmand. Pour ta structure, ça fait 9 (taille de struct _Coup), + 4 (taille de suivant) 13 octets tout le temps bouffés, plus les saloperies du malloc (soit 20 octets fastoches)

Je connais pas sbrk, c’est juste un jeu d’othello avec IA pas un module de lancement d’ariane 5 :stuck_out_tongue:
Si je teste le malloc et qu’il ya plus de place je fait koi ?
printf(“La mémoire de l’ordinateur est saturé\n”); [:matleflou]

et en quoi c’est gourmand, j’ai pas compris ?
J’ai fait une liste chainée parce que à la fac ils aiment bien ca pendant les partiels alors un peu d’entrainement me fait pas de mal ^^

Jrechigne pas sur 20 octets on taf sur des 256 mo de ram :whistle:
Par contre le gain de vitesse :slight_smile:

[:abricot] [:matleflou]

… sigh

Tu sais comment fonctionne un programme au juste? On ne t’as pas parlé de trois choses essentielles ? Les données textes, la pile et le tas (le fatras). Tout ça tient sur une certaine taille (par ex: 32Mo), et lorsque tu dépasses, qu’il n’y a réellement plus de mémoire, ben ça ne peut plus rien allouer.

Sans oublier que malloc/calloc/free ne sont pas des fonctions magiques qui quand tu demandes X octets de mémoire te le font comme ça. Il y a toute une notion d’allocation là dedans.

non mais ya pas de probleme
mais je te dit juste qu’estque je fait si on peut plus allouer de mémoire pour mon jeu?
A part faire un printf(“ACheter plus de ram svp\n”); quesque je peux faire concretement ?

EDIT: c’est un projet pour la fac, ils nous demande de faire tel ou tel truc je le fais, c’est comme les variables globales, ils veulent que j en fasse une, j’en fait une…
Pour les malloc on a meme pas parler de test !!!

hé bé… :o

sn-> j’avoue que je suis dans la meme situation que le syndic, j’utilise les malloc et free sans me soucier de ce qui se passe réellement derriere [:austindangerpowers]

tu conseilles quoi pour eviter certaines mauvaises surprises à part tester la valeur retour du malloc ?

Alors d’une, mon ordi lag. De deux, je sais pas pourquoi, de trois je sais pas pourquoi je sors ça.

Si tu veux quand tu alloue, malloc va parcourir une liste chainée de pointeur pour te récupérer une zone de données adaptée à tes besoins.

Une fois que tu as finis de travailler avec ta mémoire dynamique, si tu ne la libère pas, hé bien malloc va pédaler pendant des heures pour retrouver de la mémoire libre.

De plus, dés qu’il aura bouffé tout l’espace mémoire disponible, il cherchera à l’agrandir. Et certainement que si le programme a besoin de grandir mais qu’il ne peut pas, hé bien il sera déplacer sur une autre page mémoire / etc.

Et puis si tu n’as plus de place (et pas la peine de dire j’ai 256 Mo tout va bien), en gros tu peux plus trop allouer, ni continuer. IL est donc d’usage de faire un petit printf à la con (ou une macro, ou perror( FILE )) pour dire où ça a planté, et faire un return NULL, et surtout ne pas jouer avec des pointeurs NULL.

C’est tout.

ok, merci pour ces precisions :jap: