int in const char* umwandeln
-
Hallo ich bins wieder.
Ich wollte mir 2 Funktionen schreiben, welche ohne Hilfe von anderen Headern (string) meine Integerzahl in eine Zeichenkette umwandelt. Die erste Funktion funktioniert soweit. Die Zweite nur mit Zahlenangaben von über 19. Z.B. bei dem Parameter "12" wandelt er diesen nicht in "12" um, sondern in "11".int main() { const char* str2 = dynIntInStr2(12); cout << str2 << endl; delete [] str2; return 0; }Bei Zahlen ab 20 funktioniert sie. Kann es sein, dass ziffer abgerundet wird? Wenn ja, warum? Hier mal der Code:
char* dynIntInStr2(int z) { double zCpy = z; size_t stellen = 0; while(zCpy > 1.0) { zCpy /= 10; ++stellen; } char* temp = new char[stellen + 1]; for(size_t i = 0; i < stellen; ++i) { zCpy *= 10; int ziffer = zCpy; temp[i] = ziffer + '0'; zCpy -= ziffer; } temp[stellen] = '\0'; return temp; }
-
Die Division von Fliesskommazahlen ist nicht exakt. Probiere es mahl oohne
doublehinzubekommen und nur int zu verwenden. In Zeile 15 brauchst du dir nicht mehr die alte Zahl neu zusammenzubauen, du kannst auch gleich z verwenden und genau wie bei der Laengenbestimmung vorgehen. Auch fuer die Laengenbestimmung ist kein double erforderlich.
-
char* dynIntInStr1(int z) { int zCpy = z; size_t stellen = 0; while(zCpy != 0) { zCpy /= 10; ++stellen; } char* temp = new char[stellen + 1]; size_t i = 0; while(z != 0) { int ziffer = z % 10; temp[i++] = ziffer + '0'; z /= 10; } for(i = 0; i < stellen / 2; ++i) { const char TEMP = temp[i]; temp[i] = temp[stellen - i - 1]; temp[stellen - i - 1] = TEMP; } temp[stellen] = '\0'; return temp; }Wenn du das so meinst: Das ist die erste Funktion

-
Simon?
-
Ich habe vermutlich nichts zu tun.
#include <cassert> char* dynIntInStr2(int z) { bool sign = z < 0; if ( !sign ) z = -z; // Negation einer negativen Zahl ist u.U. undefiniert int tmp = z; unsigned digits = 0; do { ++digits; // eine Stelle gibt es immer (z == 0 beachten!) } while ( tmp /= 10 ); // Rundung in Richtung 0 ab C++11 vorgeschrieben unsigned length = digits + sign + 1; char* str = new char[length]; str[--length] = '\0'; // Terminator do { str[--length] = '0' - z % 10; // eine Stelle gibt es immer, Rest ist <= 0 } while ( z /= 10 ); if ( sign ) str[--length] = '-'; assert( length == 0 ); return str; } #include <iostream> #include <climits> int main() { const char* str2 = dynIntInStr2(INT_MIN); std::cout << str2 << '\n';; delete [] str2; return 0; }
-
#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.
throwist 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.throwist 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.throwist 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 mitthrowweiter, damit sie behandelt werden können.
Programmierfehler sollen höchstens vom Debugger behandelt werden, also ist daassertoptimal.
-
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_rangewäre doch eigentlich angebracht, oder nicht?
Die Aussage, dass man in C++ keinassert()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.