|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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! |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Guillaume GOURDIN a écrit :
> 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 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Apr 8, 5:16 pm, Guillaume GOURDIN <tr...@hotmail.com> 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:james.kanze@gmail.com 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 |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
James Kanze a écrit :
> 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. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
James Kanze a écrit :
> On Apr 8, 5:16 pm, Guillaume GOURDIN <tr...@hotmail.com> 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 |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Michael DOUBEZ a écrit :
> James Kanze a écrit : >> On Apr 8, 5:16 pm, Guillaume GOURDIN <tr...@hotmail.com> 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 |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Apr 9, 11:25 pm, Michel Decima <michel.dec...@wanadoo.fr> wrote:
> James Kanze a écrit : > > 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:james.kanze@gmail.com 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 |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Michael DOUBEZ a écrit :
> James Kanze a écrit : >> On Apr 8, 5:16 pm, Guillaume GOURDIN <tr...@hotmail.com> 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 |
|
![]() |
| Outils de la discussion | |
|
|