Fonction fscanf en langage C

Discutez d'informatique ici !
MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

Fonction fscanf en langage C

par MacErmite » 11 Déc 2010, 00:40

Bonsoir,

Je ne parviens pas à résoudre ce problème, pouvez-vous m'aider ?

J'ai crée un fichier texte avec notpad :

"73.962000 18.550000 DBC1
-114.427000 0.776000 air
-99.163000 5.300000 EDF3
660.831000 59.678000 air
55.173000 15.900000 DBC1
-228.329000 19.769000 air
-44.891000 2.650000 EDF1 "

Je cherche à charger ces valeurs dans des variables

Code: Tout sélectionner
double rayon[8],epaisseur[8];
    int matiere[8];
    for (i=0; i<8; i++)
    {
        rayon[i]=0;
        epaisseur[i]=0;
        matiere[i]="";

    }

    monFichier = fopen("systeme.txt", "r");
    if(monFichier!=NULL)
    {

        fscanf(monFichier, "%lf ", &rayon[0]);
        fscanf(monFichier, "%lf ", &epaisseur[0]);
        fscanf(monFichier, "%s ", &matiere[0]);

        printf("... %lf \t %lf \t %s \n",rayon[0],epaisseur[0],matiere[0]);
        fclose(monFichier);

    }


j'ai alors sur la fenetre "console" l'afffichage de rayon : 73.962000 et epaisseur: 18.550000 mais cela m'ejecte lorsque je veux afficher matiere.

si je remplace printf("... %lf \t %lf \t %s \n",rayon[0],epaisseur[0],matiere[0]); par printf("... %lf \t %lf \t %c \n",rayon[0],epaisseur[0],matiere[0]); cela m'affiche uniquement le premiere lettre D. Cela semble normale. Mais pourquoi cela ne marche pas avec une chaine de caracteres ??


Je ne comprends pas pourquoi ....

Merci



Avatar de l’utilisateur
Olympus
Membre Irrationnel
Messages: 1668
Enregistré le: 12 Mai 2009, 12:00

par Olympus » 11 Déc 2010, 00:50

Salut !

Je crois que tu confonds les types "char" ( caractère ) et "string" ( chaîne de caractères ) .

Ton "matiere", c'est censé être un tableau de chars ( donc une chaîne de caractères, et c'est correct alors au début ), ou bien un tableau de strings ( donc un tableau de deux dimensions de chars ) ?

MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

par MacErmite » 11 Déc 2010, 01:14

j'aimerais que matiere[0]=DBC1 , matiere[1]=air ... mais je ne sais pa comment faire ...

Avatar de l’utilisateur
Olympus
Membre Irrationnel
Messages: 1668
Enregistré le: 12 Mai 2009, 12:00

par Olympus » 11 Déc 2010, 01:25

MacErmite a écrit:j'aimerais que matiere[0]=DBC1 , matiere[1]=air ... mais je ne sais pa comment faire ...


Tu sais comment est constituée une chaîne de caractères ? C'est un tableau de caractères ( ou de int non signés ) . En fait, tab[0]='a'; tab[1]='b'; tab[2]='c' est la même chose que tab="abc" .

Tu veux que matiere[1]="air", mais ça revient à dire que matiere[1][0]='a'; matiere[1][1]='i'; matiere[1][2]='r'; .

En gros, remplace "int matiere[8];" par "int matiere[8][longueur_max_de_ta_chaine];" .

Comme ça, matiere[i] sera une chaine de caractère, et matiere[i][j] un caractère de cette chaîne .

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 11 Déc 2010, 02:30

salut,

pourquoi int matiere[8]
la vie est une fête :)

Avatar de l’utilisateur
Olympus
Membre Irrationnel
Messages: 1668
Enregistré le: 12 Mai 2009, 12:00

par Olympus » 11 Déc 2010, 10:16

Salut !

Parce que le int et le char sont la même chose au final ?

