IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Erreur de segmentation à la lecture d'un fichier et l'insertion dans une liste chainée


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut Erreur de segmentation à la lecture d'un fichier et l'insertion dans une liste chainée
    Bonjour, j'ai créé un programme qui a pour objectif de : lire dans un fichier ligne par ligne, puis extraire les mots de chacun de ces lignes, et enfin placer ces mots dans une liste. Tout marche, jusqu'à la rentrée dans une liste, où j'obtiens une segmentation fault, mais je vois pas d'où ça vient. Voilà le main.c et la définition de ma liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
     
    typedef struct elem {
    char* word;
    struct elem* next;
    } Element;
     
    typedef Element* List;
     
    int main(int argc,char* argv[])
    {
    	List l=NULL;
    	char str[200];
    	FILE *fp = fopen("./test.txt","r");
    	char* wrd; /*a array of caracters representing ONE word*/
     
       	if(!fp) return 1; /* bail out if file not found*/
     
        /*
        fgets function :
        
        La fonction fgets() prends comme premier paramètre la chaîne dans laquelle elle va placer la saisie. Le deuxième paramètre est le nombre maximal 
        de caractères (n-1 plus exactement) qui seront lus et le dernier paramètre est le flux à lire. Ici se sera stdin. (le flux est un fichier)
        */
     
    	while(fgets(str,sizeof(str),fp) != NULL)
    	{
    		/* strip trailing '\n' if it exists*/
    		int len = strlen(str)-1;
    		if(str[len] == '\n')
    		{ 
    	    	str[len] = 0;
    	    	}
     
    		/*
    		char * strtok ( char * str, const char * delimiters );
    		str :
    		C string to truncate.
    		Notice that the contents of this string are modified and broken into smaller strings (tokens).
    		Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
    		delimiters :
    		C string containing the delimiter characters.
    		These may vary from one call to another.
    		*/
     
      		printf ("Splitting string \"%s\" into words:\n",str);
    		wrd = strtok (str," ");
    		l = insertTail(l,wrd);
    		while (wrd != NULL)
    		{
    			printf ("word extracted : %s\n",wrd);
    			wrd = strtok(NULL," "); /* the second time we call the function, we have to put NULL into the second parameter*/
    			if(wrd != NULL)
    			{
    				l = insertTail(l,wrd);
    			}
    		}
     
    	}
    	printf("\n");
    	fclose(fp);
     
     
     
    	printList(l);
     
    	return EXIT_SUCCESS;
    }
    voici maintenant les fonctions printlist et inserttail :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    List insertTail(List l, char* p)
    {
    	List newel; 
    	List pl;
     
    	newel = (Element *) malloc(sizeof(Element));
    	newel->word = p;
    	newel->next = NULL;
     
    	if(l == NULL)
    	{
    		l = newel;
    	} else {
    		pl = l;
    		while(pl->next != NULL){
    			pl=pl->next;
    		}
    		pl->next=newel;
    	}
     
    	return l;
    }
     
    void printList(List l)
    {
    	if(l==NULL)
    	{
    		printf("Empty List\n");
    	}
    	else
    	{
    		Element* w = w;
    		while(w->next != NULL)
    		{
    			printf("%s",w->word);
    			w=w->next;
    		}
    		printf("%s\n",w->word);
    	}
    }
    Si vous pouviez m'aider ou m'indiquer comment trouver, ça m'aiderait beaucoup... Merci

  2. #2
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Bonjour,

    Je n'ai que regardé ton code en diagonal, mais je suppose que le problème vient d'une mauvaise utilisation de strtok (cf la man page). Le pointeur que tu insères dans ta liste sera modifié par les appels ultérieurs à fgets et strtok.
    Le plus simple pour le constater et confirmer mon intuition est d'utiliser ton débugueur favori ( printf manuels, gdb, ddd, celui de ton ide ...).

  3. #3
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    w mal initialisé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void printList(List l)
    {
    ...
    		Element* w = w;
    Par ailleurs, tu stockes les pointeurs sur des éléments de la chaine str. Mais cette chaine change à chaque tour de boucle. Tous les éléments de la liste vont pointer sur des éléments du dernier str lu. Les éléments de la liste doivent stocker les chaines elles-mêmes, pas des pointeurs.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup diogene, c'est ça qui pêchait effectivement. Maintenant, j'ai un autre problème, mes codes ont changé en :

    le main.c

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    main.c
     
    int main(int argc,char* argv[])
    {
    	List l=NULL;
    	char str[200];
    	FILE *fp = fopen("./test.txt","r");
    	char* wrd; /*a array of caracters representing ONE word*/
     
       	if(!fp) return 1; /* bail out if file not found*/
     
        /*
        fgets function :
        La fonction fgets() prends comme premier paramètre la chaîne dans laquelle elle va placer la saisie. Le deuxième paramètre est le nombre maximal 
        de caractères (n-1 plus exactement) qui seront lus et le dernier paramètre est le flux à lire. Ici se sera stdin. (le flux est un fichier)
        */
    	while(fgets(str,sizeof(str),fp) != NULL)
    	{
    		/* strip trailing '\n' if it exists*/
    		int len = strlen(str)-1;
    		if(str[len] == '\n')
    		{ 
    	    	str[len] = 0;
    	    }
     
    		/*
    		char * strtok ( char * str, const char * delimiters );
    		str :
    		C string to truncate.
    		Notice that the contents of this string are modified and broken into smaller strings (tokens).
    		Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
    		delimiters :
    		C string containing the delimiter characters.
    		These may vary from one call to another.
    		*/
     
      		printf ("Splitting string \"%s\" into words:\n",str);
     
    		wrd = strtok(str," ");
    		if(wrd != NULL)
    		{
    			l = insertTail(l,wrd);
    			printf("Extracted word : %s\n",wrd);
    		}
    		while(wrd != NULL)
    		{
    			wrd = strtok(NULL," ");
    			if(wrd != NULL)
    			{
    				l = insertTail(l,wrd);
    				printf("Ectracted word : %s\n",wrd);
     
    			}
     
     
     
    		}
     
    	}
    	printf("\n");
    	fclose(fp);
     
     
    	printf("Number of words in the list : %d\n",nbwords(l));
    	printList(l); /*le problème du programme ne vient pas de la printList, mais de l'insertion des mots, 
    	(de plus, la fonction insertTail fait bien son job) puisqu'il y a bien 8 mots (mais les mauvais)*/
     
    	return EXIT_SUCCESS;
    }
    printlist et insertTail :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    List insertTail(List l, char* p)
    {
    	List newel; 
    	List pl;
     
    	newel = (Element *) malloc(sizeof(Element));
    	newel->word = p;
    	newel->next = NULL;
     
    	if(l == NULL)
    	{
    		l = newel;
    	} else {
    		pl = l;
    		while(pl->next != NULL){
    			pl=pl->next;
    		}
    		pl->next=newel;
    	}
     
    	return l;
    }
     
     
    void printList(List l) /*bug in this function : every words are always the first of the last line, and the last word is the last of the last line*/
    {
     
    	printf("Visionnage de la chaine extraite :\n");
    	if(l==NULL)
    	{
    		printf("Empty List\n");
    	}
    	else
    	{
    		Element* w = l;
     
    		while(w->next != NULL)
    		{
    			printf("%s ",w->word);
    			w=w->next;
    		}
     
    		printf("%s\n",w->word);
    	}
    }
    "Et l'output est la suivante :
    Splitting string "pourquoi" into words:
    Extracted word : pourquoi
    Splitting string "il" into words:
    Extracted word : il
    Splitting string "veut" into words:
    Extracted word : veut
    Splitting string "pas" into words:
    Extracted word : pas
    Splitting string "commencer" into words:
    Extracted word : commencer
    Splitting string "par" into words:
    Extracted word : par
    Splitting string "le début" into words:
    Extracted word : le
    Ectracted word : début

    Number of words in the list : 8
    Visionnage de la chaine extraite :
    le le le le le le le début"

  5. #5
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    J'ai répondu, par anticipation, à cette question dans mon message précédent
    .... Tous les éléments de la liste vont pointer sur des éléments du dernier str lu. ...
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Le problème est que je n'arrive pas à visualiser le problème ni à trouver une solution../

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il faut stocker dans le maillon la chaine elle même et non pas un pointeur sur une chaine dont le contenu varie (str) au cours de l'exécution. Du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    newel =  malloc(sizeof(Element));
    if(newel != NULL)
    {
       newel->word = malloc(strlen(p)+1);
       if(newel->word != NULL) strcpy(newel->word,p);
       ....
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Ca fonctionne, merci beaucoup . J'ai compris le problème, et je pense que j'aurais pu résoudre le problème en utilisant fscanf au lieu de fgets.

Discussions similaires

  1. Segmentation fault dans une liste chainée
    Par lahlaly dans le forum C
    Réponses: 6
    Dernier message: 29/01/2013, 09h07
  2. liste récursive des fichiers d'un dossier dans une liste
    Par identifiant_bidon dans le forum Langage
    Réponses: 2
    Dernier message: 30/06/2010, 16h33
  3. nombre de fichiers de repertoires contenus dans une liste
    Par morty dans le forum Général Python
    Réponses: 3
    Dernier message: 12/06/2009, 01h46
  4. Réponses: 4
    Dernier message: 11/07/2007, 19h28
  5. Ouvrir fichier sur lien hypertexte dans une liste
    Par JimmyB dans le forum Access
    Réponses: 10
    Dernier message: 18/10/2006, 15h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo