Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
772 connectés 

  FORUM HardWare.fr
  Programmation
  C

  sscanf et lecture de réel

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

sscanf et lecture de réel

n°1415418
ThibB
Posté le 28-07-2006 à 16:40:37  profilanswer
 

Bonjour tous le monde !
 
Je rencontre un problème lorsque je cherche à lire des réels depuis un buffer : impossible de faire fonctionner le sscanf ... encore ...
Je lis en fait une ligne de 250 caractères dont les caractère 159 à 165 represente un litrage en mL, dans mon exemple : 1023800 (autre ex : 0048600)
Voila plusieurs bouts de code pour comprendre le problème :
 
s->data[i].volumeCarbu --> float
tmp --> int

---------------------
 

Code :
  1. for (k=158; k < 165; k++)
  2.                            buffer[k-158] = ligne[k];
  3.                        buffer[k-158] = '\0';
  4.                        if (1 != sscanf(buffer,"%f",&s->data[i].volumeCarbu))
  5.                           return 0;
  6.                        s->data[i].volumeCarbu /= 1000.0f;


Résultat :
Un nombre qui n'a rien a voir du type : 1218173.0
---------------------
 

Code :
  1. for (k=158; k < 165; k++)
  2.                            buffer[k-158] = ligne[k];
  3.                        buffer[k-158] = '\0';
  4.                        if (1 != sscanf(buffer,"%d",&tmp))
  5.                           return 0;
  6.                        s->data[i].volumeCarbu = tmp/1000.0f;


Résultat :
Le bon nombre mais sans les décimales (tronqué) : 1023.0
 
 
--> Impossible d'avoir le bon résultat : 1023.8
 
 
Est ce que quelqu'un aurait une solution ?
Merci d'avance ;) !

Message cité 1 fois
Message édité par ThibB le 28-07-2006 à 16:57:54

---------------
Visiter mon site
mood
Publicité
Posté le 28-07-2006 à 16:40:37  profilanswer
 

n°1415427
Aldarek
Posté le 28-07-2006 à 16:47:58  profilanswer
 

C'est bien un float ton nombre?

n°1415431
_darkalt3_
Proctopathe
Posté le 28-07-2006 à 16:51:23  profilanswer
 

pourquoi %d dans le second morceau de code ?


---------------
Töp of the plöp
n°1415433
ThibB
Posté le 28-07-2006 à 16:53:57  profilanswer
 

Oui autant pour moi j'ai pas mis les type de variable :

