Forum Clubic

[aide]Débutant en C - bug bug bug :s

D’abord, bonjour a tous, ensuite voici mon probleme :
J’ai commencé cette années des cours du soir en programmation, par pur masochisme d’ailleurs car cela n a rien a voir avec mon taf…
Nous arrivons en période d examen et j ai un programme a rendre…
Seulement voila, je deviens fou depuis des jours et des jours, sans trouver la solution a mon probleme.
Je ne sais pas si qq peut m’aider mais ce serait vraiment cool…

Voila l’explication succinte de ce que dois faire le programme :
Gerer une course de ski…
On doit encoder des participants (sauver dans un fichier)
On doit relire se fichier te placer les renseignements dans une structure, qui sera gerée en file d attente…(pointeur p_next inside)
ensuite on doit tirer aléatoirement un N° de dossard unique pour chaque participant, trier la file d attente sur base du N° de dossard.
Ensuite voila le deroulement de la course :
chaque coureur passe par N° de dossard, on encode en tps en secondes et centiemes , chaque participant est alors inséré dans une liste triée par temps de parcours…
Apres chaque participant, on affiche les 3 premiers et a la fin le classement complet.
L’ensemble doit etre gére dynamiquement…vive les mallocs

L’endroit ou je bloque ?
Et bien lors du passage des participants , le premier prends bien sur le meilleur temps dans la liste puis je dois inserer les suivants en fct de leurs temps respectifs…
ET la, ca bug et je ne comprend pas, j ai retourné le code dans tous les sens alors en dernier recours je demande un coup de pouce , certainement pas pour me faire mon programme mais juste pour m aider a passer ce bug…
D’avance merci a ceux qui prendrais la peine de m aider.
je vais vous mettre mon code.
On ne se moque pas hien, je suis débutant



#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#include<math.h>
#include<ctype.h>
#include<time.h>
#define NOM_FICHIER "fichier.txt"

struct RUNNERS
{
char nom[30];
char prenom[30];
char nation[3];
int dossard;
int temp;
struct RUNNERS *p_next;
};


void afficher_liste (struct RUNNERS *,int);//fct d affichage d'une structure
void encode_runners(struct RUNNERS *);
int verif_nation(char *,char [][3],int);
void maju (char []);//fct de mise en majuscule(remplace strupr
int verif_nom(char *);
int verif_prenom(char *);
void lire_fichier(struct RUNNERS *,int *);
void tire_dossard (struct RUNNERS *,int);
void affiche_erreur(int);//fct indique le type d erreur
int est_admis(char);//fct determine si un caractere est autorisé
struct RUNNERS * cree_liste_triee (struct RUNNERS *);//fct crée une liste triée
struct RUNNERS * courir (struct RUNNERS *,int);


int main()
{

int nb_runners=0;
struct RUNNERS *p_debut_struct,*classement;
p_debut_struct=NULL;
p_debut_struct=(struct RUNNERS *)malloc (sizeof(struct RUNNERS));


if (p_debut_struct==NULL)
{
printf("Pas de memoire disponible...\n");
system("pause");
exit(0);
}

printf("4e Criterium internationnal de la jambe cassee\n\n");

//encode_runners(p_debut_struct);
lire_fichier(p_debut_struct,&nb_runners);
afficher_liste(p_debut_struct,nb_runners);
printf("\n\n\nListe d attente des participants.\n\n");
system("pause");
tire_dossard (p_debut_struct,nb_runners);
afficher_liste(p_debut_struct,nb_runners);
printf("\n\n\nListe des participants et de leur dossard.\n\n");
system("pause");
p_debut_struct=cree_liste_triee (p_debut_struct);
afficher_liste(p_debut_struct,nb_runners);
printf("\n\n\nVoici les participants par N de dossard.\n");
system("pause");
classement=courir(p_debut_struct,nb_runners);
afficher_liste(classement,nb_runners);
system("pause");
return 0;
}

////////////////////////////////////////////////////////////////////////////////
/////////////////////Encode coureurs dans fichier///////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void encode_runners(struct RUNNERS *p_debut_struct)
{

char recommence=-1;
int valide=0,nelem=0;
char buf_nom[30],buf_prenom[30],buf_natio[3];
char nation[][3]={"AU","GB","US","AT","BE","BA","BG","CA","CN","HR","CY","DK","FI","FR","DE","GR","HU","IE","IL","IT","JP","LU","NL","NO","PL","PT","RU","SM","SK","SI","ES","SE","CH","TR"};
FILE *pfich=NULL;
pfich=fopen(NOM_FICHIER,"r");
if(pfich==NULL)
{
pfich=fopen(NOM_FICHIER,"w");
}
else
{
pfich=fopen(NOM_FICHIER,"w");
}

do{
printf("Voulez vous encoder un coureur ?");
recommence=getch();

if(recommence=='O'||recommence=='o')
{

do{
printf("\nQuel est le nom du participant ?\n");
gets(buf_nom);
maju(buf_nom);
valide=verif_nom(buf_nom);
if(valide==0) affiche_erreur(1);
}while(buf_nom[0]==0||valide==0);

do{
printf("\nQuel est le son prenom ?\n");
gets(buf_prenom);
valide = verif_prenom(buf_prenom);
if (valide==0) affiche_erreur(2);
}while(buf_prenom[0]==0||valide==0);

do{
printf("Quelle est la nationnalite du coureur ?\n");
gets(buf_nati;
maju(buf_nati;
valide=verif_nation(buf_natio,nation,sizeof(nation)/sizeof(nation[0]));
if(valide==0) affiche_erreur(3);
}while(valide==0);


nelem++;
printf("\nDebug ->%d participant",nelem);
fprintf(pfich,"%s,%s,%s\n",buf_nom,buf_prenom,buf_nati;
fflush(pfich);
printf("\nSauvegarde sur fichier effectuee\n");


}
}while(recommence=='o'||recommence=='O');

if(nelem==0)
{
printf("Pas de participant\n");
printf("\nVous n'esperiez quand meme pas m avoir avec ca ?\n");
printf("il va falloir faire mieux..car sans participant..PAS DE COURSE-->CYA\n");
system("pause");
exit(0);
}
if(nelem==1)
{
printf("\nA vaincre sans peril, on triomphe sans gloire... \n");
system("pause");
}
if(nelem==2)
{
printf("Un petit 3e pour pouvoir faire un podium non ? \n");
}
fclose(pfich);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////Vérifie nationnalité du coureur/////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int verif_nation(char buf_natio[3],char nation [][3],int nb_nations)
{

int valide=-1,i=0,comp=-1;
for(i=0;comp!=0&&i<nb_nations;i++)
comp = strcmp(buf_natio,nation[i]);

if(comp==0) valide=1;else valide=0;

return valide;
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////Fct lire fichier//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void lire_fichier(struct RUNNERS *p_debut_struct,int *nb_runners)
{

char buf_nom[30],buf_prenom[30],buf_natio[4];
struct RUNNERS *p_courant, *p_suiv, *p_prec;
FILE *pfich;
p_courant=(struct RUNNERS *)malloc(sizeof(struct RUNNERS));
p_courant=p_debut_struct;

pfich=fopen(NOM_FICHIER,"r");
do{
if (!feof(pfich))
{
fscanf(pfich,"%[^,],%[^,],%s\n",buf_nom,buf_prenom,buf_nati;
p_prec=p_courant;
strcpy(p_courant->nom,buf_nom);
strcpy(p_courant->prenom,buf_prenom);
strcpy(p_courant->nation,buf_nati;
p_courant->temp=99999;
p_courant->dossard=0;
p_suiv=(struct RUNNERS *)malloc(sizeof(struct RUNNERS));
p_courant->p_next=p_suiv;
p_courant=p_suiv;
p_courant->p_next=NULL;
*nb_runners=*nb_runners+1;
}

}while(!feof(pfich));

p_prec->p_next=NULL;

fclose(pfich);

}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////Fct tire dossard//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void tire_dossard (struct RUNNERS *p_debut_struct,int nb_runners)
{

int i,j,doublon=1;
int ta[nb_runners];
srand(time(NULL));
for (i=0;i<nb_runners;i++)
{
do
{
ta[i]=1+rand()%nb_runners;
for (j=0,doublon=0;j<i;j++)
if (ta[i]==ta[j])doublon = 1;
}while(doublon==1);
}

for (i=0;i<nb_runners&&p_debut_struct!=NULL;i++)
{

p_debut_struct->dossard=ta[i];
p_debut_struct=p_debut_struct->p_next;

}

}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////Fct verif nom///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int verif_nom(char *buf_nom)
{

int i, valide=1;

for (i = 0; valide && buf_nom[i] != 0; i++)
{
if (!isupper(buf_nom[i]) &&
!isspace(buf_nom[i])) {
valide = 0;
}
}
return(valide);

}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////Fct verif prenom////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int verif_prenom(char *buf_prenom)
{

int i, valide=1;

for (i=0;valide&&buf_prenom[i]!=0;i++)
{
if (!isalpha(buf_prenom[i])&&!est_admis(buf_prenom[i])&&buf_prenom[i] != '-')
{
valide = 0;
}
}

return(valide);

}

////////////////////////////////////////////////////////////////////////////////
/////////////////////////Fct caractere admis dans prenom////////////////////////
////////////////////////////////////////////////////////////////////////////////

int est_admis(char c)
{

int i, valide=0;
char liste[]={-123,-125,-124,-126,-118,-120,-119,-115,-116,-117,-107,-109,-108,-105,-106,-127,-121,0};

for (i=0;!valide&&liste[i]!=0;i++)
{
if(c==liste[i])
valide = 1;
}
return valide;

}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////Fct mise en majuscule///////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void maju (char phrase[])
{

int i;
for(i=0;phrase[i]!=0;i++)
phrase[i]=toupper(phrase[i]);

}

////////////////////////////////////////////////////////////////////////////////
///////////////////////////////Fct affiche erreurs//////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void affiche_erreur(int erreur)
{

switch(erreur)
{
case 1 : printf("Ce nom n'est pas valide \n");
break;
case 2 : printf("Ce prenom n'est pas valide\n");
break;
case 3 : printf("Cette nationnalite n'est pas valide\n");
break;
default: printf("y a pas de default \n");
}

}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////Fct cree liste triee/////////////////////////////
////////////////////////////////////////////////////////////////////////////////

struct RUNNERS * cree_liste_triee (struct RUNNERS *p_debut_struct)
{

int ppetite_valeur;
struct RUNNERS *p_courant,*p_prec,*p_min,*p_min_prec,*p_liste_debut,*p_liste_courant,*p_liste_prec;
p_courant=p_prec=p_min=p_min_prec=p_liste_debut=p_liste_courant=p_liste_prec=NULL;//j'initialise les pointeurs a NULL
//p_min=(struct RUNNERS *)malloc(sizeof(struct RUNNERS *));
do {
ppetite_valeur=100;
for (p_courant=p_debut_struct,p_prec=NULL;p_courant!=NULL;p_prec=p_courant,p_courant=p_courant->p_next)
{
//si le dossard courant est plus pt que la +pt valeur
if (p_courant->dossard<ppetite_valeur)
{
ppetite_valeur=p_courant->dossard;//ppetite valeur prend la valeur du dossard courant
p_min=p_courant; //Adresse du +petit dossard = p_courant
p_min_prec=p_prec;//Adresse du precedent au +petit dossard = p_prec
}

else
{
//on ne fait rien ..
}

}//fin du for

// On supprime
if ( p_min==p_debut_struct )//si l adresse de la ppetite valeur est au debut de ma struct
{
p_debut_struct=p_debut_struct->p_next;//j avance d un element dans cette struct
}

else
{//si l adresse de la ppetite valeur N'est PAS au debut de ma struct
p_min_prec->p_next=p_min->p_next;
}//le suivant de l ancien plus pt deviens le suivant du plus petit


if ( p_liste_debut == NULL ) //si la liste est vide
{
p_liste_debut=p_min; //je mets le debut de liste a l adresse contenant la +pt valeur
p_liste_debut->p_next=NULL;//je mets son suivant a null
p_liste_courant=p_liste_debut;//je mets la liste courante au debut de la liste
p_liste_prec=p_liste_courant;//je mets le precedent de la liste à l adresse de la liste courante c a d au debut de la liste
}
else //si la liste n est pas vide
{
p_liste_prec->p_next=p_min; //je mets le suivant du precedent de la liste a l adresse du plus petit
p_liste_courant=(struct RUNNERS *)malloc(sizeof (struct RUNNERS *));//j alloue de la memore POUR LE POINTEUR liste courante
p_liste_courant=p_min;//je mets la liste courante a l adresse du plus petit
p_liste_courant->p_next=NULL;//je mets son suivant a NULL
p_liste_prec=p_liste_courant;//je recule d un coup...
}

}while(p_debut_struct!=NULL);//tant que la file d attente n est pas vide



return p_liste_debut;//je retourne l adresse du debut de la liste
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////Fct AFFICHE liste //////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void afficher_liste ( struct RUNNERS * p_debut ,int nb_runners)
{

system("cls");
printf("\t\t\t******************************\n");
printf("\t\t\t***Liste des participants :***\n");
printf("\t\t\t******************************\n\n\n\n");
printf("Dossard\tNom\t\tprenom\n");
printf("------------------------------\n");
struct RUNNERS *p_courant;
printf("pdeb : %p\n",p_debut);
for ( p_courant=p_debut; p_courant!=NULL; p_courant=p_courant->p_next )
{
printf("(%d)\t%s \t%s \t%d %p\n",p_courant->dossard,p_courant->nom,p_courant->prenom,p_courant->temp,p_courant);
}

}
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////Fct COURSE////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

struct RUNNERS * courir(struct RUNNERS *pdebut,int nb_runners)
{
char buf[30];
int temps, centi, podium=0, egal=0;
struct RUNNERS *ptrav, *pprec, *psuiv, *pdoigt, *pdoigtprec;
int DONE;

//pdoigt=( struct RUNNERS *)malloc(sizeof(struct RUNNERS));
//pdoigtprec=( struct RUNNERS *)malloc(sizeof(struct RUNNERS));
//p_min=(struct RUNNERS *)malloc(sizeof(struct RUNNERS *));
ptrav = pdebut;
pprec = NULL;
podium = 0;
//system("cls");

while(ptrav != NULL)
{
// On met le doigt sur l'element "courant"
if (pprec != NULL) pdoigtprec = pprec; //si je ne suis pas sur le 1er,

// Je mets le prec du doigt a prec
do
{
printf("entrez le temps de %s %s\n", ptrav->nom, ptrav->prenom);
printf("D'abord les secondes : ");
gets(buf); // Verifier pour les entrées de caracteres
temps = atoi(buf);
printf("temps : %d\n", temps);
temps = temps*100; // Pour passer les secondes en centiemes
}
while (buf[0] == 0 || temps > 5999);

do
{
printf("Et les centiemes : ");
gets(buf);
centi = atoi(buf);
temps = temps + centi;
printf("%6d%6d\n", temps/100, temps%100);
}
while (buf[0] == 0 || centi >= 100);

ptrav->temp = temps;

// Premier -> On le classe en premiere position
if(ptrav == pdebut)
{
printf("\nCOUCOU\n");
system("pause");

// On passe au suivant
pprec = ptrav;
ptrav = ptrav->p_next;
afficher_liste(pdebut, 0);
system("pause");
}
else // Pour les coureurs apres le premier
{
// Si le temp courant est le meilleur
if (ptrav->temp <= pdebut->temp)
{
printf("p_trav->temp <= pdebut->temp\n");
printf("adresse memoire du suivant : %p\n",ptrav);
system("pause");

// mirko // On memorise deja l'element suivant
psuiv = ptrav->p_next;

// On copie vers un pointeur qui designe le plus petit
//pprec->p_next = ptrav->p_next;
pprec->p_next = psuiv;
ptrav->p_next = pdebut;
pdebut = ptrav;

printf("\nCOUCOU2\n");
system("pause");


pprec = ptrav;
// mirko // ptrav = ptrav->p_next;
ptrav = psuiv;

afficher_liste(pdebut, 0);
system("pause");
}
else
{
// Sinon
// On reparcours depuis le debut pour l'inserer au bon endroit
// pdoigt garde un doigt sur l'element que l'on va inserer

//for( pdoigt=ptrav , pprec=NULL , ptrav=pdebut; ptrav->p_pnext!=pdoigt; pprec=ptrav , ptrav=ptrav->p_next )

/*
printf("ptrav : %p\n", ptrav);
printf("ptrav->next : %p\n", ptrav->p_next);
printf("pdoigt : %p\n", pdoigt);
*/

/* NE PAS OUBLIE DE NE PAS ALLER TROP LOIN EN CAS DE CLASSEMENT */
DONE = 0;
for (pdoigt = ptrav, pprec = NULL, ptrav = pdebut, pdoigtprec = NULL;
// mirko // ptrav->p_next != pdoigt;
!DONE && ptrav != pdoigt;

)
{
/*
printf("pprec : %p - ptrav : %p - ptrav->pnext %p \n", pprec,ptrav, ptrav->p_next);
system("pause");
*/
//printf("pprec->temp : %d \n",pprec->temp );

// mirko // if (ptrav != pdebut && ptrav->temp >= pprec->temp)
if (ptrav != pdebut && pdoigt->temp < ptrav->temp)
// On est un trop loin
// Alors on insere entre pprec et ptrav
{
pdoigtprec = pdoigt;
pprec->p_next = pdoigt;
// on avance le pdoigt
ptrav->p_next = pdoigt->p_next; // mirko
pdoigt->p_next = ptrav;
// afficher_liste(pdebut,0);
//system("pause");
DONE = 1; // mirko
}
//if (ptrav == pdebut) printf("ptrav au debut \n");

pprec = ptrav;
ptrav = ptrav->p_next;

}
//printf("pdoigt->pnext : %p ", pdoigt->p_next);

//ptrav = pdoigt->p_next;

if (pdoigtprec != NULL) ptrav = pdoigtprec->p_next->p_next;
else ptrav = ptrav->p_next;
//pprec = ptrav;

afficher_liste(pdebut, 0);
}
}
}
system("pause");
return pdebut;
}

As tu essayé un débugger ? (gdb par hasard)

tu vas rire mais je savais meme pas que ca existait :s
je fais une recherche :slight_smile:

option -g dans gcc

Cela te permettra d’éxecuter ton code pas à pas.

ça marche chez moi… (visualcpp)


Dossard Nom             prenom
------------------------------
pdeb : 002F4E30
(4)     g       h       320 002F4E30
(2)     e       f       401 002F4DA8
(1)     a       b       500 002F2C18
Appuyez sur une touche pour continuer...

Oui en fait ca marche bien SAUF qd j’ajoute des participants qui ont des temps se situant vers le mileu, avec 5, 6 participants, dans ce cas il m en vire un a chaque nouvel encodage :s

Tu ne pourrais pas définir un pointeur vers le précedent dans ta structure??

Bon tu as plusieurs cas de figure:

  • L’element est le premier saisi: on l’insere directement
  • L’element présente un nouveau record, on l’insere en tête
  • L’element est à insérer au milieu de la liste
  • L’element est à insérer à la finDonc c’est au niveau de ta fonction courir que ça déconne:

struct RUNNERS * courir(struct RUNNERS *pdebut,int nb_runners)
{
	char buf[30];
	int temps, centi, podium=0, egal=0;
	struct RUNNERS *ptrav, *pprec, *psuiv, *pdoigt, *pdoigtprec;

	//pdoigt=( struct RUNNERS *)malloc(sizeof(struct RUNNERS));
	//pdoigtprec=( struct RUNNERS *)malloc(sizeof(struct RUNNERS));
	//p_min=(struct RUNNERS *)malloc(sizeof(struct RUNNERS *));
	ptrav = pdebut;
	pprec = NULL;
	podium = 0;
	//system("cls");

	while(ptrav != NULL)
	{
  // On met le doigt sur l'element "courant"
  if (pprec != NULL) pdoigtprec = pprec; //si je ne suis pas sur le 1er,
  // Je mets le prec du doigt a prec
  do
  {
  	printf("entrez le temps de %s %s\n", ptrav->nom, ptrav->prenom);
  	printf("D'abord les secondes : ");
  	gets(buf); // Verifier pour les entrées de caracteres
  	temps = atoi(buf);
  	printf("temps : %d\n", temps);
  	temps = temps*100; // Pour passer les secondes en centiemes
  }
  while (buf[0] == 0 || temps > 5999);
  do
  {
  	printf("Et les centiemes : ");
  	gets(buf);
  	centi = atoi(buf);
  	temps = temps + centi;
  	printf("%6d%6d\n", temps/100, temps%100);
  }
  while (buf[0] == 0 || centi >= 100);
  ptrav->temp = temps;

  //1 premiere insertion
  if(ptrav==pdebut)
  	ptrav=ptrav->p_next;
  
  //2 nouveau record
  else if(ptrav->temp<pdebut->temp)
  {
  	psuiv=ptrav->p_next;
  	pprec=pdebut;
  	//recherche du précendent de ptrav..
  	for (pdoigt=pdebut;pdoigt!=ptrav;pdoigt=pdoigt->p_next)
    pdoigtprec=pdoigt;
  	pdebut=ptrav;
  	ptrav->p_next=pprec;
  	pdoigtprec->p_next=psuiv;

  	ptrav=psuiv;
  }
  /
  else
  {
  	for (pdoigt=pdebut,pdoigtprec=NULL;pdoigt!=NULL;)
  	{
    //4 on retombe sur notre ptrav, on l'insere
    if (pdoigt==ptrav)
    {
    	pdoigtprec=ptrav;
    	ptrav=ptrav->p_next;
    	pdoigt=NULL;
    }
    //3 on trouve un temps moins bon, on l'insere avant
    else if (pdoigt->temp > ptrav->temp )
    {
    	psuiv=ptrav->p_next;
    	ptrav->p_next=pdoigt;
    	pdoigt->p_next=psuiv;
    	if(pdoigtprec!=NULL) pdoigtprec->p_next=ptrav;
    	pdoigt=NULL;
    }
    else
    {
    pdoigtprec=pdoigt;
    pdoigt=pdoigt->p_next;
    }
  	}
  }
  system("pause");
  afficher_liste(pdebut, 0);
  }
	system("pause");
	return pdebut;
}

ça ne me semble pas nécessaire, on peut faire cet algo avec une liste simplement chainé, si on ajoute un lien vers le précédent, ça devient une liste doublement chainée, et c’est plus compliqué à gérer.

Ton problème vient-il du tri de ta liste? la fonction est un peu longue et devrais être découpé, tu pourrais notemment traiter ta liste comme un Type de Données Abstrait (un TDA) avec des fonctions de base create, insert, move, delete… ça éviterais d’avoir un problème lors de l’insertion d’un élément par exemple, et ça rendrais un peu plus lisible l’algo de parcours de liste qui te permet d’insérer les éléments un à un à ce que j’ai compris.
d’ailleurs, pour trier avec cet algo, tu pourrais simplement déplacer les éléments un à un sans les recopier.
:slight_smile:

Merci a tous de votre aide :slight_smile:
Je viens de scinder ma fct en deux et j ai recopié la partie jeu de pointeurs pour le classement
Et maintenant ca marche :slight_smile:

Merci à tous