So konvertieren Sie unsigned long in string

Lesezeit: 5 Minuten

Benutzer-Avatar
Walidix

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

    – 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

Benutzer-Avatar
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

Benutzer-Avatar
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

Benutzer-Avatar
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);

Benutzer-Avatar
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.

Benutzer-Avatar
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 );
     }

Benutzer-Avatar
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.

char *unsigned_long_to_string(char *dest, unsigned long x) {
  sprintf(dest, "%lu", x);
  return dest;
}

// Compound literal                                        v-----------------------------------v
#define UNSIGNED_LONG_TO_STRING(u) unsigned_long_to_string((char [UNSIGNED_LONG_STRING_SIZE]){0}, (u))

int main(void) {
  puts(UNSIGNED_LONG_TO_STRING(42));
  puts(UNSIGNED_LONG_TO_STRING(ULONG_MAX));
}

Ausgabe

42
18446744073709551615  // This varies

1352300cookie-checkSo konvertieren Sie unsigned long in string

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy