Ich habe mich gefragt, ob meine Implementierung einer "itoa" -Funktion korrekt ist. Vielleicht kannst du mir helfen, es ein bisschen "richtiger" zu machen, ich bin mir ziemlich sicher, dass ich etwas verpasse. (Vielleicht gibt es bereits eine Bibliothek, die die Konvertierung so macht, wie ich es möchte, aber ... konnte keine finden)
%Vor% Der einzige tatsächliche Fehler besteht darin, dass Sie den Rückgabewert von malloc
für null nicht überprüfen.
Der Name itoa
wird bereits für eine Funktion verwendet, die nicht Standard, aber nicht ungewöhnlich ist. Es reserviert keinen Speicher, sondern schreibt in einen vom Aufrufer bereitgestellten Puffer:
Wenn Sie sich nicht darauf verlassen wollen, dass Ihre Plattform das hat, würde ich Ihnen trotzdem empfehlen, dem Muster zu folgen. String-Handling-Funktionen, die neu zugewiesenen Speicher in C zurückgeben, sind in der Regel ärger, als sie auf lange Sicht wert sind, da Sie meistens weitere Manipulationen vornehmen und viele Zwischenergebnisse freigeben müssen. Vergleichen Sie zum Beispiel:
%Vor%gegen
%Vor% Wenn Sie Grund haben, sich besonders um die Leistung zu sorgen (wenn Sie beispielsweise eine stdlib-ähnliche Bibliothek einschließlich itoa
implementieren) oder wenn Sie Basen implementieren, die sprintf
nicht unterstützt, dann könnten Sie das tun erwägen Sie nicht, sprintf
aufzurufen. Aber wenn Sie eine Basis 10-Saite wollen, dann war Ihr erster Instinkt richtig. Es gibt absolut nichts "Falsches" über den %d
Format-Spezifizierer.
Hier ist eine mögliche Implementierung von itoa
, nur für die Basis 10:
Hier ist einer, der den snprintf-ähnlichen Ansatz für Pufferlängen einbezieht:
%Vor% Ich denke, dass Sie vielleicht zu viel Speicher zuweisen. malloc(8*sizeof(int))
wird Ihnen auf den meisten Computern 32 Bytes geben, was wahrscheinlich für eine Textdarstellung eines int. exzessiv ist.
Ich bin nicht ganz sicher, wo Sie 8*sizeof(int)
als die maximal mögliche Anzahl von Zeichen erhalten - ceil(8 / (log(10) / log(2)))
ergibt einen Multiplikator von 3*
. Zusätzlich können Sie unter C99 und einigen älteren POSIX-Plattformen eine genau zuweisende Version mit sprintf()
erstellen:
HTH
Ich habe eine interessante Ressource gefunden, die sich mit verschiedenen Problemen bei der Itoa-Implementierung befasst Vielleicht möchten Sie auch nach itoa () Implementierungen mit Leistungstests
suchen Sie sollten zu diesem Zweck eine Funktion in der printf
-Familie verwenden. Wenn Sie das Ergebnis in stdout
oder eine Datei schreiben möchten, verwenden Sie printf
/ fprintf
. Andernfalls verwenden Sie snprintf
mit einem Puffer, der groß genug ist, um 3*sizeof(type)+2
bytes oder mehr zu speichern.
Ein guter itoa()
Funktioniert für [INT_MIN...INT_MAX]
, Basis [2...36]
Benötigt kein Zweierkomplement.
% Co_de% benötigt keinen größeren positiven Bereich als unsigned
- int
wird nicht verwendet.
Nimmt nicht unsigned
size an.
Hinweis: Verwendet int
für negative Zahlen, auch wenn '-'
.
Passen Sie die Fehlerbehandlung nach Bedarf an.
%Vor%Das sollte funktionieren:
%Vor%Wenn Sie nicht die mathematischen / Gleitkommafunktionen verwenden möchten (und in den Mathematikbibliotheken verlinken müssen), sollten Sie in der Lage sein, nicht-Gleitkommaversionen von log10 zu finden, indem Sie das Web durchsuchen und tun:
size_t len = mein_log10 (abs (x)) + 1;
Das könnte Ihnen 1 Byte mehr geben, als Sie brauchten, aber Sie hätten genug.
Dort ein paar Vorschläge, die ich machen könnte. Sie können einen statischen Puffer und Straddup verwenden, um zu verhindern, dass bei nachfolgenden Aufrufen wiederholt zu viel Speicher zugewiesen wird. Ich würde auch eine Fehlerüberprüfung hinzufügen.
%Vor%Wenn dies in einer Multithread-Umgebung aufgerufen wird, entfernen Sie "static" aus der Pufferdeklaration.
sprintf ist ziemlich langsam, wenn Leistung zählt, ist es wahrscheinlich nicht die beste Lösung.
Wenn das Basisargument eine Potenz von 2 ist, kann die Konvertierung mit einer Verschiebung und Maskierung erfolgen, und man kann vermeiden, dass die Zeichenkette umgekehrt wird, indem die Ziffern von den höchsten Positionen aufgezeichnet werden. Zum Beispiel etwas für Base = 16
%Vor%const char Ziffern [] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', a, b, c, d, e, f};
%Vor%Für Dezimalzahlen gibt es eine gute Idee, ein statisches Array zu verwenden, das groß genug ist, um die Zahlen in umgekehrter Reihenfolge aufzuzeichnen, siehe hier