itoa selber basteln?



  • also ich bin mir nicht sicher inwieweit es stimmt,
    aber es kann vorkommen das der compiler gewisse sachen aufbläht um in das 4byte-"schema" zu passen, da der cpu am besten mit 32bit umgehn kann....

    das da oben kann jetzt auch völliger schwachsinn sein ich mach mich da jetzt mal nich fest, aber ich hab sowas in der art düster im hinterkopf..



  • HumeSikkins schrieb:

    Abkürzer schrieb:

    bool ist ein schlechter Witz. Die Variablen werden so groß wie ints.

    Auf welchem Compiler hast du dieses Verhalten festgestellt? Bei den Compilern die ich kenne ist ein bool ein Byte groß und damit kleiner als ein int.

    Ja, stimmt. Ich habe mich getäuscht, aber ein ganzes Byte für zwei Zustände zu verbrauchen ist auch nicht schön.



  • Ach und deswegen ist int besser geeignet?

    Der Grund wieso es bool gibt hat aber aus ganz anderen Gründen.

    Der erste Grund ist, dass man ohne Cast Pointers zuweisen kann. Beispiel

    typedef int BOOL;
    const BOOL TRUE = 1;
    const BOOL FALSE = 0;
    //...
    int *a = foo();
    bool b = a; //ok
    BOOL c = (BOOL)a; //Cast wird gebraucht
    

    Bei int gibt es ein Zustand der Falsch darstellt und alle anderen stellen Wahr dar. Bei bool gibt es immer nur 2 Zustände. Na zweites Problem schon erkannt? Wenn nicht dann schau mal her

    typedef int BOOL;
    const BOOL TRUE = 1;
    const BOOL FALSE = 0;
    //...
    int*a = foo(); //foo gibt nicht NULL zurück
    BOOL b = (BOOL)a;
    if(b == TRUE) //Ausdruck ist falsch muss heißen if(b != FALSE)
    {/*...*/}
    bool c = a;
    if(c == true) //ok
    {/*...*/}
    

    Im Vergleich zu bool ist BOOL nur ein typedef für ein int. Das heist du kannst Schablonen für bool spezialisiren aber nicht für BOOL.

    Ich glaub das sollte reichen um bools Überlegenheit zu zeigen. 🙄



  • Irgendwer schrieb:

    typedef int BOOL;
    const BOOL TRUE = 1;
    const BOOL FALSE = 0;
    //...
    int*a = foo(); //foo gibt nicht NULL zurück
    BOOL b = (BOOL)a;
    if(b == TRUE) //Ausdruck ist falsch muss heißen if(b != FALSE)
    {/*...*/}
    

    Du mu0t das schon richtig machen

    #define TRUE 1
    #define FALSE 0
    #define BOOL(x) (!(!(x)))
    //...
    int*a = foo(); //foo gibt nicht NULL zurück
    if(BOOL(b) == TRUE) //Kein Problem
    {/*...*/}
    


  • Und du findest es nicht etwas schwachsinnig einen BOOL in einen BOOL casten zu müssen um ein richtiges Ergebnis zu bekommen? o_O"



  • Angenommen ich habe ein Spiel mit verschiedenen States, die jeweils eine update() und eine draw() Methode haben.

    Es gibt nun ne Variable "currentState", die eine Instanz des aktuellen States enthält.
    In der Mainloop wird nun zunächst die update() Methode, dann die draw() Methode aufgerufen.

    Nun wird ja auch zwischen den States gewechselt. Fändet ihr es nun besser, wenn die update() Methode einen Pointer auf die Instanz des nächsten States zurückliefert (bzw this wenn keine Änderung vorgenommen werden soll), oder wenn die Methode einen Wert zurückliefert, der angibt in welchen State gewechselt werden soll und dies dann in einer switch-case Konstruktion geprüft wird.



  • Sorry, bitte Frage in eigenen Thread verschieben! Danke



  • Abkürzer schrieb:

    groovemaster schrieb:

    Trotzdem noch lange nicht zum Original funktionsäquivalent.

    Wieso nicht?

    Du überprüfst den Wertebereich von radix nicht. Dh mit 0 für radix könnte man bei dir problemlos undefiniertes Verhalten hervorrufen.
    Im Origianlcode wird nur bei dezimaler Umwandlung das Vorzeichen beachtet.
    Sollte der Zielpuffer im Origianlcode ein Nullzeiger sein, wird dynamisch in der Funktion Speicher reserviert. Find ich persönlich abartig 🙂 , aber wenn der Autor es so will. 😕

    Abkürzer schrieb:

    bool ist ein schlechter Witz. Die Variablen werden so groß wie ints.

    Der Standard sieht das aber nicht so 😉 , was den Compilern natürlich eine gewisse Freiheit gibt.

    C++ Standard schrieb:

    in particular, sizeof(bool) and sizeof(wchar_t) are implementationdefined.

    Abkürzer schrieb:

    aber ein ganzes Byte für zwei Zustände zu verbrauchen ist auch nicht schön

    Genau deshalb gibt es ja bool. Den Standard interessiert der Speicherverbrauch herzlich wenig. Der sagt nur, dass es ein Typ ist, der zwei Zustände hat, false oder true. Dass herkömmliche x86 CPUs keine Bitregister haben, ist doch nicht die Schuld des C++ Typsystems. Und dass man gerade mit einem eigenen Typ auch speicherrelevant optimieren kann, zeigt vector<bool>. Was würdest du denn machen, wenn bool einfach nur ein typedef auf int wäre?



  • Gibt es nun eine gute itoa lösung? 😕



  • Grundsätzlich würde ich nicht versuchen, itoa entsprechend diverser Implementierungen nachzubauen. Dann kannst du auch gleich direkt itoa nehmen.
    Zudem solltest du alles, was keine Laufzeitdynamik braucht, mittels Templates realisieren, wie zB radix oder uppercase/lowercase.
    Hier mal ein Ansatz meiner Funktionen, mit denen ich vor einiger Zeit rumgespielt habe

    // x - zu konvertierender Wert
    // destination - Zielstring
    // length - verfuegbare Laenge des Zielstrings
    // return - Beginn des konvertierten Wertes im Zielstring
    template <unsigned int Radix, bool UpperCase>
    char* integer_to_string(unsigned int x, char* destination, size_t length)
    {
    	// static assert 2 <= radix <= 36
    	// assert length != 0
    	static const char* digit_map[2] = {"0123456789abcdefghijklmnopqrstuvwxyz", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
    	const char* digits = digit_map[UpperCase];
    	char* p = &destination[length];
    	do
    	{
    		unsigned int digit = x % Radix;
    		x /= Radix;
    		--p;
    		*p = digits[digit];
    	}
    	while (x != 0 && p != destination);
    	return p;
    }
    

    Falls man nun eine Funktion braucht, die speziell dezimale Zahlen ausgeben soll, kann man eine entsprechende Verkürzung schreiben

    char* integer_to_string_10(unsigned int x, char* destination, size_t length)
    {
    	return integer_to_string<10, false>(x, destination, length);
    }
    

    Für signed Zahlen müsste man natürlich noch entsprechende Anpassungen vornehmen.
    Zudem ist zu beachten, dass hier kein C-String erzeugt wird, sondern die reine Zeichensequenz. Aber ein '\0' Zeichen am Ende ranzuhängen, sofern dies erforderlich ist, sollte kein allzu grosses Problem sein.


Anmelden zum Antworten