Wie iteriere ich über eine Zeichenfolge in C?

Lesezeit: 2 Minuten

Vincents Benutzeravatar
Vinzenz

Momentan versuche ich das:

#include <stdio.h>

int main(int argc, char *argv[]) {

    if (argc != 3) {

        printf("Usage: %s %s sourcecode input", argv[0], argv[1]);
    }
    else {
        char source[] = "This is an example.";
        int i;

        for (i = 0; i < sizeof(source); i++) {

            printf("%c", source[i]);
        }
    }

    getchar();

    return 0;
}

Auch das geht NICHT:

char *source = "This is an example.";
int i;

for (i = 0; i < strlen(source); i++){

    printf("%c", source[i]);
}

Ich bekomme den Fehler

Unbehandelte Ausnahme bei 0x5bf714cf (msvcr100d.dll) in Test.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000054.

(frei übersetzt aus dem Deutschen)

Also, was ist falsch an meinem Code?

  • Bitte bearbeiten Sie den Code, nach dem Sie gefragt haben, nicht. Das ändert Ihre Frage ziemlich, sodass viele der Antworten irrelevant sind. Posten Sie stattdessen einfach alle Dinge, die Sie ausprobiert haben, und erwähnen Sie, welche davon als Antwort auf die Antworten erfolgten.

    – Michael myers

    9. Juli 2010 um 15:13 Uhr

  • Der neue Test gegen argc, den Sie hinzugefügt haben, ist falsch.

    anon

    9. Juli 2010 um 15:17 Uhr

Sie wollen:

