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 :

sscanf(): lire jusqu'à trouver un nombre puis lire ce nombre


Sujet :

C

  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut sscanf(): lire jusqu'à trouver un nombre puis lire ce nombre
    Bonjour,

    Tout est dans le titre ou presque. Avec fscanf(), je souhaite lire ma chaine jusqu'à rencontrer un chiffre puis lire le nombre correspondant. J'observe un comportement étonnant avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(tout, "%[^[0-9]]%d", &texte[0], &nombre);
    Si la chaine est correctement lue, le nombre ne l'est pas et je me vois obligé de faire un nouveau sscanf() pour pouvoir le lire.

    J'ai essayé plusieurs techniques, qui marchent. J'aimerais comprendre pourquoi la première technique dans le code suivant ne marche pas. Je trouve aussi bizarre que le formateur %n donne 0 avec cette technique.

    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
    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main(void)
    {
        const char *tout = "Du texte au debut puis un nomber a lire :42";
     
        char texte[1024] = {0};
        int nombre = 0;
        int nbConv = 0;
        int nbLus = 0;
     
        // Premiere technique
        nbConv = sscanf(tout, "%[^[0-9]]%n%d", &texte[0], &nbLus, &nombre);
        printf("Conv = %d\n", nbConv);
        printf("Texte : [%s]\n", texte);
        printf("Nombre : [%d]\n", nombre);
        nbConv = sscanf(tout + strlen(texte), "%d", &nombre);
        printf("Nombre relu : [%d]\n", nombre);
        printf("%d %d\n\n", strlen((texte)), nbLus);
     
        // Seconde technique
        puts("");
        nbLus = 0;
        nbConv = sscanf(tout, "%[^:] %*c %n %d", &texte[0],&nbLus,  &nombre); // %*c pour passer le double point
        printf("Conv = %d\n", nbConv);
        printf("Texte : [%s]\n", texte);
        printf("Nombre : [%d]\n", nombre);
        printf("%d %d\n\n", strlen((texte)), nbLus);
     
        // Troisieme technique
        puts("");
        nbLus = 0;
        nbConv = sscanf(tout, "%[a-zA-Z :]%n%d", &texte[0],&nbLus,  &nombre);
        printf("Conv = %d\n", nbConv);
        printf("Texte : [%s]\n", texte);
        printf("Nombre : [%d]\n", nombre);
        printf("%d %d\n\n", strlen((texte)), nbLus);
    }
    Sortie console :
    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
    Conv = 1
    Texte : [Du texte au debut puis un nomber a lire :]
    Nombre : [0]
    Nombre relu : [42]
    41 0
     
     
    Conv = 2
    Texte : [Du texte au debut puis un nomber a lire ]
    Nombre : [42]
    40 41
     
     
    Conv = 2
    Texte : [Du texte au debut puis un nomber a lire :]
    Nombre : [42]
    41 41
     
     
    Process returned 0 (0x0)   execution time : 0.012 s
    Press any key to continue.
    Merci d'avance

  2. #2
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Salut,

    Citation Envoyé par Bktero Voir le message
    J'observe un comportement étonnant avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(tout, "%[^[0-9]]%d", &texte[0], &nombre);
    Mauvais format.

    Le problème vient du fait que ton premier ] ferme l’ensemble des caractères :
    Citation Envoyé par man 3 sscanf
    To include a close bracket in the set, make it the first character after the open bracket or the circumflex; any other position will end the set.
    Du coup, le dernier ] est considéré comme un littéral ce qui fait échouer la lecture.
    En gros, ça donne :
    - "%[^[0-9]" va lire "Du texte au debut puis un nomber a lire :" ;
    - "]" ne matche pas, donc arrêt de la lecture => %n n’est pas évalué (il vaut donc 0) et %d non plus (le nombre n’est donc pas lu)

    Le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(tout, "%[^0-9]%d", &texte[0], &nombre);
    va bien lire le texte et nombre

    Édit : au passage, la coloration syntaxique de Vim met cela bien en évidence :

    On voit bien que la dernière ] est considérée comme un littéral et non pas comme un bout du spécificateur de format.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Mince je n'avais pas vu tes éditions ! Sacré historique de messages d'ailleurs

    Merci beaucoup pour ces superbes explications ! J'avais été eu ! Je crois que j'ai tenté de me la jouer façon expressions régulières pour grep, mais ça ne l'a pas fait. La coloration de vim le met en effet très bien en évidence, ce que CodeBlocks ne fait pas du tout.


  4. #4
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Sacré historique de messages d'ailleurs
    Oui, j’ai assez vite trouvé le problème, mais l’explication complète est venu au fur et à mesure ^^"

  5. #5
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    une autre méthode :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    p = strchr (chaine, ':');
    sscanf ( (p+1), "%d", &nombre);

    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lire une chaine jusqu'à trouver un entier
    Par cisco.nat dans le forum Langage
    Réponses: 2
    Dernier message: 17/07/2013, 13h17
  2. Sockets : Comment lire jusqu'à la fin ?
    Par devoluti0n dans le forum Langage
    Réponses: 10
    Dernier message: 28/09/2010, 16h27
  3. Réponses: 7
    Dernier message: 12/10/2007, 18h05
  4. Comment lire jusqu'au caractère CTRL-D EOF ?
    Par AsmCode dans le forum C
    Réponses: 9
    Dernier message: 08/02/2007, 21h27

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