Afficher un fichier

Fermé
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 - Modifié le 15 févr. 2021 à 19:18
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 - 2 mars 2021 à 15:22
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
A voir également:

3 réponses

[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 16 févr. 2021 à 16:19
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
1
wytekrow Messages postés 8 Date d'inscription lundi 30 novembre 2020 Statut Membre Dernière intervention 9 juillet 2021 2
15 févr. 2021 à 20:12
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 …
0
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 1
Modifié le 2 mars 2021 à 15:22
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é !
0