Afficher un fichier

Signaler
Messages postés
146
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
4 mars 2021
-
Messages postés
146
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
4 mars 2021
-
Bonjour, j'essaie d'afficher ce fichier en prenant en compte des séparateurs qui sont les virgules et les guillemets:

"movieId","title","genres"
1,"Toy Story (1995)","Adventure|Animation|Children|Comedy|Fantasy"
2,"Jumanji (1995)","Adventure|Children|Fantasy"
3,"Grumpier Old Men (1995)","Comedy|Romance"
4,"Waiting to Exhale (1995)","Comedy|Drama|Romance"
5,"Father of the Bride Part II (1995)","Comedy"
6,"Heat (1995)","Action|Crime|Thriller"
7,"Sabrina (1995)","Comedy|Romance"
8,"Tom and Huck (1995)","Adventure|Children"
9,"Sudden Death (1995)","Action"
10,"GoldenEye (1995)","Action|Adventure|Thriller"


pour chaque ligne, lorsqu'on rencontre une virgule, j'aimerais aller à la ligne. J'ai donc obtenu le code suivant:

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

int main(){
    
    FILE * filePtr = fopen("test.csv", "r");
    (filePtr == NULL)? exit(-1) : printf("succes");
    
    char * piece;
    
    // for every line
    char chaine[1024] = "";    
    while(fgets(chaine, sizeof(chaine), filePtr)){
        
        // "movieId" part
        piece = strtok(chaine, ",\"");
        printf("%s\n",piece);

        // "title" part
        piece = strtok(NULL,"\",\""); 
        printf("%s\n", piece);

        // "genres" part
        piece = strtok(NULL,"\""); 
        printf("%s\n", piece);

        piece = strtok(NULL, "|");
        printf("%s\n", piece);        

        /* do{
            piece = strtok(NULL,"\"");
            printf("%s\n", piece);
        } while (piece = strtok(NULL, "\n")); */

              
    }

    fclose(filePtr);  

    printf("\n");
    return 0;
}

cependant, j'obtiens le résultat suivant:

succesmovieId
title
,
genres"

1
Toy Story (1995)
,
Adventure
2
Jumanji (1995)
,
Adventure
3
Grumpier Old Men (1995)
,
Comedy
4
Waiting to Exhale (1995)
,
Comedy
5
Father of the Bride Part II (1995)
,
Comedy"

6
Heat (1995)
,
Action
7
Sabrina (1995)
,
Comedy
8
Tom and Huck (1995)
,
Adventure
9
Sudden Death (1995)
,
Action"

10
GoldenEye (1995)
,
Action

Erreur de segmentation (core dumped)

pourquoi est-ce que ça n'affiche pas chaque partie (movieId, title, genres) correctement ?

Configuration: Linux / Chrome 88.0.4324.150

3 réponses

Messages postés
5478
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
3 mars 2021
928
Salut charline159,

En fait, tu veux travailler sur deux niveaux : tu délimites ta chaîne selon les virgules, pour chaque sous chaîne que tu trouves, tu veux la délimiter selon les (éventuels) guillemets.

Dans un tel cas, tu peux utiliser la version réentrante
strtok_r()
(c'est du POSIX, mais c'est implémenté dans les versions récentes de MinGW) si tu as la possibilité de l'utiliser.

http://manpagesfr.free.fr/man/man3/strtok.3.html

#include <stdio.h>
#include <string.h>

int main(void) {
    char chaine[1024] = "2,\"Jumanji (1995)\",\"Adventure|Children|Fantasy\"";
    char * niveau1;
    char * p1;
    char * niveau2;
    char * p2;

    for (niveau1 = strtok_r(chaine, ",", &p1);
            niveau1 != NULL;
            niveau1 = strtok_r(NULL, ",", &p1)) {
        for (niveau2 = strtok_r(niveau1, "\",", &p2);
                niveau2 != NULL;
                niveau2 = strtok_r(NULL, "\",", &p2))
            printf("%s\n", niveau2);
    }

    return 0;
}


donne :

$ gcc -Wall 37094952.c
$ ./a.out
2
Jumanji (1995)
Adventure|Children|Fantasy


Sinon, ton cas étant assez simple, tu peux faire cela sur un seul niveau, en séparant par virgules seulement avec
strtok()
et en regardant si le premier et le dernier caractère de la chaîne est un guillemet et si c'est le cas en incrémentant le pointeur de départ de la chaîne et en écrasant le guillemet de fin avec
'\0'
....

Note que tout ceci fonctionne avec
strtok()
ou
strtok_r()
avec ton jeu de données car tu n'as pas de virgules à l'intérieur du texte entre guillemets. Si c'est un cas qui peut se produire, tu devrais opérer différemment.

Dal
Messages postés
5
Date d'inscription
lundi 30 novembre 2020
Statut
Membre
Dernière intervention
15 février 2021
1
strtok considère une suite de séparateurs comme un seul séparateur. Donc en gros, la séquence
","
est considérée comme un seul séparateur si tu donnes comme liste de séparateurs
,"
.

Les séparateurs du second strtok contiennent un " de trop. Le troisième strtok n'a pas la virgule comme séparateur dans la liste du coup , est considéré comme un champ …
Messages postés
146
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
4 mars 2021
1
Salut Dal et merci pour ta réponse. Désolée de ne pas avoir répondu plus tôt (je tourne sur plusieurs projets et langages, selon le jour ou la semaine...)!

Merci pour ton aide, je vais essayer de tester strtok() de mon côté !