En C, chaines de caractères dans un fichier

Fermé
r2 - 10 août 2011 à 18:49
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 17 août 2011 à 20:21
Bonjour,

J'aurais aimé créer un programme qui puisse savoir si le contenu d'un répertoire a changé et si oui, me donner le nom des fichiers. J'ai deux fichier rep et rep.old. En utilisant stdio.h je veux pouvoir enregistrer les noms de fichiers dans 2 tableaux (de pointeurs), un qui donne la liste de rep et l'autre de rep.old. Mon problème c'est que je n'arrive à rien avec fscanf, je débute en C et les pointeurs et les chaines de caractères c'est vraiment galère :( Quand j'essaye ca, ca m'affiche (null);

/* le fichiers sont déja ouverts*/
int cmp-rep ( ) {
char *liste[80], *liste_old[80];

fscanf ( fichier, "%s", liste[1] );
printf ("%s", liste[1] );
}

pour l'instant, je voudrais "prendre" seulement le premier nom qui apparait dans le fichier

j'aimerai savoir ce qui va pas, pourriez vous me proposer une fonction qui marcherait ?

Merci d'avance

PS : Les fichiers ont comme contenu :
fichier1
fichier2
fichier....
A voir également:

4 réponses

Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
10 août 2011 à 19:36
Bonjour,

Lorsque vous faites
char *liste[80]
ça créer un tableau de 80 pointeurs de type char, autrement dit :
liste[0] est un pointeur auquel il faut lui donné une adresse ! ( l'adresse d'un char ou d'un tableau de char [ou de tout type en fait, le type char* est aussi utilisé pour éviter de faire des calculs sur les adresses lorsqu'on utilise le type void* qui sert pour stocker les adresses de type différents] )

exemple :
#include <stdio.h>

int main(void)
  {
    char *s[2];
    char *a="hello world";
    char *b="bonjour tout le monde";
    s[0]=a;
    s[1]=b;
    printf("%s\n",s[0]);
    printf("%s\n",s[1]);
    return 0;
  }

Vous voyez s[0] récupère l'adresse de la chaîne "a" et s[1] celle de "b"

Pour lire un fichier utilisez fread avec une boucle,
exemple :
#include <stdio.h>

int main(void)
  {
    char buffer[10];
    size_t count,i;
    FILE *fichier;
    fichier = fopen("test.txt","r");
    if(fichier)
      {
        while((count=fread(buffer,sizeof(char),10,fichier))){
            for(i=0;i<count;i++)
                printf("%c",buffer[i]);
        }
      }
    fclose(fichier);
    return 0;
  }
1
Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
11 août 2011 à 20:51
Vrai qu'avec fread et un tableau de pointeur c'est pas super simple à mettre en place, je vous ai pondu la simplification pour récupérer chaque ligne dans un tableau :

#include <stdio.h>

#include <string.h>
#include <stdlib.h>
#include <assert.h>

#define SZBUF 4096 /* pour le buff utilisé dans fread */
#define SZLTMP 65536 /* pour le buff temporaire servant à stocker une ligne (taille max d'une ligne lu) */

typedef struct{
    char **tabptr; /* tableau qui stock les lignes */
    unsigned int n; /* nombre de lignes en stock */
}fline2tab;

void free_fline2tab(fline2tab *ft)
  {
    unsigned int i; for(i=0;i<ft->n;i++)
        free(ft->tabptr[i]);
    free(ft->tabptr);
    free(ft);
  }

fline2tab *get_file_lines(const char *path)
  {
    char buffer[SZBUF],
         *temp=NULL,
         **tabptrtmp;
    size_t count,i;
    int z=0;
    FILE *file;
    fline2tab *ft;

    file = fopen(path,"r");
    if(!file) return NULL;
    temp=malloc(sizeof(char)*(SZLTMP+1));
    if(!temp){ fclose(file); return NULL; }
    ft=malloc(sizeof(fline2tab));
    if(!ft){ fclose(file); free(temp); return NULL; }
    ft->tabptr=NULL;
    ft->n=0;

    while((count=fread(buffer,sizeof(char),SZBUF,file))){
        for(i=0;i<count;i++){
            if((z<SZLTMP) && buffer[i]!='\n' && buffer[i]!='\r'){
                temp[z]=buffer[i];
                z++;
            }
            if((buffer[i]=='\n' || (i==count-1 && count<SZBUF)) && z>0) {
                temp[z]='\0';
                tabptrtmp=realloc(ft->tabptr,sizeof(char*)*(ft->n+1));
                assert(tabptrtmp);
                ft->tabptr=tabptrtmp;
                ft->tabptr[ft->n]=malloc(sizeof(char)*(z+1));
                memcpy(ft->tabptr[ft->n],temp,z+1);
                ft->n+=1; z=0;
            }
        }
    }
    free(temp);
    fclose(file);
    return ft;
  }

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

void print_tab(char **tab,unsigned int n)
  {
    unsigned int i; for(i=0;i<n;i++)
        printf("%d - %s\n",i,tab[i]);
  }

int main(void)
  {
    fline2tab *ft;
    ft=get_file_lines("test.txt"); /* lit et stock chaque ligne du fichier dans ft */
    print_tab(ft->tabptr,ft->n); /* affichage */
    free_fline2tab(ft); /* libère la mémoire utilisé par ft */
    return EXIT_SUCCESS;
  }

il n'y a plus qu'à utiliser le type "fline2tab" pour stocker les lignes en utilisant la fonction get_file_lines puis de libérer la mémoire quand on en a plus besoin.. prend en charge les fichier texte avec sauts de ligne du type \r\n , \n\r et \n
0
J'ai essayé ce que tu m'as proposé, ca marche mais j'obtiens tout ce qui est dans le fichier dans une seule chaine de caractères, sauf que ce que je voudrais faire c'est enregistrer ma liste de noms dans un tableau (de pointeurs ?) selon un motif genre "%s" en employant fscanf.
0
J'ai essayé ce que tu m'as proposé, ca marche mais j'obtiens tout ce qui est dans le fichier dans une seule chaine de caractères, sauf que ce que je voudrais faire c'est enregistrer ma liste de noms dans un tableau (de pointeurs ?) selon un motif genre "%s" en employant fscanf.
0
ci dessous le programme que j'essaye de faire :

#define VRAI 0
#define T 128

FILE *fichier, *fichier_old;

int comp_file (void) {

char text[T];
char *liste[T], *liste_old[T];

int n= 0 , i, j;

printf ("Comparaison avec l'ancienne liste ... \n");

/* Mettre les noms dans le tableau liste */
while ( fscanf ( fichier, "%s", text ) != EOF )
{
liste[n] = text;
printf ( "%s\n", liste[n] ); // Test pour voir ce qu'il y a dans liste[n]
n ++;
}
i=n; //i indique le nombre d'elements dans liste

printf ( "Le repertoire de maintenant contient %d élements:\n", i );

/* Afficher les éléménts */

printf ("%s\n", liste[0] );
printf ("%s\n", liste[1] );

n=0; //réinitialise n

/* Mettre les noms dans le tableau liste_old */
while ( fscanf ( fichier_old, "%s", text) != EOF )
{ liste_old[n] = text; n++; }
j=n; // j indique le nombre d'elements dans liste_old

/* Afficher les élements */
printf ("Le répertoire d'avant contenait %d élements : \n", j );
for ( n=0; n<=j; n++ )
{ printf ("%s\n", liste_old[n] ); }


return (0);

}

Mon probleme c'est que la premiere boucle affiche la liste avec printf mais quand je veux "revoir" la liste, ca ecrit la derniere chaine de caractere du fichier :( J'aimerai savoir mon erreur svp.
0
Selon moi, plutôt que fread, tu devrais utiliser la fonction getline (qui te renvoie toute une ligne de ton fichier sous la forme de char *, à chaque appelle, ça te donne la ligne d'après)
Tu auras plus de facilité pour enregistrer chaque nom dans une case de ton tableau de pointeurs (et comme le nombre de lignes du fichier est inconnu, il faudra ré allouer ce tableau de pointeur à chaque fois, pour ça, je t'oriente vers la fonction realloc).

ça donnerait en gros un

int i = 0;  
while ((tab[i++] = getline(arguments)) != NULL)  
{  
   tab = realloc(taille actuelle + 1);  
} 


Réfère toi aux manuels pour la syntaxe exacte des arguments (que je n'ai plus en tête)

edit :
J'oubliais quelque chose d'important, pour la lecture d'un tableau il est généralement assez délicat d'utiliser une variable contenant la taille de ce tableau. Ici, le dernier appelle à getline mettra NULL à la derniere case de ton tableau, donc pour en lire le contenu, la boucle sera plus simple à reproduire n'importe ou dans le code sans devoir garder une variable qui garderait sa taille :

int i = 0;
while (tab[i] != NULL)
{
   printf("%s\n", tab[i++]);
}


J'espère ne pas m'être trompé dans ce que tu voulais faire ;)
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 17/08/2011 à 20:23
Pour info, getline() nest pas une fonction standard.
0
Dsl pour mon temps de réponse, les vacances...

Merci pour vos infos :) je vais pouvoir essayer de me débrouiller avec tout ça, dans mon coin j'avais réussi en utilisant aussi struct mais sans pointeur, ca m'a evité les erreurs de segmentation, mais les pointeurs ont l'air vraiment incontournable alors je vais y travailler de ce pas... encore merci ;)
0