Was ist der richtige Weg, um eine gute Funktion "itoa ()" zu implementieren?

8

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%     
Nicolas C. 09.08.2010, 13:59
quelle

11 Antworten

6

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:

%Vor%

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:

%Vor%

Hier ist einer, der den snprintf-ähnlichen Ansatz für Pufferlängen einbezieht:

%Vor%     
Steve Jessop 09.08.2010, 16:18
quelle
10
%Vor%     
Minh Nguyen 12.09.2012 11:16
quelle
3

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.

    
kbrimington 09.08.2010 14:08
quelle
2

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:

%Vor%

HTH

    
llasram 09.08.2010 14:20
quelle
2

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     
Adam 09.08.2010 19:50
quelle
1

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.

    
R.. 09.08.2010 16:07
quelle
1

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%     
chux 29.04.2015 03:29
quelle
0

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.

    
nategoose 09.08.2010 15:18
quelle
0

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.

    
Brandon Horsley 09.08.2010 14:19
quelle
0

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

    
Sergey Solovyev 08.11.2017 17:24
quelle
-1
%Vor%     
user411313 09.08.2010 14:17
quelle

Tags und Links