Wie konvertiert man eine int(Ganzzahl) in eine Zeichenfolge? Ich versuche eine Funktion zu erstellen, die die Daten von a structin eine Zeichenfolge konvertiert , um sie in einer Datei zu speichern.
Möglicherweise möchten Sie auch diese FAQ zur Serialisierung und möglicherweise die folgenden Fragen zur Serialisierung in C lesen: (a) , (b) , (c) , um Ihre tatsächliche Absicht zu erreichen.
Moooeeeep
2
Mein üblicher Haustier semantischer Ärger hier. Sie möchten nichts konvertieren. Sie möchten eine Zeichenfolge erhalten, die eine (Basis 10?) Darstellung des Werts von enthält int. Ja ich weiß. Es ist eine sehr häufige Abkürzung, aber es nervt mich immer noch.
BEARBEITEN: Wie im Kommentar erwähnt, itoa()handelt es sich nicht um einen Standard. Verwenden Sie daher besser den in der konkurrierenden Antwort vorgeschlagenen sprintf () -Ansatz!
Mit der itoa()Funktion können Sie Ihren ganzzahligen Wert in eine Zeichenfolge konvertieren .
Hier ist ein Beispiel:
int num =321;char snum[5];// convert 123 to string [buf]
itoa(num, snum,10);// print our string
printf("%s\n", snum);
Wenn Sie Ihre Struktur in eine Datei ausgeben möchten, müssen Sie zuvor keinen Wert konvertieren. Sie können einfach die printf-Formatspezifikation verwenden, um anzugeben, wie Ihre Werte ausgegeben werden sollen, und einen der Operatoren aus der printf-Familie verwenden, um Ihre Daten auszugeben.
Um sicher zu sein tat ENOUGHgenügt wir tun können , es durchmalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@Hauleth Oder sogar zwei, wenn man bedenkt , dass (int)log10(42)ist 1.
Christian Rau
23
Oder Sie können es zur Kompilierungszeit berechnen:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
Café
4
@hauleth Immer noch +2 statt +1, auch bei Ceil: Ceil (log (100)) = 2,0, nicht 3. Also +1 für die exakten Potenzen von 10 und weitere +1 für die Beendigung von Null.
Nicht-nur-Yeti
24
Minuszeichen und Gebietsschema werden nicht berücksichtigt: Tausendertrennzeichen und Gruppierung. Bitte machen Sie es so: Verwenden Sie int length = snprintf(NULL, 0,"%d",42);, um die Länge zu ermitteln, und weisen Sie dann length+1Zeichen für die Zeichenfolge zu.
user2622016
69
Die kurze Antwort lautet:
snprintf( str, size,"%d", x );
Je länger ist: Zuerst müssen Sie die ausreichende Größe herausfinden. snprintfgibt Ihnen die Länge an, wenn Sie es NULL, 0als ersten Parameter aufrufen :
snprintf( NULL,0,"%d", x );
Weisen Sie dem Nullterminator ein Zeichen mehr zu.
#include<stdio.h>#include<stdlib.h>int x =-42;int length = snprintf( NULL,0,"%d", x );char* str = malloc( length +1);
snprintf( str, length +1,"%d", x );...
free(str);
Wenn dies für jede Formatzeichenfolge funktioniert, sodass Sie float oder double mithilfe von verwenden können "%g", können Sie int mithilfe von "%x"usw. in hex konvertieren und so weiter.
@ user1821961 Danke, es sollte wirklich erwähnt werden, dass diese Header-Dateien enthalten sein müssen.
Byxor
Ich liebe dieses, weil es das robusteste und "nach dem Buch" ist.
Motti Shneor
30
Nachdem ich mir verschiedene Versionen von itoa für gcc angesehen habe, ist die vierteste Version unter http://www.strudel.org die flexibelste Version, die ich gefunden habe und die Konvertierungen in binäre, dezimale und hexadezimale, sowohl positive als auch negative, verarbeiten kann .uk / itoa / . Während sprintf/ snprintfVorteile haben, werden sie behandeln nicht negative Zahlen für etwas anderes als Dezimal - Umwandlung. Da der obige Link entweder offline oder nicht mehr aktiv ist, habe ich die 4. Version unten eingefügt:
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/char* itoa(int value,char* result,int base){// check that the base if validif(base <2|| base >36){*result ='\0';return result;}char* ptr = result,*ptr1 = result, tmp_char;int tmp_value;do{
tmp_value = value;
value /= base;*ptr++="zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35+(tmp_value - value * base)];}while( value );// Apply negative signif(tmp_value <0)*ptr++='-';*ptr--='\0';while(ptr1 < ptr){
tmp_char =*ptr;*ptr--=*ptr1;*ptr1++= tmp_char;}return result;}
Auch das ist deutlich schneller als Sprintf. Kann beim Speichern großer Dateien wichtig sein.
Eugene Ryabtsev
@Eugene Ryabtsev C gibt die Leistungsbewertung von nicht an sprintf()und "dies ist erheblich schneller als sprintf" kann auf Ihrem Compiler zutreffen, aber nicht immer halten. Ein Compiler kann es prüfen sprintf(str, "%d", 42);und auf eine optimierte itoa()ähnliche Funktion optimieren - sicherlich schneller als dieser Benutzer. Code.
chux
3
@chux Ja, ein Compiler könnte das sprintf(str, "%d", 42);Anhängen von zwei konstanten Zeichen optimieren , aber das ist Theorie. In der Praxis sprinten die Leute keine Konstanten und die oben genannte itoa ist fast so optimiert wie es nur geht. Zumindest könnten Sie 100% sicher sein, dass Sie keine Herabstufung eines generischen Sprintf um Größenordnungen erhalten würden. Es wäre schön zu sehen, welches Gegenbeispiel Sie im Sinn haben, mit der Compiler-Version und den Einstellungen.
Eugene Ryabtsev
1
@chux Wenn es in einem Aufruf endet, erklärt es nicht viel, es sei denn, wir vergleichen die aufgerufene Routine mit der obigen Routine (bis hinunter zu keinen weiteren Aufrufen; in Assembly, wenn Sie möchten). Wenn Sie dies als Antwort mit der Compiler-Version und den Einstellungen tun, werde ich es als nützlich bewerten.
Eugene Ryabtsev
2
Es wäre gut, eine Möglichkeit bereitzustellen, um die Ausgabelänge zurückzugewinnen. Ich habe das hier gemacht: stackoverflow.com/a/52111436/895245 + Unit-Tests.
Das Konvertieren von etwas in eine Zeichenfolge sollte entweder 1) die resultierende Zeichenfolge zuweisen oder 2) ein char *Ziel und eine Größe übergeben. Beispielcode unten:
Beide arbeiten für alle inteinschließlich INT_MIN. Sie bieten eine konsistente Ausgabe, snprintf()die nicht vom aktuellen Gebietsschema abhängt.
Methode 1: Rückgabe NULLbei Speichermangel.
#define INT_DECIMAL_STRING_SIZE(int_type)((CHAR_BIT*sizeof(int_type)-1)*10/33+3)char*int_to_string_alloc(int x){int i = x;char buf[INT_DECIMAL_STRING_SIZE(int)];char*p =&buf[sizeof buf -1];*p ='\0';if(i >=0){
i =-i;}do{
p--;*p =(char)('0'- i %10);
i /=10;}while(i);if(x <0){
p--;*p ='-';}size_t len =(size_t)(&buf[sizeof buf]- p);char*s = malloc(len);if(s){
memcpy(s, p, len);}return s;}
Methode 2: NULLWird zurückgegeben, wenn der Puffer zu klein war.
staticchar*int_to_string_helper(char*dest,size_t n,int x){if(n ==0){return NULL;}if(x <=-10){
dest = int_to_string_helper(dest, n -1, x /10);if(dest == NULL)return NULL;}*dest =(char)('0'- x %10);return dest +1;}char*int_to_string(char*dest,size_t n,int x){char*p = dest;if(n ==0){return NULL;}
n--;if(x <0){if(n ==0)return NULL;
n--;*p++='-';}else{
x =-x;}
p = int_to_string_helper(p, n, x);if(p == NULL)return NULL;*p =0;return dest;}
[Bearbeiten] als Anfrage von @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3ist mindestens die maximale Anzahl, die charerforderlich ist, um den Ganzzahlentyp mit Vorzeichen als Zeichenfolge zu codieren, die aus einem optionalen negativen Vorzeichen, Ziffern und einem Nullzeichen besteht.
Die Anzahl der nicht vorzeichenbehafteten Bits in einer vorzeichenbehafteten Ganzzahl beträgt nicht mehr als CHAR_BIT*sizeof(int_type)-1. Eine Basis-10-Darstellung einer n-bit-Binärzahl nimmt n*log10(2) + 1Ziffern auf. 10/33ist etwas mehr als log10(2). +1 für das Vorzeichen charund +1 für das Nullzeichen. Andere Fraktionen könnten wie 28/93 verwendet werden.
Methode 3: Wenn man am Rande leben möchte und der Pufferüberlauf kein Problem darstellt, folgt eine einfache C99-Lösung oder eine spätere Lösung, die alle Probleme löst int.
@CiroSantilli 法轮功 改造 中心 六四 六四 法轮功 Ich bin mit der internen Implementierung von glibc nicht vertraut.
chux
3
/*Function return size of string and convert signed *
*integer to ascii value and store them in array of *
*character with NULL at the end of the array */int itoa(int value,char*ptr){int count=0,temp;if(ptr==NULL)return0;if(value==0){*ptr='0';return1;}if(value<0){
value*=(-1);*ptr++='-';
count++;}for(temp=value;temp>0;temp/=10,ptr++);*ptr='\0';for(temp=value;temp>0;temp/=10){*--ptr=temp%10+'0';
count++;}return count;}
Wenn Sie Ihre Struktur in eine Datei ausgeben möchten, müssen Sie zuvor keinen Wert konvertieren. Sie können einfach die printf-Formatspezifikation verwenden, um anzugeben, wie Ihre Werte ausgegeben werden sollen, und einen der Operatoren aus der printf-Familie verwenden, um Ihre Daten auszugeben.
printf
oder einer seiner Cousins sollte den Trick machenint
. Ja ich weiß. Es ist eine sehr häufige Abkürzung, aber es nervt mich immer noch.Antworten:
BEARBEITEN: Wie im Kommentar erwähnt,
itoa()
handelt es sich nicht um einen Standard. Verwenden Sie daher besser den in der konkurrierenden Antwort vorgeschlagenen sprintf () -Ansatz!Mit der
itoa()
Funktion können Sie Ihren ganzzahligen Wert in eine Zeichenfolge konvertieren .Hier ist ein Beispiel:
Wenn Sie Ihre Struktur in eine Datei ausgeben möchten, müssen Sie zuvor keinen Wert konvertieren. Sie können einfach die printf-Formatspezifikation verwenden, um anzugeben, wie Ihre Werte ausgegeben werden sollen, und einen der Operatoren aus der printf-Familie verwenden, um Ihre Daten auszugeben.
quelle
itoa
ist nicht Standard - siehe z. B. stackoverflow.com/questions/190229/…itoa()
das gleiche Pufferüberlaufpotential wiegets()
.Sie können
sprintf
es verwenden, oder vielleicht,snprintf
wenn Sie es haben:Wobei die Anzahl der Zeichen (plus Abschlusszeichen) in
str
berechnet werden kann mit:quelle
ENOUGH
genügt wir tun können , es durchmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
ist1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
, um die Länge zu ermitteln, und weisen Sie dannlength+1
Zeichen für die Zeichenfolge zu.Die kurze Antwort lautet:
Je länger ist: Zuerst müssen Sie die ausreichende Größe herausfinden.
snprintf
gibt Ihnen die Länge an, wenn Sie esNULL, 0
als ersten Parameter aufrufen :Weisen Sie dem Nullterminator ein Zeichen mehr zu.
Wenn dies für jede Formatzeichenfolge funktioniert, sodass Sie float oder double mithilfe von verwenden können
"%g"
, können Sie int mithilfe von"%x"
usw. in hex konvertieren und so weiter.quelle
Nachdem ich mir verschiedene Versionen von itoa für gcc angesehen habe, ist die vierteste Version unter http://www.strudel.org die flexibelste Version, die ich gefunden habe und die Konvertierungen in binäre, dezimale und hexadezimale, sowohl positive als auch negative, verarbeiten kann .uk / itoa / . Während
sprintf
/snprintf
Vorteile haben, werden sie behandeln nicht negative Zahlen für etwas anderes als Dezimal - Umwandlung. Da der obige Link entweder offline oder nicht mehr aktiv ist, habe ich die 4. Version unten eingefügt:quelle
sprintf()
und "dies ist erheblich schneller als sprintf" kann auf Ihrem Compiler zutreffen, aber nicht immer halten. Ein Compiler kann es prüfensprintf(str, "%d", 42);
und auf eine optimierteitoa()
ähnliche Funktion optimieren - sicherlich schneller als dieser Benutzer. Code.sprintf(str, "%d", 42);
Anhängen von zwei konstanten Zeichen optimieren , aber das ist Theorie. In der Praxis sprinten die Leute keine Konstanten und die oben genannte itoa ist fast so optimiert wie es nur geht. Zumindest könnten Sie 100% sicher sein, dass Sie keine Herabstufung eines generischen Sprintf um Größenordnungen erhalten würden. Es wäre schön zu sehen, welches Gegenbeispiel Sie im Sinn haben, mit der Compiler-Version und den Einstellungen.Das ist alt, aber hier ist ein anderer Weg.
quelle
Wenn Sie GCC verwenden, können Sie die asprintf-Funktion der GNU-Erweiterung verwenden.
quelle
Das Konvertieren von etwas in eine Zeichenfolge sollte entweder 1) die resultierende Zeichenfolge zuweisen oder 2) ein
char *
Ziel und eine Größe übergeben. Beispielcode unten:Beide arbeiten für alle
int
einschließlichINT_MIN
. Sie bieten eine konsistente Ausgabe,snprintf()
die nicht vom aktuellen Gebietsschema abhängt.Methode 1: Rückgabe
NULL
bei Speichermangel.Methode 2:
NULL
Wird zurückgegeben, wenn der Puffer zu klein war.[Bearbeiten] als Anfrage von @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
ist mindestens die maximale Anzahl, diechar
erforderlich ist, um den Ganzzahlentyp mit Vorzeichen als Zeichenfolge zu codieren, die aus einem optionalen negativen Vorzeichen, Ziffern und einem Nullzeichen besteht.Die Anzahl der nicht vorzeichenbehafteten Bits in einer vorzeichenbehafteten Ganzzahl beträgt nicht mehr als
CHAR_BIT*sizeof(int_type)-1
. Eine Basis-10-Darstellung einern
-bit-Binärzahl nimmtn*log10(2) + 1
Ziffern auf.10/33
ist etwas mehr alslog10(2)
. +1 für das Vorzeichenchar
und +1 für das Nullzeichen. Andere Fraktionen könnten wie 28/93 verwendet werden.Methode 3: Wenn man am Rande leben möchte und der Pufferüberlauf kein Problem darstellt, folgt eine einfache C99-Lösung oder eine spätere Lösung, die alle Probleme löst
int
.Beispielausgabe
quelle
quelle
Wenn Sie Ihre Struktur in eine Datei ausgeben möchten, müssen Sie zuvor keinen Wert konvertieren. Sie können einfach die printf-Formatspezifikation verwenden, um anzugeben, wie Ihre Werte ausgegeben werden sollen, und einen der Operatoren aus der printf-Familie verwenden, um Ihre Daten auszugeben.
quelle
Verwenden Sie die Funktion
itoa()
, um eine Ganzzahl in eine Zeichenfolge zu konvertierenBeispielsweise:
quelle