Probleme avec istringstream

Le
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!
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Michael DOUBEZ
Le #2621691
Bonjour à tous, j'ai un problème avec le code suivant :

#include <sstream>
#include <iostream>
#include 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

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

#include <sstream>
#include <iostream>
#include 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

Michel Decima
Le #2652561

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.

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

#include <sstream>
#include <iostream>
#include 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


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

#include <sstream>
#include <iostream>
#include 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



James Kanze
Le #2702541
On Apr 9, 11:25 pm, 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 ?


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


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

#include <sstream>
#include <iostream>
#include 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



Olivier Miakinen
Le #2706751
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 particulier les paragraphes 3a et 3b.

le réveil est dur ce matin.


Désolé.

--
Olivier Miakinen

Publicité
Poster une réponse
Anonyme