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 :

Léger soucis de fscanf


Sujet :

C

  1. #1
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Par défaut Léger soucis de fscanf
    Salut tout le monde !

    Voilà, je dispose d'un fichier contenant des commandes, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ls
    ls -a -i /dev/
    who
    J'aimerai pouvoir stocker dans un tableau à 2 dimensions sont contenus, ce qui donnerai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Tab[0][0] = "ls"
    Tab[1][0] = "ls" Tab[1][1] = "-a" Tab[1][2] = "-i" Tab[1][3] = "/dev"
    Tab[2][0] = "who"
    Pour cela j'ai commencé à codé cela :
    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
     
     
    typedef struct
    {
    	char nomCommande[COMMAND_LIMIT];
    	char option[50];
    	char parametre[PARAMETER_LIMIT];
    } Commande;
    .............................
     
    Commande *cmd;
    .............................
    	while (feof(fichier) == 0)
    	{
    		fscanf(fichier, "%s%s%s", cmd[i].nomCommande, cmd[i].option, cmd[i].parametre);
    		printf ("%s%s%s\n",cmd[i].nomCommande, cmd[i].option, cmd[i].parametre);
     
    		i++;
    	}
    Est-il possible de tester ce que l'on récupère du fscanf ? Car si on tombe sur un "ls" sans option et sans paramètre alors il prendra pour le cmd[i].option le cmd[i+1].nomCommande...

    D'avance un très grand merci et bonne semaine !!

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 200
    Par défaut
    commence par utiliser la fonction "fgets" pour isoler une ligne



    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
    #include "stdafx.h"
     
    #define COMMAND_LIMIT  20
    #define PARAMETER_LIMIT  20
    	typedef struct
    {
    	char nomCommande[COMMAND_LIMIT];
    	char option[50];
    	char parametre[PARAMETER_LIMIT];
    } Commande;
     
    	int _tmain(int argc, _TCHAR* argv[])
    {
    	Commande cmd [20]; // Pas de pointeur, il faut alouer la mémoire pour la structure
    	FILE* fichier=fopen("c:\\fichier.txt","r");
        int i=0 ;
    	while (feof(fichier) == 0)
    	{
     
    		char sTemp[PARAMETER_LIMIT+50+COMMAND_LIMIT+2]={'\0'} ;
    		fgets(sTemp, PARAMETER_LIMIT+50+COMMAND_LIMIT+2,fichier) ;
    		sscanf(sTemp, "%s %s %s\n", &cmd[i].nomCommande, &cmd[i].option, &cmd[i].parametre);
    		printf ("%s %s %s\n",cmd[i].nomCommande, cmd[i].option, cmd[i].parametre);
     
    		i++;
    	}
     
    	return 0;
    }

    Tout est dans l'ordre, mais il complète les chaînes par des caractaires spéciaux

  3. #3
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Par défaut
    Salut et merci pour la réponse !!

    En effet, y'a du mieux !! Mais c'est bizare cette histoire de caractère spéciaux, j'ai remarqué que ça le faisait que sur des petites lignes comme "ls" mais quand les lignes sont plus grandes du style "ls -i /proc" là ça marche nickel...

    Tu sais pas d'où sa peut venir ?

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Nico_stras
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #define COMMAND_LIMIT  20
    #define PARAMETER_LIMIT  20
    	typedef struct
    {
    	char nomCommande[COMMAND_LIMIT];
    	char option[50];
    	char parametre[PARAMETER_LIMIT];
    } Commande;
    <...>
    		sscanf(sTemp, "%s %s %s\n", &cmd[i].nomCommande, &cmd[i].option, &cmd[i].parametre);
    Tout est dans l'ordre, mais il complète les chaînes par des caractaires spéciaux
    Pas de & avec les tableaux...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
          sscanf(sTemp, "%s %s %s\n", cmd[i].nomCommande
                                    , cmd[i].option
                                    , cmd[i].parametre);
    Quand au \n final, je ne sais pas si c'est correct.

    Il serait particulièrement bien venu de contrôler le code retour (nombre de conversions réussies...)

    et #include "stdafx.h", c'est du pur Microsoft. Pas portable du tout... Mettre les headers nécessaires explicitement.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 200
    Par défaut
    Excuse pour le stdafx. J'ai testé le code sous Windows.

    Tout a fait juste aussi pour le '&'

    Par contre, le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(sTemp, "%s %s %s\n", &cmd[i].nomCommande, &cmd[i].option, &cmd[i].parametre);
    marche aussi. Pourquoi ?


    Autre écriture correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(sTemp, "%s %s %s\n", (cmd+i)->nomCommande, (cmd+i)->option, (cmd+i)->parametre);
    Le '\n' est inutile aussi

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Nico_stras
    Par contre, le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sscanf(sTemp, "%s %s %s\n", &cmd[i].nomCommande, &cmd[i].option, &cmd[i].parametre);
    marche aussi. Pourquoi ?
    Parce que l'adresse du tableau et l'adresse du premier élément du tableau sont confondues :

    http://emmanuel-delahaye.developpez.....htm#param_tab

    Mais c'est incorrect parce que le type est différent. Ton compilateur ne dit rien ?

    http://emmanuel-delahaye.developpez....tm#cfg_compilo

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 200
    Par défaut
    D'acord, c'est confondu, mais là, c'est l'adresse de l'adresse de donc de type char**

    Le compilo (VS 2005) ne dit rien. Mais je suis d'accord avec toi que ce n'est pas correct

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Nico_stras
    D'acord, c'est confondu, mais là, c'est l'adresse de l'adresse de donc de type char**
    Non. de type (char *) [TAILLE]
    Le compilo (VS 2005) ne dit rien. Mais je suis d'accord avec toi que ce n'est pas correct
    A ma connaissance, seul gcc en mode -Wall -Wextra voit ce genre de défaut avec printf...

    Par contre, ton compilateur devrait être sensible à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int main (void)
    {
       char s[10];
     
       char *pa = s;                /* OK */
       char *pb = &s;               /* incorrect */
       char (*pc)[10] = &s;         /* OK */
       char **pd = &s;              /* incorrect */
     
       return 0;
    }
    gcc :
    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
     
    Project   : Forums
    Compiler  : GNU GCC Compiler (called directly)
    Directory : C:\dev\forums2\
    --------------------------------------------------------------------------------
    Switching to target: default
    Compiling: main.c
    main.c: In function `main':
    main.c:6: warning: initialization from incompatible pointer type
    main.c:8: warning: initialization from incompatible pointer type
    main.c:5: warning: unused variable `pa'
    main.c:6: warning: unused variable `pb'
    main.c:7: warning: unused variable `pc'
    main.c:8: warning: unused variable `pd'
    Linking console executable: console.exe
    Process terminated with status 0 (0 minutes, 1 seconds)
    0 errors, 6 warnings

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Par défaut
    En effet, après les remarques apportées par Emmanuel cela marche fortement bien !! Donc un grand merci à vous deux !

    Par contre je m'intéroge sur un truc, pourquoi quand je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char cmd[200][200];
    sscanf(sTemp, "%s %s %s", cmd[i][0], cmd[i][1], cmd[i][2]);
    ça me rempli que des valeurs null, pourtant une case d'un tableau à 2 dimensions équivaut bien à une case d'un tableau de structure, non ?

  10. #10
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par soad029
    Par contre je m'intéroge sur un truc, pourquoi quand je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char cmd[200][200];
    sscanf(sTemp, "%s %s %s", cmd[i][0], cmd[i][1], cmd[i][2]);
    ça me rempli que des valeurs null, pourtant une case d'un tableau à 2 dimensions équivaut bien à une case d'un tableau de structure, non ?
    40000 char en mémoire auto, ça se fait pas...
    quick'n dirty :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       static char cmd[200][200];
       sscanf(sTemp, "%s %s %s", cmd[i][0], cmd[i][1], cmd[i][2]);
    Mais quel est le type de cmd[i][0] ? Tu trouves que ça ressemble à un char * ?

    Encore une fois, ce genre de chose est détectée par gcc, mais si tu as un doute, fait un essai 'en dur' comme je te l'ai déjà montré. On ne sera pas toujours là pour tout faire à ta place... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char s[3][10];
     
    char *p = s[1][2];
    ça devrait faire réagir ton compilateur...

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 200
    Par défaut
    Tu m'as devancé Manu ...

    Quel con Microsoft !!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(int argc, _TCHAR* argv[])
    {
    	int i=1 ;
    	char cmd[200][200];     // Tableau à 2 dimensions de CARACTERES
    	char* sTemp="kkjhu jjj gggg" ;
    	sscanf(sTemp, "%s %s %s", cmd[i][0], cmd[i][1], cmd[i][2]); 
    	return 0;
    }
    0 erreur, 0 Warning

    J'en déduis qu'il faut éviter Microsoft VS pour faire des programmes de base comme celui-ci !!!

    _________________________________________

    Je laisse soad029 trouver son erreur

  12. #12
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Nico_stras
    J'en déduis qu'il faut éviter Microsoft VS pour faire des programmes de base comme celui-ci !!!
    Bah, je te rassure, avec Borland, c'est pareil. C'est plutôt gcc qui est exceptionnel, en ce sens qu'il analyse les chaines de formatage de *printf() et de *scanf(), alors que ces fonctions font partie de la bibliothèque et non du noyau du langage (mais elles font quand même partie du langage).

  13. #13
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Nico_stras
    Tu connais un petit IDE léger avec GCC ?
    je sais ... Je ne suis pas au bon endroit pour demander ça
    Nous sommes très nombreux à utiliser Code::Blocks. C'est suffisamment léger pour mon portable (Celeron M80, RAM 256 Mo, XP...)

Discussions similaires

  1. Léger soucis de compilation: Makefile
    Par Marlan dans le forum Fortran
    Réponses: 1
    Dernier message: 14/06/2010, 15h16
  2. [Débutant] Léger soucis avec les Types
    Par Zooix dans le forum Haskell
    Réponses: 6
    Dernier message: 16/06/2009, 13h58
  3. quelques soucis de lecture de fichiers avec fscanf
    Par monsieurab dans le forum Bibliothèque standard
    Réponses: 2
    Dernier message: 05/11/2008, 14h28
  4. Réponses: 17
    Dernier message: 13/03/2007, 15h31
  5. léger soucis guillemet
    Par Quentinn06 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 19/01/2007, 10h09

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