s->data[i].volumeCarbu --> float
tmp --> int

 
L'idée de tmp c'est de récupérer la valeur dans un entier (à la base c'est une valeur entière), mais une fois divisé par 1000 elle devient décimal, d'ou le float.


Message édité par ThibB le 28-07-2006 à 16:54:42

---------------
Visiter mon site
n°1415464
Trap D
Posté le 28-07-2006 à 17:13:36  profilanswer
 

Si c'est pour faire un sscanf(buffer,"%f",&s->data[i].volumeCarbu)), autant faire un strtod(buffer, NULL); ce sera plus sûr.  
(les Xscanf sont trèèèèèèès difficiles à utiliser).

n°1415471
_darkalt3_
Proctopathe
Posté le 28-07-2006 à 17:19:11  profilanswer
 

ou atof, mais c'est moins bien (juste pour rajouter une solution)


---------------
Töp of the plöp
n°1415474
ThibB
Posté le 28-07-2006 à 17:21:09  profilanswer
 

Je n'avais pas pensé à utliser cette fonction mais malheureusement ca ne passe pas :(
 
J'ai mis :

Code :
  1. s->data[i].volumeCarbu = (float)strtod(buffer, NULL);


Et j'obtien :
-2147483648,c


---------------
Visiter mon site
n°1415479
ThibB
Posté le 28-07-2006 à 17:22:46  profilanswer
 

Même résultat avec atof :(


---------------
Visiter mon site
n°1415494
Elmoricq
Modérateur
Posté le 28-07-2006 à 17:35:15  profilanswer
 

Mets errno à 0, avant le strtod(), et regarde sa valeur après.

n°1415499
tisouytni
Posté le 28-07-2006 à 17:38:27  profilanswer
 

Et avec un "long double"?

Code :
  1. long double f=0;
  2. char s[100]="123456789.123";
  3. sscanf(s,"%Lf",&f);
  4. fprintf(stdout,"%Lf\n",f);

mood
Publicité
Posté le 28-07-2006 à 17:38:27  profilanswer
 

n°1415512
ThibB
Posté le 28-07-2006 à 18:07:02  profilanswer
 

Pour errno elle vaut toujours 0 après le strtod() :s
Et le long double ne résoud pas le problème non plus ...
 
En tout cas merci de me donner vos idées ;)


---------------
Visiter mon site
n°1415515
ThibB
Posté le 28-07-2006 à 18:14:52  profilanswer
 

Est que quelqu'un aurait une idée de la cause du problème dans le second bout de code ?
J'ai utilisé le debugger pour voir ce qu'il se passait dans ce cas la : tmp prend bien la bonne valeur (qui est donc un entier), mais c'est l'opération suivante (s->data[i].volumeCarbu = tmp/1000.0f;) qui donne un résultat entier ...


---------------
Visiter mon site
n°1415566
Trap D
Posté le 28-07-2006 à 20:22:14  profilanswer
 

eh bien essaye s->data[i].volumeCarbu = ((float)tmp)/1000.0f
ce serait d'ailleur, sans doute meilleur avec double.
Pour information, les fonctions atoX ne sont plus utilisables depuis 1989 cf http://www.developpez.net/forums/s [...] stcount=19

n°1415568
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-07-2006 à 20:30:34  profilanswer
 

ThibB a écrit :

Bonjour tous le monde !
 
Je rencontre un problème lorsque je cherche à lire des réels depuis un buffer : impossible de faire fonctionner le sscanf ... encore ...
Je lis en fait une ligne de 250 caractères dont les caractère 159 à 165 represente un litrage en mL, dans mon exemple : 1023800 (autre ex :  
<...>
Est ce que quelqu'un aurait une solution ?


 
A l'avenir, poste du code compilabel (j'ai passé 20 minutes à réinventer ce qui manquait...)
 
Ceci a l'air de fonctionner. Mais je recommande double au lieu de float. Meilleure précision, meilleures performances (pas de conversions).

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. /* 0 | 1 */
  4. #define DOUBLE 0
  5. struct data
  6. {
  7. #if DOUBLE
  8.    double volumeCarbu;
  9. #else
  10.    float volumeCarbu;
  11. #endif
  12. };
  13. struct x
  14. {
  15.    struct data data[1];
  16. };
  17. static int f (struct x *s, char const *ligne, int i)
  18. {
  19.    char buffer[20];
  20.    {
  21.       size_t k;
  22.       for (k = 158; k < 165; k++)
  23.       {
  24.          buffer[k - 158] = ligne[k];
  25.       }
  26.       buffer[k - 158] = '\0';
  27.    }
  28. #if DOUBLE
  29.    if (1 != sscanf (buffer, "%lf", &s->data[i].volumeCarbu))
  30. #else
  31.    if (1 != sscanf (buffer, "%f", &s->data[i].volumeCarbu))
  32. #endif
  33.    {
  34.       return 1;
  35.    }
  36.    s->data[i].volumeCarbu /= 1000;
  37.    return 0;
  38. }
  39. int main ()
  40. {
  41.    struct x x =
  42.    {
  43.       0
  44.    };
  45.    char ligne[200] = "";
  46.    /* 1023800 ml */
  47.    ligne[158] = '0';
  48.    ligne[159] = '1';
  49.    ligne[160] = '0';
  50.    ligne[161] = '2';
  51.    ligne[162] = '3';
  52.    ligne[163] = '8';
  53.    ligne[164] = '0';
  54.    ligne[165] = '0';
  55.    int ret = f (&x, ligne, 0);
  56.    printf ("%f ret=%d\n", x.data[0].volumeCarbu, ret);
  57.    return 0;
  58. }



102.379997 ret=0
 
Press ENTER to continue.


avec double :  


102.380000 ret=0
 
Press ENTER to continue.


Message édité par Emmanuel Delahaye le 28-07-2006 à 20:33:33

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1416078
ThibB
Posté le 30-07-2006 à 18:31:58  profilanswer
 

OK merci, je test ca et je vous tiens au courant :)  
Je ferais gaffe la prochaine fois de donner les structures, les type de variables, etc ...


Message édité par ThibB le 30-07-2006 à 18:40:44

---------------
Visiter mon site

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  sscanf et lecture de réel

 

Sujets relatifs
Problème de lecture sur fichier ini.blocage sur la lecture d'un socket
[résolu] lecture à partir d'un BufferedReaderLecture de fichiers avec accents...
heure en temps reel[Résolu] Problème de droit en lecture! [move_uploaded_file()]
écriture et lecture de fichierLecture d'un fichier ini vs lecture dans la bdd
[VBS] Lecture de fichier...Lecture d'un site distant avec fopen - Passage d'argument a un CGI
Plus de sujets relatifs à : sscanf et lecture de réel


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR