Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Probleme avec istringstream

8 réponses
Avatar
Guillaume GOURDIN
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation hexadécimal de
14... Quelqu'un peut-il me dire ce que je fais pas bien?

Merci d'avance!

8 réponses

Avatar
Michael DOUBEZ
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation hexadécimal de
14... Quelqu'un peut-il me dire ce que je fais pas bien?


La stream lit le premier "e" qui a la valeur 14 en hexadecimal.

Michael

Avatar
James Kanze
On Apr 8, 5:16 pm, Guillaume GOURDIN wrote:
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation
hexadécimal de 14... Quelqu'un peut-il me dire ce que je fais
pas bien?


Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit. Dans ce cas-là (c'était STL port, je crois), la
solution la plus simple, c'est d'écrire toi-même un manipulateur
ws, quelque chose comme :

std::istream&
ws( std::istream& source )
{
if ( source.good() ) {
std::ctype< char > const&
ctype = getFacet( source.getloc() ) ;
std::streambuf* sb = source.rdbuf() ;
int c = sb->sgetc() ;
while ( c != EOF
&& ctype.is( std::ctype_base::space,
static_cast< char >( c ) ) ) {
c = sb->snextc() ;
}
if ( c == EOF ) {
source.setstate( std::ios::eofbit ) ;
}
}
return source ;
}

(Ici, getFacet est plus ou moins std::get_facet, avec des
work-arounds pour d'autres erreurs dans une autre bibliothèque,
et qui renvoie un proxy, de façon à que tu n'aies pas besoin de
répéter le type.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Michel Decima

Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit.


Le manipulateur ne peut pas positionner failbit, mais est-ce qu'il
peut positionner eofbit ? Je dis ca parce que pour du code similaire
a celui ci-dessus, j'ai l'habitude de tester eof() plutot que le
resultat de get():

if ( iss >> std::hex >> tmp >> std::ws
&& iss.eof() ) {
// c'est bon
}

Ca marche au moins avec g++, mais pour les autres ?

MD.

Avatar
Michael DOUBEZ
On Apr 8, 5:16 pm, Guillaume GOURDIN wrote:
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation
hexadécimal de 14... Quelqu'un peut-il me dire ce que je fais
pas bien?


Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit.


Je ne comprends pas le problème dans ce cas là:
- si il était déjà à la fin, il positionne failbit et le get suivant
retourne bien EOF. Donc, la stream ne contenait bien que l'entier
- si il n'était pas à la fin, après cela, si la stream est épuisée,
alors get() va de toutes façon positionner failbit.

Michael


Avatar
Michael DOUBEZ
On Apr 8, 5:16 pm, Guillaume GOURDIN wrote:
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation
hexadécimal de 14... Quelqu'un peut-il me dire ce que je fais
pas bien?


Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit.


Je ne comprends pas le problème dans ce cas là:
- si il était déjà à la fin, il positionne failbit et le get suivant
retourne bien EOF. Donc, la stream ne contenait bien que l'entier
- si il n'était pas à la fin, après cela, si la stream est épuisée,
alors get() va de toutes façon positionner failbit.


Oups, désolé.
J'ai compris: j'avais pas réalisé qu'il y avait une lecture formatée
dans la logique du if().

Est ce qu'il n'est pas possible alors de faire une logique du type suivant ?

if ( (iss >> std::hex >> tmp) //test formatted input
&& (skipws(iss).get() == EOF) //test unformated input is EOF
)
{
//c'est bon
}

Michael



Avatar
James Kanze
On Apr 9, 11:25 pm, Michel Decima wrote:

Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit.


Le manipulateur ne peut pas positionner failbit, mais est-ce qu'il
peut positionner eofbit ?


Oui.

En général, je crois qu'on pourrait considérer le eofbit comme
une partie de l'état interne du flux. Pour des raisons diverses,
il y a eu des streambuf qui ne renvoyaient pas forcement EOF une
deuxième fois, quand on appelait sgetc. Pour éviter les
problèmes, alors, l'istream positionne eofflag toujours dès
qu'il voit un eof, et ça, où que ce soit, et n'appelle jamais
plus sgetc/sbumpc/snextc une fois que eofflag positionné. Et la
norme l'exige, plus ou moins. (En fait, la norme n'est pas 100%
claire sur ce qu'elle exige des operator<< écris par
l'utilisateur.)

Du coup, l'utilisation fréquente de eofflag après l'échec, pour
déterminer si l'échec est dû à une erreur de format ou à la fin
du fichier n'est pas 100% fiable. Essaie donc :

std::istringstream s( "1.2E-" ) ;
double d ;
s >> d ;

L'échec est bien dû à une erreur de formattage, et non à la fin
de fichier. Mais eofbit serait quand même positionné.

En fait, il faudrait deux eofflag : un interne, qui signifie
que le streambuf a renvoyé EOF, et qu'on ne doit plus y lire, et
un deuxième, qui signifier que l'échec est dû à la fin de
fichier. Ou simplement rédéfinir eofbit pour servir uniquement
dans le deuxième cas, et exiger que des streambuf::sgetc
successifs doivent toujours renvoyer la même valeur (ce qui est
le cas dans toutes les bonnes implémentations aujourd'hui).

Je dis ca parce que pour du code similaire a celui ci-dessus,
j'ai l'habitude de tester eof() plutot que le resultat de
get():

if ( iss >> std::hex >> tmp >> std::ws
&& iss.eof() ) {
// c'est bon
}

Ca marche au moins avec g++, mais pour les autres ?


Formellement, je ne crois pas que c'est garantie. Mais je vois
mal comment implémenter ws sans faire du look-ahead, et si ce
look-ahead renvoie EOF, l'eofbit doit être positionné. En
revanche, je ne l'aime pas trop, précisement à cause de toutes
ces ambiguïtés autour de eofbit. Utiliser istream::peek ou
istream::get me semble plus « intuitif ».

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Michael DOUBEZ
On Apr 8, 5:16 pm, Guillaume GOURDIN wrote:
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include <stdint.h>
using namespace std;

int main(int argc, char ** argv)
{
string s("endor ID Low Byte");
istringstream iss;
uint32_t tmp;

iss.str( s );

if ( !(iss >> hex >> tmp) )
{
return ( false );
}

cout << tmp << endl;

return ( true );
}

Pour ce code, "endor ID Low Byte" est une représentation
hexadécimal de 14... Quelqu'un peut-il me dire ce que je fais
pas bien?


Rien. Ta chaîne commence bien par un nombre hexadécimal qui a la
valeur 14. Si tu veux vérifer que c'est tout ce qu'il
contient :

if ( iss >> std::hex >> tmp >> std::ws
&& iss.get() == EOF ) {
// c'est bon
}

Attention, en revanche. J'ai déjà rencontré des manipulateur
std::ws qui positionnait failbit s'il était déjà à la fin (parce
qu'il construisait un istream::sentry avant de commencer à
lire), bien qu'un manipulateur ne doit jamais positionner
failbit.


Je ne comprends pas le problème dans ce cas là:
- si il était déjà à la fin, il positionne failbit et le get suivant
retourne bien EOF. Donc, la stream ne contenait bien que l'entier
- si il n'était pas à la fin, après cela, si la stream est épuisée,
alors get() va de toutes façon positionner failbit.


J'espère que mon message originel est bien annulé. Désolé pour le bruit,
le réveil est dur ce matin.

J'ai compris: j'avais pas réalisé qu'il y avait une lecture formatée
dans la logique du if().

//dans le message originel - code faux

Michael



Avatar
Olivier Miakinen
Bonjour,

[ Une cinquantaine de lignes citées ]

J'espère que mon message originel est bien annulé.


Je n'en sais rien. Les articles de toi qui sont visibles, en plus de
celui auquel je réponds, sont celui que tu cites intégralement (il est
donc visible deux fois, sans compter le code initial que tu as cité
intégralement trois fois), plus celui où tu ne répondais qu'une seule
ligne aux trente lignes citées.

Désolé pour le bruit,


Pour faire un peu moins de bruit, il est recommandé de supprimer de la
citation tout ce qui est superflu pour la compréhension de ta réponse.
Lire <http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html>, en
particulier les paragraphes 3a et 3b.

le réveil est dur ce matin.


Désolé.

--
Olivier Miakinen