String mit Hexadezimalzahl in entsprechenden int umwandeln
-
bitset<10> myset(string("1001010111"));
int myint = myset.to_ulong();Man könnte (wenn man ganz sicher gehen will) ja auch so etwas machen:
bitset<10> myset(string("1001010111")); int my_int = my_awesome_cast<int>(myset.to_ulong()); // Dabei: template<typename T> T my_awesome_cast(unsigned long input) { if (input < static_cast<unsigned long>(numeric_limits<T>.max())) return input; else { // Fehlerbehandlung } }Das müsste funktionieren, da unsigned long der größte eingebaute Integertyp ist. Geht natürlich schief, falls man es mit eigenen, größeren Typen oder Fließkommazahlen versucht.
-
Ich habe in der Zwischenzeit ausprobiert ob es mit dezimalen Zahlen funktioniert. Seltsamerweise funktioniert es nicht wie erwartet. Die Funktion die ich geschrieben habe sieht so aus:
template < typename T > T convert(const std::string &value,const std::string &base) { T ret; std::cout << "input " << value << " " << base << std::endl; std::stringstream conv(value); std::cout << "stringstream " << conv.str()<< std::endl; if(base == "hex") { conv >> std::hex >> ret; } else if(base == "dec") { conv >> std::dec >> ret; std::cout << ret << std::endl; } else if(base == "oct") { conv >> std::oct >> ret; } else { std::string error="parser error: unknown base type"; throw error; } if (conv.fail()) { std::string error="parser error: can't convert input value to expected type"; throw error; } else { return ret; } }Ich habe ein paar Testausgaben eingebaut um zu sehen, was schief läuft.
Wenn ich jetzt Versuche verschiedene Datentypen mit Werten zu füllen gibt es folgende ausgabe:
input 10 dec stringstream 10 1 input 11 dec stringstream 11 11 input 12 dec stringstream 12 12 input 23 dec stringstream 23 2 input 24 dec stringstream 24 24 input 25 dec stringstream 25 25Man sieht folgendes: das schreiben in den stringstream funktioniert immer. Bei der Konvertierung wird allerdings die letzte Dezimalstelle abgeschnitten falls T vom Typ uint8_t ist (die Typen bei den Aufrufen sind sind: uint8_t, uint16_t uint32_t, uint8_t, uint16_t uint32_t). Mit uint16_t und uint32_t treten keine Fehler auf. Eigentlich müssten 10 und 23 doch locker in einen uint8_t passen und wenn das nicht funktioniert, warum wird keine Exeption geworfen? Ich stehe total auf dem Schlauch? Hat jemand eine Idee?
-
Bei 'uint8_t' buw. 'int8_t' wirkt die char-Überladung des Operators >>, d.h. es wird nur ein einzelnes Zeichen gelesen - sind schon viele drauf hereingefallen, d.h. das beste ist immer dann die Variable 'ret' entsprechend als int (bzw. long) zu deklarieren (unabhängig von T).
-
Th69 schrieb:
Bei 'uint8_t' buw. 'int8_t' wirkt die char-Überladung des Operators >>, d.h. es wird nur ein einzelnes Zeichen gelesen - sind schon viele drauf hereingefallen, d.h. das beste ist immer dann die Variable 'ret' entsprechend als int (bzw. long) zu deklarieren (unabhängig von T).
OK das erklärt das natürlich. Wenn ich 'ret' entsprechend als int deklariere, verliere ich dann nicht den "Überlaufschutz"? Wenn der Rückgabewert generel signed ist, wird er auch in jedem Fall kleiner sein als der entsprechende Unsigned Typ, so das ich dessen Wertebereich nicht voll nutzen kann oder?
-
Nebenbei mal ne dumme Frage: Wesshalb heißt das Teil uint8_t wenn es eigentlich ein char ist? Hätte ich das Verhalten von char benötigt, hätte ich auch einen char genommen.
-
siecpp schrieb:
Nebenbei mal ne dumme Frage: Wesshalb heißt das Teil uint8_t wenn es eigentlich ein char ist? Hätte ich das Verhalten von char benötigt, hätte ich auch einen char genommen.
Weil chars sich wie int verhalten. Zumindest in jeder Hinsicht bis auf die eine Überladung bei den stream-Operatoren.
-
bit manipulation
<< 32 |
<< 16
<< 8
-
SeppJ schrieb:
Weil chars sich wie int verhalten. Zumindest in jeder Hinsicht bis auf die eine Überladung bei den stream-Operatoren.
"bis auf ..." ist gut
Das hebelt das komplette C++ Ein- und Ausgabekonzept aus, ohne das jemand ne Chance hat das zu bemerken. Wie Th69 schon bemerkte, bin ich nicht der Einzige, der darauf reingefallen ist. Wenn ein char fast wie int ist, dann soll doch der Programierer gezwungen werden ein char zu nehmen und sich selber über die Unterschiede Gedanken machen, anstatt etwas vorzutäuschen, was garnicht da ist. Ist bestimmt ne historische C Sache.
-
siecpp schrieb:
SeppJ schrieb:
Weil chars sich wie int verhalten. Zumindest in jeder Hinsicht bis auf die eine Überladung bei den stream-Operatoren.
"bis auf ..." ist gut
Das hebelt das komplette C++ Ein- und Ausgabekonzept aus, ohne das jemand ne Chance hat das zu bemerken. Wie Th69 schon bemerkte, bin ich nicht der Einzige, der darauf reingefallen ist. Wenn ein char fast wie int ist, dann soll doch der Programierer gezwungen werden ein char zu nehmen und sich selber über die Unterschiede Gedanken machen, anstatt etwas vorzutäuschen, was garnicht da ist. Ist bestimmt ne historische C Sache.Nein, das ist ungeheuer praktisch. Man verwendet char praktisch nur zum speichern von Zeichen, niemand verwendet char als Ersatz für Integertypen. Daher ist es sehr sinnvoll, dass das Standardverhalten darauf ausgelegt ist, dass chars als Zeichen und nicht als Zahl behandelt werden.
-
SeppJ schrieb:
Nein, das ist ungeheuer praktisch.
Was genau soll daran praktisch sein? Was habe ich denn für Vorteile damit, dass ich einen char als int8_t bezeichne? Ich kann immer noch nur genau das machen, was ich mit einem char machen kann nur merke ich das nicht mehr.
SeppJ schrieb:
Man verwendet char praktisch nur zum speichern von Zeichen, niemand verwendet char als Ersatz für Integertypen.
Natürlich käme normalerweise niemand auf diese Idee. Daher ist es ja umso verwunderlicher, dass die C Standardbibliothek genau das macht.
SeppJ schrieb:
Daher ist es sehr sinnvoll, dass das Standardverhalten darauf ausgelegt ist, dass chars als Zeichen und nicht als Zahl behandelt werden.
Das ist durchaus richtig so. Das Problem ist, dass das Standardverhalten eines int8_t gerade nicht durchgehend darauf ausgelegt ist, als Zahl behandelt zu werden. Warum so tun als ob es einen int8_t gäbe, wenn es den in Wirklichkeit garnicht gibt? Beim reinen C kann man noch sagen: das macht keinen Unterschied. Wer aber richtiges C++ programiert wird beim Benutzen dieses Datentypes schnell darüber stolpern dass er sich gerade nicht so verhällt, wie man es von allen anderen Typen erwarten kann.