Avatar de l’utilisateur
Ben314
Le Ben
Messages: 21534
Enregistré le: 11 Nov 2009, 22:53

par Ben314 » 11 Déc 2010, 10:36

Olympus a écrit:Salut !

Parce que le int et le char sont la même chose au final ?
Je suis pas du tout certain que "ça passe" sur tout les compilateurs :
En général le char est un simple octet (non signé) alors que le int est un mot de 16 ou 32 bits (signé) et je suis pas du tout sûr que le transtypage se fasse automatiquement dans un cas comme celui là où le %s spécifie une chaine charactère donc à priori un tableau d'octets.
Qui n'entend qu'un son n'entend qu'une sonnerie. Signé : Sonfucius

Avatar de l’utilisateur
Olympus
Membre Irrationnel
Messages: 1668
Enregistré le: 12 Mai 2009, 12:00

par Olympus » 11 Déc 2010, 11:22

J'ai le droit d'aller me coucher alors, ça fait longtemps que j'ai plus touché au C :briques:

MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

par MacErmite » 11 Déc 2010, 21:55

J'ai essayé avec :

Code: Tout sélectionner
 double rayon[8],epaisseur[8];
    int matiere[8][10];
    for (i=0; i<8; i++)
    {
        rayon[i]=0;
        epaisseur[i]=0;
       // matiere[i][]="";
    }

    monFichier = fopen("systeme.txt", "r");
    if(monFichier!=NULL)
    {

        fscanf(monFichier, "%lf ", &rayon[0]);
        fscanf(monFichier, "%lf ", &epaisseur[0]);
        fscanf(monFichier, "%s ", &matiere[3][10]);

        printf("... %lf \t %lf \t %s \n",rayon[0],epaisseur[0],matiere[3][10]);
        fclose(monFichier);

    }


Mais cela plante la compilation. Je suis vraiement bloqué :mur:

Avatar de l’utilisateur
Olympus
Membre Irrationnel
Messages: 1668
Enregistré le: 12 Mai 2009, 12:00

par Olympus » 11 Déc 2010, 22:11

Salut !

Je suis bien curieux de savoir comment tu t'inities au C ... tu as sûrement brûlé plusieurs étapes ( pointeurs, types de variables, tableaux etc... ) .

Voici le code qui marche :

Code: Tout sélectionner
 #include "stdio.h"

int main(void){
    double rayon[8],epaisseur[8];
    char matiere[8][10]; // ca marche aussi avec un int, mais comme Ben l'a dit, leurs tailles sont differentes, et t'as droit a un warning de la part de GCC
    int i;
    FILE *monFichier; // t'as oublier ça je crois
    for (i=0; i<8; i++)
    {
        rayon[i]=0;
        epaisseur[i]=0;
        matiere[i][0]=0; // inutile de vider tous les caractères de chaque chaine, il suffit de mettre un 0 comme premier caractere
    }

    monFichier = fopen("systeme.txt", "r");
    if(monFichier!=NULL)
    {

        fscanf(monFichier, "%lf ", &rayon[0]);
        fscanf(monFichier, "%lf ", &epaisseur[0]);
        fscanf(monFichier, "%s ", &matiere[3][0]); // c'est un pointeur qu'il faut donner a fscanf

        printf("... %lf \t %lf \t %s \n",rayon[0],epaisseur[0],matiere[3]); // idem, c'est un pointeur qu'il faut a printf, et non un caractère
        fclose(monFichier);

    }
   return(0);
}


Et voici ce que me retourne le terminal :

Code: Tout sélectionner
bouazza@bouazza-laptop:~$ gcc test.c
bouazza@bouazza-laptop:~$ ./a.out
... 73.962000     18.550000     DBC1
bouazza@bouazza-laptop:~$


PS : même si je ne sais pas pourquoi t'as mis exactement matiere[3] et non matiere[0], mais bon ça ne change rien ici .

EDIT : j'ai mis des commentaires dans le code .

MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

