Wie konvertiere ich in der C-Sprache unsigniert lang Wert in eine Zeichenfolge (Zeichen *) und meinen Quellcode portabel halten oder ihn einfach neu kompilieren, damit er auf einer anderen Plattform funktioniert (ohne Code neu zu schreiben?
Zum Beispiel, wenn ich habe sprintf(buffer, format, value)wie bestimme ich die Puffergröße plattformunabhängig?
mit sprintf, wie man die Puffergröße plattformunabhängig ermittelt
Dies ist tatsächlich eine große Schwäche von sprintf, die in C++ teilweise behoben wurde, indem Streams anstelle von Puffern verwendet wurden. Die übliche “Antwort” ist, einen sehr großzügigen Puffer zuzuweisen, der wahrscheinlich nicht überläuft, sprintf darauf ausgeben zu lassen und dann zu verwenden strlen um die tatsächlich produzierte Saitenlänge zu bestimmen, calloc einen Puffer von (dieser Größe + 1) und kopiere die Zeichenfolge dorthin.
– Carl Smotricz
25. April 2010 um 20:05 Uhr
@Walidix: Sie müssen rechnen log10(ULONG_MAX)…
– kennytm
25. April 2010 um 20:09 Uhr
Eine narrensichere Antwort ist snprintf Wenn du es hast. Siehe meine Antwort für ein wenig mehr Details.
– Carl Smotricz
25. April 2010 um 20:09 Uhr
jfs
const int n = snprintf(NULL, 0, "%lu", ulong_value);
assert(n > 0);
char buf[n+1];
int c = snprintf(buf, n+1, "%lu", ulong_value);
assert(buf[n] == '\0');
assert(c == n);
Beachten Sie die VLA (char buf[n+1];) erfordert C99.
– kennytm
26. April 2010 um 17:56 Uhr
2014 und ich stecke immer noch fest mit Visual Studio bei der Arbeit für die Windows-Entwicklung, was es nicht zulässt 🙁
– Ruairi O’Brien
23. Januar 2014 um 10:27 Uhr
Ausgezeichnete Antwort und eine, die man Leuten ins Gesicht werfen kann, die glauben, dass dies nicht ohne Schwierigkeiten möglich ist, es sei denn, Sie verwenden C ++. Ich sehe dich an, Carl Smotricz!!
– FizzixNerd
14. Mai 2014 um 12:42 Uhr
Karl Smotricz
Der Standardansatz ist zu verwenden sprintf(buffer, "%lu", value); um eine Zeichenfolge rep von zu schreiben value zu buffer. Überlauf ist jedoch ein potenzielles Problem, da sprintf wird glücklich (und unwissentlich) über das Ende Ihres Puffers schreiben.
Dies ist tatsächlich eine große Schwäche von sprintf, die in C++ teilweise behoben wurde, indem Streams anstelle von Puffern verwendet wurden. Die übliche “Antwort” besteht darin, einen sehr großzügigen Puffer zuzuweisen, der wahrscheinlich nicht überläuft, sprintf darauf ausgeben zu lassen und dann strlen zu verwenden, um die tatsächlich erzeugte Zeichenfolgenlänge zu bestimmen, einen Puffer von (dieser Größe + 1) aufzurufen und die Zeichenfolge dorthin zu kopieren .
Diese Seite diskutiert diese und verwandte Probleme ausführlich.
Einige Bibliotheken bieten snprintf als Alternative, mit der Sie eine maximale Puffergröße angeben können.
Ja würde ich verwenden snprintf. Es ist Standard und bietet Unterstützung für die vollständige Lösung dieses Problems.
– Johannes Schaub – litb
25. April 2010 um 20:10 Uhr
Im Widerspruch zu Ihrem Gravatar, +1 für geistige Gesundheit.
– Tim Post
25. April 2010 um 20:10 Uhr
Das Drucken einer Nummer ist ein Fall, in dem Sie es nicht brauchen snprintf; Sie können die erforderliche Puffergröße einfach festlegen. (Drucken mit %s OTOH, das erfordert Vorsicht.)
– Donal Fellows
25. April 2010 um 20:12 Uhr
Viele Programmierer werden sich besser fühlen, wenn sie eine sehr explizite Obergrenze mit angeben snprintf als Erwägungen über die Größe von Zahlen zu verwenden, um eine solche Grenze mathematisch festzulegen, oder – schlimmer noch – IMO- mit Logarithmen herumzuspielen, um diese Größe vorab zu berechnen.
– Carl Smotricz
25. April 2010 um 20:17 Uhr
Benutzer2083050
Sie können eine Funktion schreiben, die von unsigned long in str konvertiert, ähnlich der ltostr-Bibliotheksfunktion.
char *ultostr(unsigned long value, char *ptr, int base)
{
unsigned long t = 0, res = 0;
unsigned long tmp = value;
int count = 0;
if (NULL == ptr)
{
return NULL;
}
if (tmp == 0)
{
count++;
}
while(tmp > 0)
{
tmp = tmp/base;
count++;
}
ptr += count;
*ptr="\0";
do
{
res = value - base * (t = value / base);
if (res < 10)
{
* -- ptr="0" + res;
}
else if ((res >= 10) && (res < 16))
{
* --ptr="A" - 10 + res;
}
} while ((value = t) != 0);
return(ptr);
}
Sie können auf meinen Blog verweisen hier die die Implementierung und Verwendung anhand eines Beispiels erläutert.
char buffer [50];
unsigned long a = 5;
int n=sprintf (buffer, "%lu", a);
MAK
Versuchen Sie es mit sprintf:
unsigned long x=1000000;
char buffer[21];
sprintf(buffer,"%lu", x);
Bearbeiten:
Beachten Sie, dass Sie im Voraus einen Puffer zuweisen müssen und keine Ahnung haben, wie lang die Zahlen tatsächlich sein werden, wenn Sie dies tun. Ich gehe von 32bit aus longs, die Zahlen mit bis zu 10 Ziffern erzeugen kann.
Eine bessere Erläuterung der damit verbundenen Probleme finden Sie in der Antwort von Carl Smotricz.
Stapler
Für einen langen Wert müssen Sie die Längeninformationen ‘l’ und ‘u’ für unsigned decimal integer hinzufügen,
als Referenz der verfügbaren Optionen siehe Sprintf
#include <stdio.h>
int main ()
{
unsigned long lval = 123;
char buffer [50];
sprintf (buffer, "%lu" , lval );
}
Chux – Wiedereinsetzung von Monica
… wie bestimme ich die Puffergröße plattformunabhängig?
Eine der Herausforderungen beim Konvertieren von a unsigned long zu einer Zeichenfolge ist, wie man die benötigte Zeichenfolgengröße bestimmt.
Dynamisch
Teilen Sie den Wert wiederholt durch 10, bis Sie 0 finden size_needed.
value_copy = value;
unsigned size_needed = 1; // For the null character.
if (value_copy < 0) size_needed++; // Only needed for signed types.
do {
size_needed++; // Add 1 per digit.
value_copy /= 10;
} while (value_copy != 0);
Schlimmer Fall
Finde die Saitenlänge von ULONG_MAX.
Beginnen Sie mit dem Raffinierten IMAX_BITS(m) was die Anzahl der Bits in a zurückgibt Mersenne-Zahl wie ULONG_MAX. (Dies gibt uns die maximale Bitbreite, auch wenn der Typ aufgefüllt ist.) Dann skalieren Sie nach Protokoll102 (0,301…), um die Anzahl der Dezimalstellen zu finden, und addieren Sie 2 zum Runden und das Nullzeichen.
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define LOG2_10_N 28
#define LOG2_10_D 93
#define UNSIGNED_LONG_STRING_SIZE (IMAX_BITS(ULONG_MAX)*LOG2_10_N/LOG2_10_D + 2)
// Slightly different for signed types, one more for the sign:
#define SIGNED_LONG_STRING_SIZE (IMAX_BITS( LONG_MAX)*LOG2_10_N/LOG2_10_D + 3)
Bewaffnet mit der Saitengröße gibt es viele mögliche nächste Schritte. Ich verwende gerne C99 (und höher) zusammengesetztes Literal um den benötigten Raum zu bilden. Der Platz ist bis zum Ende des Blocks gültig.
mit sprintf, wie man die Puffergröße plattformunabhängig ermittelt
– Walidix
25. April 2010 um 20:01 Uhr
@Walidix die Antwort ist wahrscheinlich limits.h : en.wikipedia.org/wiki/Limits.h
– Andrej Ciobanu
25. April 2010 um 20:03 Uhr
Dies ist tatsächlich eine große Schwäche von sprintf, die in C++ teilweise behoben wurde, indem Streams anstelle von Puffern verwendet wurden. Die übliche “Antwort” ist, einen sehr großzügigen Puffer zuzuweisen, der wahrscheinlich nicht überläuft, sprintf darauf ausgeben zu lassen und dann zu verwenden
strlen
um die tatsächlich produzierte Saitenlänge zu bestimmen,calloc
einen Puffer von (dieser Größe + 1) und kopiere die Zeichenfolge dorthin.– Carl Smotricz
25. April 2010 um 20:05 Uhr
@Walidix: Sie müssen rechnen
log10(ULONG_MAX)
…– kennytm
25. April 2010 um 20:09 Uhr
Eine narrensichere Antwort ist
snprintf
Wenn du es hast. Siehe meine Antwort für ein wenig mehr Details.– Carl Smotricz
25. April 2010 um 20:09 Uhr