for (i = 0; i < strlen(source); i++) {

sizeof gibt Ihnen die Größe des Zeigers, nicht die Zeichenfolge. Es hätte jedoch funktioniert, wenn Sie den Zeiger als Array deklariert hätten:

char source[] = "This is an example.";

aber wenn Sie das Array an function übergeben, zerfällt auch das zu einem Zeiger. Für Saiten verwendest du am besten immer strlen. Beachten Sie, was andere über das Ändern von printf zur Verwendung von %c gesagt haben. Und auch unter Berücksichtigung von mmyers Kommentaren zur Effizienz wäre es besser, den Aufruf von strlen aus der Schleife zu verschieben:

int len = strlen(source);
for (i = 0; i < len; i++) {

oder die Schleife umschreiben:

for (i = 0; source[i] != 0; i++) {

  • Uh, ich bezweifle irgendwie, dass er es benutzen will strlen als gebunden. (Obwohl zugegeben, in einem 10-Zeilen-Programm macht es keinen großen Unterschied.)

    – Michael myers

    9. Juli 2010 um 15:01 Uhr


  • Nun, zuletzt habe ich nachgesehen, dass strlen alle Zeichen durchlaufen musste, um die Länge herauszufinden. Und da sich char* in der Schleife ändern könnte, kann strlen nicht aus der Begrenzungsprüfung durch den Compiler gehoben werden; das macht die Schleife O(n^2) statt O(n). Bitte korrigieren Sie mich, falls ich falsch liege.

    – Michael myers

    9. Juli 2010 um 15:06 Uhr

  • In diesem Beispiel könnte ein guter Compiler feststellen, dass sich der String nicht ändert, und wiederholte Aufrufe von strlen auslassen. Aber es ist wahrscheinlich besser, die Länge vor der Schleife in einer Variablen zu speichern.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Juli 2010 um 15:09 Uhr

  • @Neil Butterworth: Der Unterschied zwischen for (i=0, max=strlen(str); i

    – Vatine

    9. Juli 2010 um 15:09 Uhr

  • @anon Sicher, es spielt keine Rolle, wenn Sie ein Programm schreiben, das eine Zeichenfolge mit 21 Zeichen druckt, aber der Unterschied zwischen O (n ^ 2) und O (n) wird sehr deutlich, wenn es darauf ankommt.

    – Elfen Tau

    29. April 2018 um 18:05 Uhr

Benutzeravatar von Alexandre C
Alexandre C.

Eine gängige Redewendung ist:

char* c = source;
while (*c) putchar(*c++);

Ein paar Anmerkungen:

  • In C sind Strings nullterminiert. Sie iterieren, während das gelesene Zeichen nicht das Nullzeichen ist.
  • *c++ Schritte c und gibt die dereferenzierte zurück alt Wert von c.
  • printf("%s") gibt eine nullterminierte Zeichenfolge aus, kein Zeichen. Dies ist die Ursache Ihrer Zugriffsverletzung.

  • Kann ich benutzen while (*c++) putc(*c);?

    – Incerteza

    6. September 2014 um 15:25 Uhr

  • -1 “In C sind Strings nullterminiert.” Das macht keinen Sinn. Vielleicht versuchen Sie zu sagen, dass C-Strings nullterminiert sein sollten.

    – Celeritas

    22. September 2014 um 4:06 Uhr

  • @Celeritas: Ich finde die Ablehnung etwas hart – C hat Sprachunterstützung für nullterminierte Zeichenfolgen, und das OP verwendet diese. Zugegeben, Sie können gezählte Zeichenfolgen verwenden (z. BSTRs in der Windows-Welt), aber sie sind weniger verbreitet, und die Frage ist nicht mehrdeutig, welchen String-Typ man verwendet.

    – Alexander C.

    22. September 2014 um 18:20 Uhr

  • Oh, du redest nur davon, wie sie heißen? Nullterminiert ist eher ein Name aus der Win32-API-Welt (wo String-Variablen dämlich vorangestellt werden sz), und nullterminiert ist ein eher “traditioneller” (und gebräuchlicher) Name. Jedenfalls meinen beide dasselbe.

    – Alexander C.

    23. September 2014 um 17:54 Uhr

  • Ist das putc aus <stdio.h>? Weil es scheint, dass diese Funktion ein zweites Argument erwartet, einen Stream. putchar kann mit nur einem einzigen Argument verwendet werden, wie es dieses Beispiel tut.

    – Dave Yarwood

    2. September 2017 um 14:30 Uhr

Benutzeravatar von Mark Ingram
Markus Ingram

Anstatt wie oben vorgeschlagen strlen zu verwenden, können Sie einfach nach dem NULL-Zeichen suchen:

#include <stdio.h>

int main(int argc, char *argv[])
{
    const char *const pszSource = "This is an example.";
    const char *pszChar = pszSource;

    while (pszChar != NULL && *pszChar != '\0')
    {
        printf("%s", *pszChar);
        ++pszChar;
    }

    getchar();

    return 0;
}

  • Es wird funktionieren, aber ich würde empfehlen, dies zu überprüfen pszChar != '\0' sowieso explizit sein. Du vergleichst nicht mit NULL (typischerweise für Zeiger), aber gegen das Nullzeichen, das C-Strings beendet. (Alternativ sind beide gleich Null, also pszChar && *pszChar ist auch ein guter Zustand, wenn Sie auf so etwas stehen).

    – Matt Enright

    3. April 2013 um 13:11 Uhr

Ein optimierter Ansatz:

for (char character = *string; character != '\0'; character = *++string)
{
    putchar(character); // Do something with character.
}

Die meisten C-Strings sind nullterminiert, was bedeutet, dass sobald das Zeichen zu a wird '\0' die Schleife sollte aufhören. Das *++string bewegt den Zeiger um ein Byte, dereferenziert ihn dann und die Schleife wiederholt sich.

Der Grund, warum dies effizienter ist als strlen() liegt daran, dass strlen bereits die Saite durchläuft, um die Länge zu finden, sodass Sie effektiv zweimal (einmal mehr als nötig) mit loopen würden strlen().

sizeof(source) gibt die Anzahl der vom Zeiger benötigten Bytes zurück char*. Sie sollten es durch ersetzen strlen(source) Dies ist die Länge der Zeichenfolge, die Sie anzeigen möchten.

Außerdem sollten Sie wahrscheinlich ersetzen printf("%s",source[i]) mit printf("%c",source[i]) da Sie einen Charakter anzeigen.

Benutzeravatar von KenE
KenE

  1. sizeof() enthält das abschließende Nullzeichen. Sie sollten strlen() verwenden (aber den Aufruf außerhalb der Schleife platzieren und in einer Variablen speichern), aber das ist wahrscheinlich nicht der Grund für die Ausnahme.
  2. Sie sollten in printf “%c” und nicht “%s” verwenden – Sie drucken ein Zeichen, keine Zeichenfolge.

Das sollte funktionieren

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

 int main(int argc, char *argv[]){

    char *source = "This is an example.";
    int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
    for (int i = 0; i < length; i++) 
    {

       printf("%c", source[i]);

    }


 }

1416900cookie-checkWie iteriere ich über eine Zeichenfolge in C?

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

Privacy policy