par MacErmite » 12 Déc 2010, 10:40

Merci pour ton aide.

Je n'ai pas tous copier sur mon post, mais j'ai bien crée un pointeur de type File avant d'ouvrir le fichier :lol3:

Je vais travailler ce que tu proposes.

Merci

MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

par MacErmite » 12 Déc 2010, 10:54

J'ai un problème. La chaine de caractere ne change pas si j'écris matiere[0] ou matiere[3] ...

MacErmite
Membre Relatif
Messages: 408
Enregistré le: 12 Mai 2006, 13:00

par MacErmite » 12 Déc 2010, 11:01

Oublier mon précédent post, j'ai enfin compris comment gérer tout cela... :doh:

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 12 Déc 2010, 11:26

salut,

simplifions l'exercice
Code: Tout sélectionner
  char matiere[3][10];//tableau de trois chaines de dix caracteres
  FILE *monFichier;//monFichier contient : prout voiture78 voiture789
  monFichier = fopen(DATA_FILE, "r");
  if(monFichier!=NULL)
  {
    /*
     * matiere[0] est une adresse qui pointe vers notre tableau de dix caracteres
     * Par exemple matiere[0][0] est le premier element, matiere[0][1] le second...etc
     */
    fscanf(monFichier, "%s ", matiere[0]);
    printf("%s \n", matiere[0]);//affiche prout

    fscanf(monFichier, "%s ", matiere[1]);
    printf("%s \n", matiere[1]);//affiche voiture78

    //segfault, matiere[2] est trop petite(voiture789 contient exactement 10 caracteres)
    //! on a oublié le caractere fin de chaine'\0'
    fscanf(monFichier, "%s ", matiere[2]);
    printf("%s \n", matiere[2]);
  }
  fclose(monFichier);
la vie est une fête :)

Sve@r
Membre Transcendant
Messages: 5441
Enregistré le: 13 Avr 2008, 12:00

par Sve@r » 13 Déc 2010, 01:11

Ben314 a écrit:Je suis pas du tout certain que "ça passe" sur tout les compilateurs :
En général le char est un simple octet (non signé) alors que le int est un mot de 16 ou 32 bits (signé) et je suis pas du tout sûr que le transtypage se fasse automatiquement dans un cas comme celui là où le %s spécifie une chaine charactère donc à priori un tableau d'octets.

Du vrai et du faux dans ce que tu dis.

Déjà, en C, tout est nombre. Un char est un nombre signé sur un octet. T'as le droit de le préfixer par le mot clef "unsigned" pour le rendre non signé.
Un int est un nombre signé sur au-moins 2 octets (dans 99% des cas ils en font 2 mais j'ai vu une fois un système de m... où les int faisaient 4 et les long en faisaient 6). Là aussi t'as le droit de le préfixer par unsigned.

Si tu fais intervenir en même temps des int et des char, l'opération est possible et se fera dans le type le plus large des opérandes en cours. Attention, petit danger où je me suis fait avoir, c'est seulement le type des opérandes en cours et non le type le plus large de tous les opérandes présents.
Exemple: 2.0 + 1 / 3
Il y a dans cette opération un float (représenté par le ".0") et 2 int. On peut penser que l'opération se fera en flottant et donnera 2.0 + 0.666 = 2.666.
Malheureusement, la division ne faisant intervenir que des int se fera en int et donnera 0. Puis l'addition convertira ce 0 en flottant et donnera 2.0.

Ensuite la copie char dans int est possible (expansion dans le second octet avec transmission du bit de signe si on est en signé) et int dans un char est aussi possible (mais troncature de ce qui dépasse).

Bref on peut à loisir mélanger int, char, long, double, float sans problème. Là où ca devient difficile, c'est quand on manipule des tableaux. Là c'est plus pareil car en C on ne sait pas manipuler un tableau. On ne sait que manipuler l'adresse de son premier élément puis décaler cette adresse de X positions (le décalage interne étant alors égal à X * taille d'un élément). Et donc un tableau de char ne peut pas être manipulé comme un tableau de float (sans conversion préalable). Et une chaine n'étant qu'un tableau de char, ne peut pas devenir (du moins automatiquement) un tableau d'int...

miara chipuden
Messages: 3
Enregistré le: 14 Oct 2012, 14:50

aidez moi

par miara chipuden » 14 Oct 2012, 15:26

salut,
j'ai défini un automate finis déterministe dans un fichier sous le format suivant:
3 //nbre des etats.
ab //symboles.
0 //état initial
1 //nbre des états finaux.
2 //l'éetat final.
6 //nbre de transition
0 b 0 //les chemins possibles
0 a 1
1 a 1
1 b 2
2 a 2
2 b 2 //
la représentation en mémoire de l'automate d'un afd est:
typedef struct transition
{ int etat_dep;
char sym;
int etat_arr;
}trans ;

typedef struct autom
{ int nb_etats;
char alphabet[256];
int etat_init;
int nb_etats_fin;
int * etats_fin;
int nb_trans;
trans * lst_trans;
}afd ;
je veux définir une fonction afd read(char * nameFile) qui ouvre le fichier texte représentant un afd(automate finis déterministe)et retourne la structure qui l'implémente en mémoire.
l'ouverture du fichier est simple mais j'ai trouvé le probleme dans l'utilisation de la fonction "fscanf".par exemple je veux afficher la 7ème ligne du fichier ci-dessus avec fscanf il m'ffiche uniquement le premier caractère de la ligne.pouvez-vous m'aider à résoudre ce probleme?et merci bcp pour votre attention

:triste:

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 14 Oct 2012, 15:49

Bonjour,
La fonction fscanf génère des invraisemblance s'il y a des erreurs.
Il est généralement vivement conseillé de lire des données avec des fonctions du genre fget() et ensuite d'utiliser sscanf.
Personnellement, je n'ai jamais utilisé fscanf.

miara chipuden
Messages: 3
Enregistré le: 14 Oct 2012, 14:50

par miara chipuden » 14 Oct 2012, 16:22

Dlzlogic a écrit:Bonjour,
La fonction fscanf génère des invraisemblance s'il y a des erreurs.
Il est généralement vivement conseillé de lire des données avec des fonctions du genre fget() et ensuite d'utiliser sscanf.
Personnellement, je n'ai jamais utilisé fscanf.

on n'a pas etudié sscanf() mais comme meme je vous remercie pour la réponse

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 14 Oct 2012, 16:35

miara chipuden a écrit:on n'a pas etudié sscanf() mais comme meme je vous remercie pour la réponse

Bon, alors montrez moi votre appel de fscanf, et le pourrai peut-être vous aider.
Ce que je ne comprends pas c'est que vous parliez de read(...), disons, en gros, c'est l'un ou l'autre.

miara chipuden
Messages: 3
Enregistré le: 14 Oct 2012, 14:50

par miara chipuden » 14 Oct 2012, 16:59

Dlzlogic a écrit:Bonjour,
La fonction fscanf génère des invraisemblance s'il y a des erreurs.
Il est généralement vivement conseillé de lire des données avec des fonctions du genre fget() et ensuite d'utiliser sscanf.
Personnellement, je n'ai jamais utilisé fscanf.

la fonction read est juste défini pour ouvrir le fichier contenant l'automate et récuperer ses valeurs comme m.nb_etats,m.alphabet....aprés la déclaration du fichier fp(FILE *fp) et l'automatem(afd m),j'ai lu la première ligne par fscanf sous la forme suivante:fscan(fp,"%d",&m.nb_etats).si je fait l'affichage de m.nb_etats je vais avoir la valeur 3.mais l'utilisation de cette fonction dans la 7ème ligne(fscanf(fp,"%d",m.lst_trans.etat_dep))va m'afficher uniquement la valeur 0 à la place de 0 b 0

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 8 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite