printf mit %s, um Nullzeichen einzuschließen

Lesezeit: 4 Minuten

Ich muss einige Zeichenfolgen verketten und NULL-Bytes einfügen. Ich möchte ein ‘\0’ nicht als abschließendes Byte behandeln. Ich möchte meine wertvollen NULL-Bytes retten!

In einem Codebeispiel if

    char *a = "\0hey\0\0";

Ich muss in einem Format drucken, das “\0hey\0\0” ausgibt.

-AUstin

  • Wie willst du herausfinden, wie lang die Saite ist?

    Benutzer2100815

    23. Mai 2011 um 6:40 Uhr

  • es ist vorbestimmt. Ich habe Speicherplatz zugewiesen, sagen wir 8 Bytes. Ich möchte ein paar Zeichenfolgen verschiedener, vorgegebener Größen zusammenschlagen, indem ich ein printf(%s%s%s…)

    – Austin

    23. Mai 2011 um 6:44 Uhr

  • Wenn das Array eingebettete Nullen enthält, ist es kein String. Nennen Sie es nicht eine Zeichenfolge. Nennen Sie es ein Array von (vorzeichenlosen) Zeichen (mit eingebetteten Nullen). Da es sich nicht um eine Zeichenfolge handelt, können Sie keine zuverlässig verwenden String-Funktion zu diesem Objekt: nein "%s" Umstellung auf printf (oder scanf), NEIN fputsNEIN fgetsNEIN strcpyNEIN strcat

    – pmg

    23. Mai 2011 um 11:05 Uhr

Wie wäre es mit:

int i;
for(i = 0; i < 4; i++)
    printf("%c", a[i]);

Wenn Sie möchten, dass eine ‘printf-ähnliche’ Funktion dies verwendet, wenn Sie angeben %s In einer Formatzeichenfolge könnten Sie den obigen Code in Ihre eigene Funktion einfügen. Aber wie @Neil erwähnte, werden Sie Schwierigkeiten haben, eine Alternative zur Suche nach Nullbytes zu finden, um die Länge von Zeichenfolgen zu bestimmen. Dafür könnten Sie eine Art Escape-Zeichen verwenden.

  • Warum würde es viel Code brauchen? Es ist eine triviale for-Schleife? Es ist schwer, eine Alternative dazu zu sehen.

    – David Heffernan

    23. Mai 2011 um 6:55 Uhr

  • Ich sage viel Code, weil dies für 10 Strings 10 For-Schleifen bedeutet. natürlich kein Weltuntergang. Es scheint nur weniger ideal zu sein, aber ich gebe zu, dass ich nicht mit der idealsten Situation arbeite

    – Austin

    23. Mai 2011 um 7:25 Uhr

  • @austin – Bedeutet das nicht eine Funktion und zehn Aufrufe?

    – Bo Persson

    23. Mai 2011 um 16:37 Uhr

  • Ich empfehle, dafür putchar() anstelle von printf() zu verwenden. Zeichen müssen nicht formatiert werden, daher ist putchar() viel effizienter.

    – Eule

    25. August 2016 um 0:47 Uhr

  • Oder wie wäre es fwrite(a, 1, 4, stdout);. Das ist noch besser als putchar; Sie müssen die Bytes überhaupt nicht einzeln durchlaufen.

    – Peter Cordes

    3. Januar 2019 um 16:29 Uhr

Benutzeravatar von Matty K
Matty K

Das Problem hier ist, dass die Länge der Zeichenfolge a lässt sich nicht einfach bestimmen. Zum Beispiel Ihr Code..

char *a = "\0hey\0\0";

.. weist der Zeichenfolge sieben Bytes zu, wobei das letzte das NULL-Terminator ist. Mit einer Funktion wie strlen würde 0 zurückgeben.

Wenn Sie die genaue Länge der Zeichenfolge kennen, können Sie die Bytes folgendermaßen schreiben oder iterieren:

#ifdef ESCAPE_NULLS
    int i;
    for (i = 0; i <= 6; i++)
        if (a[i] == 0)
            printf("\\0");
        else
            printf("%c", a[i]);
#else
    write(1, a, 6);
#endif

Aber Sie müssen über die 6 Bescheid wissen.

Die Alternative besteht darin, keine NULL-terminierten Zeichenfolgen zu verwenden und stattdessen einen alternativen Speichermechanismus für Ihre Bytes zu implementieren. zum Beispiel ein längencodiertes Array.

#include <stdio.h>

typedef struct {
    int length;
    char *bytes;
} bytearr;

void my_printf(bytearr *arr)
{
    #ifdef ESCAPE_NULLS
        int i;
        for (i = 0; i <= arr->length; i++)
            if (arr->bytes[i] == 0)
                printf("\\0");
            else
                printf("%c", arr->bytes[i]);
    #else
        write(1, arr->bytes, arr->length);
    #endif
}

void main(void)
{
    bytearr foo = {
        6, "\0hey\0\0"
    };
    my_printf(&foo);
}

Graceless, aber hoffentlich verstehst du die Idee.

Bearbeiten: 31.05.2011

Beim erneuten Lesen der Frage ist mir gerade das Wort “verketten” aufgefallen. Wenn die NULL-Zeichen originalgetreu von einer Stelle im Speicher an eine andere kopiert werden sollen (nicht Backslash-Escape) und Sie die Gesamtzahl der Bytes in jedem Array vorher kennen, können Sie einfach verwenden memcpy.

#include <string.h>
char *a = "\0hey\0\0";   /*  6 */
char *b = "word\0up yo"; /* 10 */
char *c = "\0\0\0\0";    /*  4 */
void main(void)
{
    char z[20];
    char *zp = z;
    zp = memcpy(zp, a, 6);
    zp = memcpy(zp, b, 10);
    zp = memcpy(zp, c, 4);
    /* now z contains all 20 bytes, including 8 NULLs */
}

  • Sie haben eine if/else-Anweisung im ersten Teil Ihrer Antwort. Bedeutet dies, dass ein printf(“%c”) auf einem NULL-Byte nicht funktioniert?

    – Austin

    23. Mai 2011 um 7:28 Uhr

  • Es hängt davon ab, ob Sie das Null-Byte treu an STDOUT übergeben oder es mit einem Backslash-Escape versehen möchten (so habe ich die ursprüngliche Frage gelesen).

    – Matt K

    26. Mai 2011 um 14:40 Uhr

  • @MattyK: Sollte nichtwrite(1, a, 6);Seiwrite(1, a, sizeof(char)*6);?

    – Benutzer2284570

    21. Oktober 2015 um 13:00 Uhr

  • Sicher, wenn Sie richtigen, portablen Code schreiben. Es ist leicht, faul zu sein und anzunehmen sizeof(char)==1

    – Matt K

    22. Oktober 2015 um 6:48 Uhr

  • Mischen Sie nicht POSIX write() mit stdio printf. Verwenden fwrite. Und nicht verwenden printf("%c" Verwenden Sie für einzelne Bytes putchar! Oder besser, suchen Sie nach dem nächsten 0 und verwenden fwrite für alle Nicht-Null-Bytes mit einem Funktionsaufruf. Oder Copy-and-Escape in einen lokalen Puffer und fwrite das. Und übrigens, memcpy ist nicht strcat: memcpy gibt sein erstes Argument unverändert zurück, nicht das Ende wo es geschrieben hat. Ihr Update überschreibt also immer wieder den Anfang von z. Aber ja, memcpy ist das richtige Werkzeug für den Job, wenn Sie den richtigen Zielzeiger verwenden.

    – Peter Cordes

    3. Januar 2019 um 16:27 Uhr

char *a="\0hey\0\0";
int alen = 7;

char buf[20] = {0};
int bufSize = 20;

int i=0;
int j=0;
while( i<bufSize && j<alen )
{
    if(a[j]=='\0') {
        buf[i++]='\\';
        buf[i++]='0';
        j++;
    }
    else {
        buf[i++] = a[j++];
    }
}

printf(buf);

1443610cookie-checkprintf mit %s, um Nullzeichen einzuschließen

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

Privacy policy