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 :

fscanf , sscanf ? votre aide souhaitée


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Mars 2020
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : Mars 2020
    Messages : 62
    Par défaut fscanf , sscanf ? votre aide souhaitée
    bonjour,

    Je tente désespérément de lire un fichier texte dont les champs sont séparés par ':'.
    Le 2eme champs est variable et comporte un ou plusieurs espaces.

    Voici mon code et le format du fichier, pouvez vous m'aider ? D'avance merci.

    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
     
    #include <stdio.h>
    #include <string.h>
     
    /*file format
    nom1:PATRICK DUCHMOL:S:2:4:3:30:0
    nom2:HERVE DUCHMOL DE LA POTEE::1:9:6:20:9
    */
    int main()
    {
    FILE * fd  = NULL ;
    char flag [5];
    char nom[50];
    char s[2] ;
    int st1 ;
    int st2 ;
    int st3 ;
    int po ;
    int ti ;
     
    if((fd=fopen("./file.txt", "r"))==NULL) {
    printf("Error\n") ;
    }
     
    while(!feof(fd)) {
     
    if(fscanf(fd, "%s:%[^:]:%s:%d:%d:%d:%d:%d", flag, nom, s, &st1, &st2, &st3, &po, &ti) != 8)
    printf("%s\n", nom) ;
    else
    fprintf(stderr, "Format error.\n") ;
    }
     
    fclose(fd) ;
     
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 604
    Par défaut
    Bonjour,

    %s s'arrête sur les caractères espaces pas sur un :, il faut plutôt le format "%[^:]:%[^:]:%[^:]:%d:%d:%d:%d:%d ", l'espace à la fin permet de retirer des CR/LF.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    À ceci près que la seconde ligne du fichier présenté contient un set vide :
    nom2:HERVE DUCHMOL DE LA POTEE::1:9:6:20:9
    qui est refusé par le format %[^:].
    J'ai bien peur qu'il faille gérer cela de façon plus manuelle.

    Au passage, le test du retour de fscanf() devrait être == 8 et non != 8. Soit égal aux nombre de champs lus avec succès.
    Un test qui devrait être déplacé dans le while (...), sinon tu vas systématiquement afficher ton erreur « Format error. » en atteignant la fin. feof() a un autre but que de détecter la fin du fichier.

  4. #4
    Membre confirmé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Mars 2020
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : Mars 2020
    Messages : 62
    Par défaut
    Merci pour vos réponses. En effet le champ vide entre 2 : ne donne rien à l'affichage.
    C la que l'on se dit que cut, sed, awk et tr sont des outils puissants....

  5. #5
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 842
    Par défaut
    Citation Envoyé par netlink1987 Voir le message
    Merci pour vos réponses. En effet le champ vide entre 2 : ne donne rien à l'affichage.
    il faut tester fgets + strtok (<- 2 liens cplusplus.com en anglais)

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par netlink1987 Voir le message
    Voici mon code et le format du fichier, pouvez vous m'aider ? D'avance merci.
    Alors déjà tester si le fichier n'a pas été ouvert c'est bien mais dans ce cas il ne faut pas le lire.
    Ensuite on ne boucle pas sur while (!feof()). La fonction feof() n'est pas là pour t'indiquer la fin de fichier mais pour t'indiquer, une fois que tu ne peux plus lire le fichier, si l'interruption de lecture est due à une fin atteinte ou autre chose. Et ce n'est pas la même chose. Quand tu lis le dernier octet du fichier, feof() n'est pas encore actif, il ne le sera qu'à la lecture suivante. Ainsi boucler sur while (!feof()) amène à faire un traitement de plus. Sauf si tu testes la lecture réussie ou pas mais dans ce cas, autant boucler directement sur la lecture elle-même.

    Citation Envoyé par foetus Voir le message
    strtok
    Je conseillerais plutôt strtok_r. Ok ici ça n'a pas d'importance mais autant prendre les bonnes habitudes.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 842
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Je conseillerais plutôt strtok_r. Ok ici ça n'a pas d'importance mais autant prendre les bonnes habitudes.
    Cela ne fonctionne pas non plus

    De ce qui précède, il découle qu'une séquence de deux séparateurs contigus ou plus est considérée comme un seul séparateur et que les séparateurs en début et en fin de chaîne sont ignorés.
    Il mange les séparateurs contigus ... et donc walou les champs vides

    Il faut faire 1 parser personnalisé, mais la gestion des séparateurs + des fins de ligne (avec des choix comme est-ce qu'1 champs peut-être sur plusieurs ligne ou pas ) + de la fin de fichier + de la longueur des champs c'est 1 peu l'enfer

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    Cela ne fonctionne pas non plus


    Il mange les séparateurs contigus ... et donc walou les champs vides
    C'est exact, j'ai eu le souci il n'y a pas longtemps (et comme je ne savais pas qu'elle ne sait pas gérer les vides, j'ai mis du temps à comprendre ce qui se passait). Mais je n'ai pas proposé strtok_r pour gérer les champs vides, je l'ai proposée comme fonction préférentielle face à strtok. Car contrairement à cette dernière, elle sait gérer la réentrance grâce à son pointeur de travail configuré par l'appelant. Bref là où strtok() fonctionne, strtok_r() fonctionne au-moins pareil mais offre plus de robustesse.

    Pour gérer les champs vides, strsep() sait faire.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 604
    Par défaut
    Si un seul des 3 mots peut être vide. On peut juste envisager ce cas pour ne pas se compliquer la vie.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    for (;;) {
       char  buffer[200];
       if ( !fgets( buffer, 200, fd ) )
          break;
       *s = '\0;
       if (   sscanf( buffer, "%4[^:]:%49[^:]::%d:%d:%d:%d:%d", flag, nom, &st1, &st2, &st3, &po, &ti ) == 7
           || sscanf( buffer, "%4[^:]:%49[^:]:%1[^:]:%d:%d:%d:%d:%d", flag, nom, s, &st1, &st2, &st3, &po, &ti ) == 8 )
          puts( nom );
       else
          fprintf( stderr, "Format error.\n" );
    }

Discussions similaires

  1. traitement sur une chaîne, votre aide souhaitée !
    Par netlink1987 dans le forum Débuter
    Réponses: 11
    Dernier message: 16/03/2020, 16h20

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