String mit Hexadezimalzahl in entsprechenden int umwandeln
-
SeppJ schrieb:
In limits sind Compilezeitkonstanten für die Größe der verschiedenen Datentypen definiert, die als Templateargumente verwendet werden können.
Zur Umwandlung vom Binärsystem: Informier dich mal, was ein Stellenwertsystem ist und wie es funktioniert.
Was ein Stellenwertsystem ist habe ich im Studium ausreichend gelernt. Der Punkt ist, dass ich nicht weiss, wie genau Typumwandlungen in c bzw c++ funktionieren. Ich hatte gehofft, dass man in eine Variable irgendwie einzelne bits reinschieben kann und nur die anzahl der bits entscheident ist. Wenn ich noch berücksichtigen muss, wie das interpretiert wird z.B. ob der Typ vorzeichenbehaftet ist, und wie genau der dezimale Wertebereich ist, wird das schnell extrem kompliziert. Wichtig ist, das man jedes bit des Datentyps exakt so gesetzt wird, wie es angegeben wird.
-
siecpp schrieb:
Was ein Stellenwertsystem ist habe ich im Studium ausreichend gelernt. Der Punkt ist, dass ich nicht weiss, wie genau Typumwandlungen in c bzw c++ funktionieren. Ich hatte gehofft, dass man in eine Variable irgendwie einzelne bits reinschieben kann und nur die anzahl der bits entscheident ist. Wenn ich noch berücksichtigen muss, wie das interpretiert wird z.B. ob der Typ vorzeichenbehaftet ist, und wie genau der dezimale Wertebereich ist, wird das schnell extrem kompliziert. Wichtig ist, das man jedes bit des Datentyps exakt so gesetzt wird, wie es angegeben wird.
Du hast falsche Vorstellungen von dieser Art Typumwandlungen. Es wird schlicht und einfach gerechnet. Keine Zauberei mit reinterpret_cast oder so. Für hexadezimal, dezimal und oktal gibt es schon vorgefertigte Lösungen, weil diese häufig vorkommen. Daten im Binärformat hat man nur sehr selten, deshalb musst du dir die Rechnung selber schreiben.
-
Hmm OK. danke. Dann muss ich das wohl anders angehen. Ich werde mal mit unsigned Integern anfangen und dann weitersehen. Was passiert denn. wenn ich z.B. den wert einer 32 bit unsigned Variable in einer 32 bit signed Variablen speicher? Wird die dann gegebenenfalls abgeschnitten gerundet oder nur anders interpretiert?
-
Such einfach mal hier im Forum nach "Binärzahl" o.ä. - da findest du dutzende Beispiele für die Umwandlung und Darstellung einer Zahl im Binärsystem.
-
siecpp schrieb:
Was passiert denn. wenn ich z.B. den wert einer 32 bit unsigned Variable in einer 32 bit signed Variablen speicher? Wird die dann gegebenenfalls abgeschnitten gerundet oder nur anders interpretiert?
Wenn sie passt, passiert gar nichts. Wenn sie zu groß ist, dann hängt das Verhalten von der Compilerimplementierung ab.
-
Tachyon schrieb:
Wenn sie passt, passiert gar nichts. Wenn sie zu groß ist, dann hängt das Verhalten von der Compilerimplementierung ab.
OK dass hatte ich befürchtet. Dann muss ich offenbar tatsächlich unterscheiden zwischen signed und unsigned Typen und die binärzahl jeweils unterschiedlich interpretieren. Es ist sehr schade, dass es in C und C++ nur über den Umweg dezimal geht.
-
Th69 schrieb:
Such einfach mal hier im Forum nach "Binärzahl" o.ä. - da findest du dutzende Beispiele für die Umwandlung und Darstellung einer Zahl im Binärsystem.
Das hatte ich als erstes gemacht. Leider sind dort meist andere Anwendungen gemeint. Der einzigen Beitrag, der in etwa das beschreibt, was ich machen möchte ist dieser: http://www.c-plusplus.net/forum/viewtopic-var-t-is-237767-and-highlight-is-bin%E4r.html
Leider hat der keine brauchbare Antwort bekommen.
-
Vielleicht könntest du mal beschreiben, was du überhaupt machen willst. Aus deinen bisherigen Beschreibengen entnehme ich, dass du vermutlich daten die in unterschiedlichen Zahlensystemen gegeben sind parsen willst. Ist das korrekt?
Ich verstehe aber nicht, warum du dir selber solche Schwierigkeiten machst: Was soll denn deiner Meinung nach passieren, wenn eine Zahl zu groß für den Zieltyp ist? Was meinst du mit dem Umweg über Dezimal? Was ist deine GENAUE Problemstellung?
-
SeppJ schrieb:
Vielleicht könntest du mal beschreiben, was du überhaupt machen willst. Aus deinen bisherigen Beschreibengen entnehme ich, dass du vermutlich daten die in unterschiedlichen Zahlensystemen gegeben sind parsen willst. Ist das korrekt?
Ja.
SeppJ schrieb:
Ich verstehe aber nicht, warum du dir selber solche Schwierigkeiten machst: Was soll denn deiner Meinung nach passieren, wenn eine Zahl zu groß für den Zieltyp ist? Was meinst du mit dem Umweg über Dezimal? Was ist deine GENAUE Problemstellung?
OK da muss ich etwas ausholen: Ich schreibe eine Testsuit für Digitalmodule. Diese soll unter anderem Eingangswerte aus einer xml datei einlesen und sie an den entsprechenden Eingang anlegen. Auf der Softwareseite sind die Eingangstypen z.B. verschiedene Integertypen. Da die Eingänge auf Hardwareseite möglicherweise als Bitfelder, Flags etc interpretiert werden können, ist es wichtig, die einzelnen bits des Eingangs genau setzen zu können. Damit man sich als Benutzer keine Gedanken machen muss, wie z.B. die Dezimal oder Hexadezimaldarstellung des entsprechenden bitfeldes aussieht, dachte ich, eine Binärdarstellung wäre für diese Fälle optimal. Außerdem muss sichergestellt werden, dass die Eingabewerte korrekt verarbeitet werden. Falls da irgendwo etwas abgeschnitten oder gerundet wird gibt das Fehler, die sehr schwer zuzuordnen sind.
-
Gerade für Bitfelder bietet sich die Klasse std::bitset an...
Edit: hier noch ein Link aus diesem Forum zur Anwendung:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-112522.html
-
Th69 schrieb:
Gerade für Bitfelder bietet sich die Klasse std::bitset an...
Das sieht vielversprechend aus. Danke!
-
Würde das so funktionieren?
else if(base == "bin") { if (value.length() > sizeof(T)*8) { std::string error="parser error: binary value to long for given type"; throw error; } else { bitset<sizeof(T)*8> bits (value); return reinterpret_cast<T>(bits); } }
-
Nein! Weisst du wofuer reinterpret_cast da ist? Hast du die Links angesehen? Und warum arbeitest du nicht mit std::bitset selbst anstelle deiner ints, shorts, ... ?
Auf der Softwareseite sind die Eingangstypen z.B. verschiedene Integertypen.
Wird Zeit, das zu ueberdenken.
-
knivil schrieb:
Nein! Weisst du wofuer reinterpret_cast da ist?
Wenn du so fragst offenbar nicht
Ich dachte, dass sei das äquivalent zum c cast. Ich möchte einfach verhindern, dass der Compiler da irgendetwas umwandelt bzw uminterpretiertknivil schrieb:
Auch sollte Bitset deine ints und short ... etc. ersetzen und nicht nur zum Umwandeln dienen.
Das ist leider nicht möglich. Dieser Bereich ist nicht meine Baustelle. Auch wäre das wenig sinvoll. da die eingangswerte in manchen Fällen durchaus als Zahl interpretiert werden sollen.
-
OK da steckt natürlich noch ein dummer denkfehler drin. Ich werde mir mal den link anschauen, den du nachträglich reineditiert hast.
-
knivil schrieb:
Nein! Weisst du wofuer reinterpret_cast da ist? Hast du die Links angesehen? Und warum arbeitest du nicht mit std::bitset selbst anstelle deiner ints, shorts, ... ?
Ist echt schwierig, sich auf eine Aussage von dir zu beziehen, wenn du sie ständig umschreibst.
-
The reinterpret_cast operator changes one data type into another. It should be used to cast between incompatible pointer types.
Manche Referenzen sagen, das er ausdruecklich nur fuer Pointer zu verwenden ist. Du kannst ihn nicht einfach auf ein Objekt anwenden, da du nicht weisst, wie der Compiler das Objekt organisiert, auch wenn du den Aufbau der Klasse kennst.
bitset<10> myset(string("1001010111"));
int myint = myset.to_ulong();Ist doch ein tolles Beispiel.
Das ist leider nicht möglich. Dieser Bereich ist nicht meine Baustelle. Auch wäre das wenig sinvoll. da die eingangswerte in manchen Fällen durchaus als Zahl interpretiert werden sollen.
Vielleicht wird ein dezent vorgebrachter Vorschlag nicht gleich komplett abgeschmettert. Auch muss man sich ueberlegen, wie oft "manchmal" im konkreten Fall bedeutet. Falls man doch manchmal ein int braucht, ist die Umwandlung recht einfach. Passt das Bitset nicht in ein int, so wird automatisch eine Exception geworfen, die man fangen und behandeln kann. Da die Laenge aber durch einen Templateparameter festgelegt wird und du aber eine variable Laenge benoetigst (verschiedene Digitalmodule), kann man sich etwas aehnliches wie Bitset bauen, bei der man zur Laufzeit die Anzahl der Bits festlegen kann.
-
knivil schrieb:
bitset<10> myset(string("1001010111"));
int myint = myset.to_ulong();Ist doch ein tolles Beispiel.
Sicher, nachdem ich es gelesen habe ist mir auch einiges klar geworden.
knivil schrieb:
Vielleicht wird ein dezent vorgebrachter Vorschlag nicht gleich komplett abgeschmettert. Auch muss man sich ueberlegen, wie oft "manchmal" im konkreten Fall bedeutet.
Ich glaube das ist eher die Regel als die Ausnahme. Das Problem ist aber auch, dass die Hardwareseite gerade parallel entwickelt wird und da auch keiner sicher ist, was da alles kommt. Ich soll allerdings mal eben die eierlegende Wollmilchsau programieren die möglichst alle zukünftigen Testfälle abdeckt. Du hast mir aber die Augen geöffnet, dass ich da offenbar völlig falsch rangehe. Ich denke ich lasse erstmal den Binärteil weg bevor ich nicht ganz sicher bin, dass soetwas dringend gebrauch wird und halte nochmal Rücksprache.
-
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?