|
|
|
|
Bonjour à tous!
Voila mon problème:
je cherche à récupérer, depuis un fichier, des données (entiers) que je veux placer dans une structure "voisinage"; le système fonctionne suivant une chaine de "voisinage", chaque "voisinage" comportant un pointeur de "voisinage" indiquant le "voisinage" suivant... (voir programme ci-après).
Voici la tête de mon fichier de données (appelé dans mon programme "Fvsng.txt" pour "famille de voisinage"):
1
1 0 0 1 1 0 0 0 0
1 1 1 1 1 1 1 1 1
Le premier entier sera affecté au champ "ordre" de la structure "voisinage". Puis, chaque ligne correspond au tableau d'entier v de la structure "voisinage".
Par exemple ici, j'aurai un ordre de 1 pour le 1° voisinage, la première ligne correspond au champ v du 1° voisinage, puis pointeur sur NULL; je rattache le tout à un 2° voisinage, ordre égal à 1, la deuxième ligne affectée au champ v du 2° voisinage, puis pointeur sur le 1° voisinage.
Voici mon programme:
#include <stdio.h>
#include <stdlib.h>
typedef struct voisinage {
int ordre;
int *v;
struct voisinage *suiv;
}voisinage;
voisinage vois;
int CreerFVoisinage(char *nom,voisinage *vsng)
{ int o,i;
voisinage *p;
FILE *f;
vsng=(voisinage *) malloc(sizeof(voisinage));
vsng=NULL;
/* Ouverture du fichier */
f = fopen (nom, "r");
if (f == NULL)
{
printf ("ERREUR fopen(%s)\n", nom);
return -1;
}
fscanf(f,"%d",&o);
while (!feof(f))
{
p=(voisinage *) malloc(sizeof(voisinage));
p->v=(int *) malloc(sizeof(int)*(2*o+1)*(2*o+1));
p->ordre=o;
for(i=0;i<(2*o+1)*(2*o+1);i++)
fscanf(f,"%d ",&(p->v[i]));
p->suiv=vsng;
vsng=p;
}
fclose(f);
return 0;
}
void afficheVoisinage(voisinage *vsng)
{
int i;
voisinage *p;
p=vsng;
while (p!=NULL)
{ printf("--------------------\n");
for(i=0;i<(2*p->ordre+1)*(2*p->ordre+1);i++)
printf("%d\n",p->v[i]);
p=p->suiv;
}
}
int main(int argc,char **argv)
{
CreerFVoisinage("Fvsng.txt",&vois);
afficheVoisinage(&vois);
return 0;
}
Ce qui est curieux, c'est que si je demande entre le fclose(f); et le return 0; de la fonction CreerFVoisinage la visualisation des données de ma chaine de "voisinage", tout semble avoir été affecté correctement, alors qu'à l'extérieur (dans le main avec la fonction afficheVoisinage) rien ne semble avoir été "mémorisé"...
Voila,
j'espère avoir été clair :-)
J'ajouterai que la compilation ne retourne aucune erreur ni aucun "warning" :-)
Je remercie d'avance tout ceux qui pourront m'aider sur ce petit problème de langage C, en tout cas tout ceux qui auront pris le temps de lire ce sujet jusqu'à la fin.
Cordialement,
Bastien.
Quand tu poste du code, mets le entre des balises de mise en forme "code" histoire que ce soit lisible ;-)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct voisinage {
int ordre;
int *v;
struct voisinage *suiv;
}voisinage;
voisinage *new_voisinage(){
voisinage *vois=(voisinage *)calloc(1,sizeof(voisinage));
return vois;
}
void del_voisinage(voisinage *vois){
free(vois.v);
free(vois);
}
void del_chaine(voisinage *debut){
voisinage *vois=debut;
voisinage *vois_suivant;
while(vois){
vois_suivant=vois->suivant;
del_voisinage(vois);
vois=vois_suivant;
}
}
//-------------------------------------------------
int *lire_ligne(char *str){
//1er passage : déterminer le nombre d'entiers :
unsigned int nb_elts,i;
int plop;
int *tab;
for(nb_elts=0;sscanf(buffer," %d ",&plop)==1;++nb_elts);
printf("La ligne [%s] contient %d element(s)\n",buffer,nb_ets);
//2e passage : remplir le tableau
tab=(int *)malloc(nb_elts*sizeof(int));
for(i=0;i<nb_elts;++i){
sscanf(buffer," %d ",&tab[i]);
}
return tab;
}
int lire_fichier(fp){
unsigned int ordre_lu;
voisinage *vois_suivant;
voisinage *vois_courant;
char buffer[255];
//1ere ligne
fscanf("%d\n",&ordre_lu);
vois_courant=new_voisinage(ordre_lu);
//Lignes suivantes
while(!feof(fp)){
fscanf("%s\n",&buffer);
printf("Lit %s\n",buffer);
vois_courant->v=lire_ligne(buffer);
vois_suivant=new_voisinage(vois_courant->ordre+1);
vois_courant->suivant=vois_suivant;
vois_courant=vois_suivant;
}
return 0;
}
int main(int argc, char **argv){
FILE *fp;
voisinage *vois;
if (argc!=1){
fprintf(stderr,"usage : %s filename\n",argv[0]);
return 1;
}
if( (fp=fopen(argv[1])==NULL){
fprintf(stderr,"Fichier %s invalide\n",argv[1]);
return 1;
}
vois=lire_fichier(fp);
del_chaine(vois);
return 0;
}
Bonne chance |
Salut,
int CreerFVoisinage(char *nom,voisinage *vsng)
{ int o,i;
voisinage *p;
FILE *f;
vsng=(voisinage *) malloc(sizeof(voisinage)); /* allocation d'une cellule voisinage */
vsng=NULL; /* mise à null du pointeur */
/* la cellule précédement alloué est perdue, elle est alloué mais on sait plus
où elle est */
Si dans le code d'entrée de ta fonction, la liste voisinage doit être vide, pas la peine de la passer en argument, ou alors comme argument de sortie. Mais avant de continuer sur ce point regardons de plus près le codage du passage d'arguement
/* en global */
voisinage vois;
/* la fonction */
int CreerFVoisinage(char *nom,voisinage *vsng)
{
}
/* la fonction main() */
int main(int argc,char **argv)
{
CreerFVoisinage("Fvsng.txt",&vois);
afficheVoisinage(&vois);
return 0;
}
La déclaration globale réserve dans l'espace de données de ton programme une cellule voisinage. L'appel dans ton main avec &vois, passe à la fonction l'adresse de cette cellule à la fonction (c'est valide vis à vis du compilateur). Le programme entre dans la fonction CreerFVoisinage, il met dans la variable vsng la copie de cette adresse (copie que tu modifie via un malloc qui sert à rien, puis une remise à null). La fonction revient dans le main() et là surprise l'adresse de 'vois' n'a pas changé, donc ta fonction affiche...() ne connait pas la valeur correcte qu'a pu élaborer Creer...(). Y a plusieurs solution pour résoudre ça, je te présente celle qui me semble la plus simple. Le prototype de la fonction Creer...() devient :
voisinage* CreerFVoisinage(char *nom)
{
voisinage* vsng = null ;
/* le reste de ton code, retourne null en cas d'erreur système à l'open */
....
/* à la fin tu retourne l'ancre de ta liste */
return vsng ;
}
Et là le code de ton main devient, après suppression de la déclaration de la variable globale vois
int main(int argc,char **argv)
{
voisinage* vois ;
vois = CreerFVoisinage("Fvsng.txt");
afficheVoisinage(vois);
/* ne pas oubllier de faire une fonction qui libère la mémoire allouée */
return 0;
}
Ca devrait être plus correct au niveau de la gestion de tes pointeurs et des fonctions. Je ne présume pas que le traitement soit OK. Sinon si tu veux absolument passer l'ancre de ta liste chainée en argument, il faut utiliser un pointeur sur un pointeur de voisinage (voisinage **pt dans le prototype de la fonction, voisinage*vois dans la déclaration pour le main, &vois lors de l'appel, et utiliser *vois dans la fonction). A+, bon courage, crabs ..., I think Slackware sounds better than 'Microsoft,' -- Patrick Volkerding - founder and maintainer of Slackware |