int in const char* umwandeln



  • #include <cassert>
    #include <limits>
    #include <string>
    
    void to_string_impl(unsigned u, unsigned base, char*& buf)
    {
    	if(u / base)
    		to_string_impl(u / base, base, buf);
    
    	*buf++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[u % base];
    }
    
    std::string to_string(unsigned u, unsigned base)
    {
    	assert(base >= 2 && base <= 36);
    
    	char buf[std::numeric_limits<unsigned>::digits + 1];
    	char* p = buf;
    	to_string_impl(u, base, p);
    	*p = 0;
    
    	return buf;
    }
    


  • #include <cassert>
    #include <limits>
    #include <string>
    #include <algorithm>
    
    std::string to_string(unsigned long long u, unsigned long long base)
    {
        assert(base >= 2 && base <= 36);
    
        char buf[std::numeric_limits<unsigned long long>::digits + 1];
    	char *p = buf;
    	do
    	{
    		*p++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[u % base];
    	}
    	while (u /= base);
    	std::reverse(buf, p);
        return std::string(buf, p);
    }
    
    int main()
    {
    	assert(to_string(123, 10) == "123");
    	assert(to_string(13, 2) == "1101");
    
    	for (unsigned i = 2; i <= 36; ++i)
    	{
    		assert(to_string(0, i) == "0");
    	}
    }
    


  • TyRoXx schrieb:

    std::string to_string(unsigned long long u, unsigned long long base)
    {
        assert(base >= 2 && base <= 36);
    	
        char buf[std::numeric_limits<unsigned long long>::digits + 1];
    	char *p = buf;
    	do
    	{
    		*p++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[u % base];
    	}
    	while (u /= base);
    	std::reverse(buf, p);
        return std::string(buf, p);
    }
    

    Statt assert sollte man aber throw verwenden. assert ist nicht im C++ standard enthalten. Außerdem kann throw abgefangen werden, sodass ein kleiner Fehler nicht gleich den Absturz des Programmes bedeutet.



  • Marthog schrieb:

    Statt assert sollte man aber throw verwenden.

    In C und C++ nimmt man für Fehler, die der Programmierer beim Benutzen einer Funktion macht, assert .
    throw ist für Laufzeitfehler da.

    Marthog schrieb:

    assert ist nicht im C++ standard enthalten.

    Doch, ist es.

    Marthog schrieb:

    Außerdem kann throw abgefangen werden, sodass ein kleiner Fehler nicht gleich den Absturz des Programmes bedeutet.

    Man möchte aber, dass das Programm beendet wird, denn es ist fehlerhaft. Wer weiß, was es kaputt macht, wenn man Programmierfehler ignoriert.
    Außerdem können die meisten nicht Ausnahmen-sicher programmieren oder wollen es nicht, sodass auch noch Ressourcen "lecken" würden.



  • Marthog schrieb:

    assert ist nicht im C++ standard enthalten.

    Siehe N3337, 19.3 Klausel 1/2.

    TyRoXx schrieb:

    Marthog schrieb:

    Statt assert sollte man aber throw verwenden.

    In C und C++ nimmt man für solche Fehler assert . throw ist für Laufzeitfehler da.

    Hier widersprichst du dir selbst, weil jeder Fehler den du mit assert prüfst, erst zur Laufzeit als solcher erkannt werden kann und damit auch ein Laufzeitfehler ist.



  • Sone schrieb:

    TyRoXx schrieb:

    Marthog schrieb:

    Statt assert sollte man aber throw verwenden.

    In C und C++ nimmt man für solche Fehler assert . throw ist für Laufzeitfehler da.

    Hier widersprichst du dir selbst, weil jeder Fehler den du mit assert prüfst, erst zur Laufzeit als solcher erkannt werden kann und damit auch ein Laufzeitfehler ist.

    Ich habe es noch einmal klarer formuliert.
    Ein Laufzeitfehler ist einer, der nicht durch die Analyse des Quellcodes erkannt werden kann: "Datei nicht gefunden", "Speicher alle" etc.
    Solche Fehler gibt man typischerweise mit throw weiter, damit sie behandelt werden können.
    Programmierfehler sollen höchstens vom Debugger behandelt werden, also ist da assert optimal.



  • Marthog schrieb:

    sodass ein kleiner Fehler nicht gleich den Absturz des Programmes bedeutet.

    Es ist kein Kleiner Fehler. Der Programmierer hat darauf zu achten, den Anforderungen der Funktion gerecht zu werden (gerade bei Assertions sollte man vorher einen Range-Check durchführen).

    Wie Tyrrox auch gesagt hat, generiert assert() ein SIGABRT Signal, was wiederum leicht genutzt werden kann, um bspw. Auf die Ursache zu schließen (mit dem Stackframe).



  • Übrigens würde ich hier tatsächlich eher werfen. Ein out_of_range wäre doch eigentlich angebracht, oder nicht? 🙂
    Die Aussage, dass man in C++ kein assert() benutzt, ist natürlich aber weiterhin Quatsch.



  • assert tut im Release-Mode einfach gar nichts. -> assert



  • Sone schrieb:

    Übrigens würde ich hier tatsächlich eher werfen.

    out of range ist ein logikfehler im programm. hier ist assert der richtige weg.

    logikfehler mit exceptions zu behandeln verleiten dazu sie zu ignorieren. das ist immer schlecht.


Anmelden zum Antworten