sprintf() ohne abschließendes Null-Leerzeichen in C

Lesezeit: 5 Minuten

Gibt es eine Möglichkeit, die C-Funktion sprintf() zu verwenden, ohne dass am Ende der Ausgabe ein ‘\0’-Zeichen hinzugefügt wird? Ich muss formatierten Text in die Mitte einer Zeichenfolge mit fester Breite schreiben.

  • Danke, ich weiß nur, dass sprintf produziert \0 am Ende seiner Ausgabe.

    – Citra Dewi

    29. Juli um 8:24 Uhr

Benutzeravatar von Greg Hewgill
Greg Hewgill

Es gibt keine Möglichkeit zu sagen sprintf() keine nachgestellte Null zu schreiben. Was Sie tun können, ist verwenden sprintf() um in eine temporäre Zeichenfolge zu schreiben, und dann so etwas wie strncpy() um nur die gewünschten Bytes zu kopieren.

  • Oder verwenden Sie memmove() oder vielleicht memcpy() anstelle von strncpy().

    – Jonathan Leffler

    10. Dezember 2008 um 18:59 Uhr

  • Roddy: Die snprintf-Funktion beendet ihre Ausgabe immer mit Null. Wenn Sie snprintf eine Größe n übergeben, schreibt es höchstens n-1 Zeichen, gefolgt von einem nachgestellten ‘\0’.

    – Greg Hewgill

    11. Dezember 2008 um 18:21 Uhr

  • Tatsächlich fügt dieses Beispiel keinen null: char name hinzu[9] = “QQ40Typ”; unsigned int i0To100 = 63; _snprintf(&name[2],2,”%d”,i0To100); printf(name);// Ausgabe: QQ63dude

    – yan bellavance

    21. Februar 2015 um 18:24 Uhr

  • @yanbellavance: Dein Beispiel funktioniert nicht so wie du es behauptest und druckt einfach QQ6.

    – Greg Hewgill

    23. Februar 2015 um 18:12 Uhr

Benutzeravatar von Doug T
Doug T.

sprintf gibt die Länge der geschriebenen Zeichenfolge zurück (ohne das Null-Terminal), Sie könnten dies verwenden, um zu wissen, wo das Null-Terminal war, und das Null-Terminal-Zeichen in etwas anderes ändern (z. B. ein Leerzeichen). Das wäre effizienter als die Verwendung von strncpy.

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';

Roddys Benutzeravatar
Roddy

Sie können dies nicht mit sprintf() tun, aber Sie kann je nach Plattform mit snprintf() möglich sein.

Sie müssen wissen, wie viele Zeichen Sie ersetzen (aber da Sie sie in die Mitte einer Zeichenfolge einfügen, wissen Sie das wahrscheinlich sowieso).

Dies funktioniert, weil einige Implementierungen von snprintf() NICHT garantieren, dass ein abschließendes Zeichen geschrieben wird – vermutlich aus Gründen der Kompatibilität mit Funktionen wie stncpy().

char message[32] = "Hello 123, it's good to see you.";

snprintf(&message[6],3,"Joe");

Danach wird „123“ durch „Joe“ ersetzt.

Bei Implementierungen, bei denen snprintf() eine Nullterminierung garantiert, selbst wenn die Zeichenfolge abgeschnitten wird, funktioniert dies nicht. Wenn also Codeportabilität ein Problem darstellt, sollten Sie dies vermeiden.

Die meisten Windows-basierte Versionen von snprintf() weisen dieses Verhalten auf.

Aber, Mac OS und BSD (und vielleicht Linux) scheinen immer nullterminiert zu sein.

  • Die snprintf-Funktion beendet ihre Ausgabe immer mit null. Nach dem Ausführen des obigen Codes enthält die Nachricht “Hello Jo”.

    – Greg Hewgill

    11. Dezember 2008 um 18:24 Uhr

  • @Greg. Sie haben fast Recht … Ich habe die Antwort aktualisiert, um die Implementierungsabhängigkeit widerzuspiegeln.

    – Roddy

    11. Dezember 2008 um 22:28 Uhr

  • Wow, ich wusste nicht, dass sich das auf den Plattformen unterscheidet, danke dafür.

    – Greg Hewgill

    12. Dezember 2008 um 5:40 Uhr

  • Hat jemand eine Ahnung, was die POSIX- und/oder C99-Spezifikationen vorschreiben?

    – Tommi

    26. Oktober 2010 um 10:13 Uhr

  • Ich glaube, die Spezifikationen schreiben vor, dass der Nullterminator immer hinzugefügt werden sollte (die Idee ist, dass Zeichenfolgen immer nullterminiert und innerhalb von Grenzen sind, wodurch ein Pufferüberlauf verhindert wird). Die meisten Implementierungen weichen jedoch vom Standard ab, indem sie \0 entweder nicht hinzufügen oder es nach dem Ende des Puffers hinzufügen. Siehe Wikipedia: printf.

    – Sam

    9. Februar 2011 um 12:06 Uhr

Sie können Ihre Zeichenfolge mit fester Breite auch wie folgt als Formatzeichenfolge verwenden:

char my_fixed_width_string_format[] = "need 10 chars starting here: %10s";
char my_fixed_width_string[40];
char string_to_print[] = "abcdefghijklmnop";
sprintf(my_fixed_width_string, my_fixed_width_string_format, string_to_print;
printf(my_fixed_width_string);

sollte nachgeben

brauchen 10 Zeichen, beginnend hier: abcdefghij

Da Sie in einen festen Bereich schreiben, können Sie dies folgendermaßen tun:

// pointer to fixed area we want to write to
char* s;

// number of bytes needed, not including the null
int r = snprintf(0, 0, <your va_args here>);

// char following the last char we will write - null goes here
char c = s[r + 1];

// do the formatted write
snprintf(s, r + 1, <your_va_args here>);

// replace what was overwritten
s[r + 1] = c;

Benutzeravatar von yan bellavance
yan bellavance

Tatsächlich fügt dieses Beispiel keine Null hinzu, wenn Sie snprintf verwenden:

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  

Benutzeravatar von afk
afk

Hier ist eine Option für speicherbeschränkte Geräte. Es tauscht die Geschwindigkeit gegen die Verwendung von weniger RAM ein. Manchmal muss ich dies tun, um die Mitte einer Zeichenfolge zu aktualisieren, die auf einem LCD gedruckt wird.

Die Idee ist, dass Sie zuerst snprintf mit einem Puffer der Größe null aufrufen, um zu bestimmen, welcher Index durch das Null-Terminator geclobbered wird.

Sie können den folgenden Code hier ausführen: https://rextester.com/AMOOC49082

#include <stdio.h>
#include <string.h>

int main(void)
{
  char buf[100] = { 'a', 'b', 'c', 'd', 'e' };
  const size_t buf_size = sizeof(buf);
  const int i = 123;

  int result = snprintf(buf, 0, "%i", i);
  if (result < 0)
  {
    printf("snprintf error: %i\n", result);
    return -1;
  }

  int clobbered_index = result; //this index will get the null term written into it

  if (result >= buf_size)
  {
    printf("buffer not large enough. required %i chars\n", result + 1);
    return -1;
  }

  char temp_char = buf[clobbered_index];
  result = snprintf(buf, buf_size, "%i", i); //add result error checking here to catch future mistakes
  buf[clobbered_index] = temp_char;

  printf("buf:%s\n", buf);

  return 0;
}

Drucke buf:123de

1408000cookie-checksprintf() ohne abschließendes Null-Leerzeichen in C

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

Privacy policy