[C]Liste chaînée qui merdoie

Salut les geeks, je suis une fois de plus en train de m’arracher les cheveux sur du code et j’implore votre aide.
J’ai un vecteur d’entiers contenant des nombres divers, et j’aimerais créer une liste reprenant les nombres pairs du vecteur ainsi que le nombre de fois qu’ils apparaissent dans le vecteur. Je vais montrer ici la fonction d’ajout dans la liste que j’ai écrite (notez que la liste est déjà créée avec un premier élément quand j’appelle cette fonction):

Le problème avec cette fonction c’est que le premier élément est bien indiqué (ainsi que le ombre de fois qu’il apparait dans le vecteur) mais après j’obtiens des nombres farfelus dans ma liste, je soupçonne que le chaînage des éléments se passe mal (problème d’adresse) mais je n’arrive pas à trouver la/les lignes qui causent problème.

Je précise que chiffre contient la valeur du nombre à ajouter (j’ai déjà vérifié qu’il était pair) et pt contient le pointeur de tête de la liste (qui contient déjà un élément je le rappelle).
[codebox]void ajouterpair(int chiffre,PAIR *pt)
{
int doublon=0,
stop=0;
PAIR *Pnouv=NULL;

while(stop<9 && doublon==0)        /*J'ai mis 9 car il y a 9 nombres dans le vecteur*/
{
	if(pt->valeur==chiffre)          /*Pour voir si le nombre est déjà dans la liste*/
	{
		pt->cpt++;                  /*compte le nombre de fois que le nombre apparait dans le vecteur*/
		doublon=1;                  /*nombre déjà dans la liste donc pas besoin de le rajouter*/
	}
	if(pt->psuiv==NULL)
	{
		stop=10;                     /*Sort de la boucle si on est en bout de liste*/
	}
	else
	{
		pt=pt->psuiv;              /*avance dans la liste*/
		stop++;
	}
}
if(doublon==0)
{
	Pnouv=malloc(sizeof(PAIR)); /*ajout d'un nombre dans la liste s'il n'y est pas déjà*/
	Pnouv->valeur=chiffre;
	Pnouv->cpt=1;
	Pnouv->psuiv=NULL;
	pt->psuiv=Pnouv;                 /*Ici je raccroche le nouvel élément en bout de liste. ça planterait ici?*/
}

}
[/codebox]

Un grand merci pour votre aide!



Ca fait quoi si tu mets ça  ?
[code]pt->cpt = (pt->cpt)+1;[/code]

Ca fait quoi si tu mets ça ?

J’ai du mal à comprendre ce que tu veux faire, tu peux pas filer tout le programme ?

avavrin : ça fait la même chose

Justement je suis pas sur, ya pas une confusion entre incrémenté l’adresse pointeur ou incrémenter la valeur du pointeur ?

j’ai pas envi de tester…

Et file tout le code, ca ira plus vite pour debuger :slight_smile:

Pourquoi faire une liste chaînée si tu sais qu’elle contiendra 9 éléments? Ce serait pas plus simple avec un bête tableau?
Sinon je suis pas bien sûr que l’erreur se situe dans ce bout de code.

[quote=« avavrin, post:4, topic: 47557 »]Justement je suis pas sur, ya pas une confusion entre incrémenté l’adresse pointeur ou incrémenter la valeur du pointeur ?

j’ai pas envi de tester…

Et file tout le code, ca ira plus vite pour debuger :crying:[/quote]
Non Drealmer a raison. Quand tu doutes, une recherche « C operator precedence » sur Google aide bien :slight_smile:

Comme demandé voici un ficher texte avec la source, merci :slight_smile: En passant, je ne savais pas que le forum interdisait l’envoi de fichiers .c

@MadGnome: oui ça serait hyper plus simple de travailler avec des vecteurs, mais le but est de se faire les dents sur les files :crying:

Le problème est dans ta fonction d’affichage.

void afficherpair(PAIR *pt) { printf("Valeurs paires:\n\n"); printf("Valeur\tFrequence\n"); while(pt!=NULL) { printf("%d\t",pt->valeur); printf("%d\n",pt->cpt); printf("A: %x ",pt); printf("S: %x",pt->psuiv); printf("\n"); pt = pt->psuiv; } printf("\n\n"); }

J’avais corrigé cette erreur dans l’ajout, mais j’étais tellement braqué sur cette fonction que je n’ai pas pensé à re-vérifier l’affichage. Heureusement que tu l’as remarqué! :slight_smile:

Bon ça ne règle pas entièrement le problème (il n’affiche que la première valeur paire et son nombre d’apparitions) mais au moins ça me remet sur la bonne piste. Merci merci merci!

[quote=« Lupuss, post:9, topic: 47557 »]J’avais corrigé cette erreur dans l’ajout, mais j’étais tellement braqué sur cette fonction que je n’ai pas pensé à re-vérifier l’affichage. Heureusement que tu l’as remarqué! :slight_smile:

Bon ça ne règle pas entièrement le problème (il n’affiche que la première valeur paire et son nombre d’apparitions) mais au moins ça me remet sur la bonne piste. Merci merci merci![/quote]
Gaffe que j’ai corrigé deux trucs, la condition du while, et le « pt = pt->psuiv ». Avec ça, chez moi ça marche, ça renvoie 6 et 2.

(Un peu à côté de la plaque, mais j’ai pas vu passer d’appel à free dans le programme, pourtant ya un malloc qui traine …)

Effectivement tu as raison, j’avais gardé l’alternative originale de peur que la dernière incrémentation du pointeur l’envoie n’importe où, mais en fait ça ne change rien. Bon ben la prochaine fois que tu passes à Liège tu as droit à des bières :crying: (mais après le 16 juin stp :slight_smile: )

Edit @ fser: Si on pouvait supprimer des éléments j’aurais mis un free bien sur, sinon c’est pas propre. Mais ici car on ne supprime pas d’éléments de la liste dans le programme, et la mémoire est libérée en quittant le programme si je ne m’abuse.

Il n’y a pas un problème dans cette partie-là ?

Pnouv=malloc(sizeof(PAIR)); Pnouv->valeur=chiffre; Pnouv->cpt=1; Pnouv->psuiv=NULL; pt->psuiv=Pnouv;
pt pointe sur le premier élément de la liste, on ajoute le nouvel élément après puis plus rien donc a priori les autres éléments sont perdus.

Sinon :
[ul]
[li]Règle ton éditeur pour qu’il remplace les tabulations par des espaces sinon ça peut donner n’importe quoi (essaie avec Notepad et un code qui contient beaucoup d’indentation par exemple).[/li][li]main() retourne toujours une valeur de type int (0 ou EXIT_SUCCESS si tout s’est bien passé, sinon EXIT_FAILURE). Il vaut mieux ajouter le “void” quand une fonction n’a pas de paramètres.[/li][li]Tu peux écrire affichervecteur(vec); au lieu de affichervecteur(&vec[0]); (la plupart du temps quand on utilise le nom d’un tableau dans une expression il est remplacé par un pointeur sur le premier élément).[/li][li]Pour afficher les pointeurs dans afficherpair() : printf("A: %p ",(void*)pt);.[/li][/ul]

J’espère que tu blagues…

DaP:

  • Pour le main j’ai bien mis un void si tu regardes.
  • pour vec au lieu de &vec[0] c’est juste, j’avais oublié
  • pour l’indentation par contre, pareil que Kineox :slight_smile:

main() est toujours un int, voir ici : http://www.research.att.com/~bs/bs_faq2.html#void-main

Mais d’accord, c’est un peu de l’enculage de mouches quand même.

Effectivement, pour les parametres, mettre void ou ne rien mettre ce n’est pas la meme chose. Mettre void en parametre ca veut dire que la fonction ne prend aucun parametre, et le compilateur signalera une erreur si l’on tente d’appeller la fonction avec des parametres. Ne rien mettre par contre, ca veut dire que la fonction prend peu etre des parametres, ou pas, mais on s’en fout par ce qu’on les utilise pas. Dans ce cas la le compilateur ne signale pas d’erreur si on appelle la fonction avec des parametres (ils sont simplement ignorés).

Entre ces deux-là tu préfères lequel si au départ tu voulais des tabulations de 3 espaces ?

[quote=« Drealmer, post:16, topic: 47557 »]main() est toujours un int, voir ici : http://www.research.att.com/~bs/bs_faq2.html#void-main

Mais d’accord, c’est un peu de l’enculage de mouches quand même.[/quote]
Je ne vois pas où est le problème, pour être portable main() doit retourner un int et il n’y a pas d’autre solution. Ça permet par exemple à quelqu’un qui appelle ton programme dans un batch d’afficher un message d’erreur si il y a eu une erreur.

C’est encore plus vicieux parce que ça dépend de si c’est une déclaration ou une définition de fonction. Enfin GCC et Visual Studio ne le prennent pas comme ça mais ICC si. De toute façon les listes de paramètres vides c’est une « obsolescent feature » qui est juste là pour supporter le vieux code.

[quote=« DaP, post:18, topic: 47557 »]Entre ces deux-là tu préfères lequel si au départ tu voulais des tabulations de 3 espaces ?

[/quote]
Tu utilises un vrai éditeur qui te permet de fixer la taille des tabulations.

Et de toute façon vouloir des tabulations de 3 espaces est un signe évident de trouble psychique :slight_smile:

Les tabs, c’est 4 espaces. Point barre .|