Wie teilt strtok() den String in C in Token auf?

Lesezeit: 7 Minuten

Bitte erklären Sie mir die Arbeitsweise von strtok() Funktion. Das Handbuch sagt, dass es die Zeichenfolge in Token zerlegt. Ich kann aus der Anleitung nicht nachvollziehen, was es wirklich tut.

Ich habe Uhren hinzugefügt str und *pch um zu überprüfen, ob es funktioniert, wenn die erste While-Schleife aufgetreten ist, der Inhalt von str waren nur “dies”. Wie wurde die unten gezeigte Ausgabe auf dem Bildschirm gedruckt?

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

Ausgabe:

Splitting string "- This, a sample string." into tokens:
This
a
sample
string

  • strtok() ändert seine Argumentzeichenfolge, indem er Tokens mit NUL beendet, bevor er zurückkehrt. Wenn Sie versuchen, den gesamten Puffer (str[]) wird zwischen aufeinanderfolgenden Aufrufen von geändert strtok().

    – Michael Foukarakis

    8. Oktober 2010 um 11:36 Uhr

  • Anstatt zuzuschauen strUhr str[0], str[1], str[2]

    – pmg

    8. Oktober 2010 um 13:42 Uhr

  • @pmg: Ich habe str gesehen[0] und Str[1].str[1] sollte ‘\0’ sein, aber dort war ein Leerzeichen.

    Benutzer379888

    8. Oktober 2010 um 14:01 Uhr

  • Ehrlich gesagt habe ich mir nie die Mühe gemacht, dies zu überprüfen, aber ich stelle mir vor, dass es den letzten übergebenen Zeiger zusammen mit der Position speichert, an der es aufgehört hat. Dann kann es einfach fortgesetzt werden, wenn der Zeiger NULL ist, oder die Position löschen und neu beginnen, wenn nicht.

    – Chris

    17. Mai 2012 um 18:17 Uhr


  • @Feuerwehr: statische Variable.

    – DCoder

    17. Mai 2012 um 18:20 Uhr

Benutzeravatar von AndersK
AndersK

Die Laufzeitfunktion strtok funktioniert so

Wenn Sie strtok zum ersten Mal aufrufen, geben Sie eine Zeichenfolge an, die Sie tokenisieren möchten

char s[] = "this is a string";

In der obigen Zeichenfolge scheint Leerzeichen ein gutes Trennzeichen zwischen Wörtern zu sein, also lasst uns das verwenden:

char* p = strtok(s, " ");

Was jetzt passiert, ist, dass ‘s’ gesucht wird, bis das Leerzeichen gefunden wird, das erste Token zurückgegeben wird (‘this’) und p auf dieses Token (String) zeigt.

um das nächste Token zu erhalten und mit der gleichen Zeichenfolge fortzufahren, wird NULL als erstes Argument übergeben, da strtok beibehalten wird ein statischer Zeiger zu Ihrer vorherigen übergebenen Zeichenfolge:

p = strtok(NULL," ");

p zeigt jetzt auf ‘ist’

und so weiter, bis keine Leerzeichen mehr gefunden werden können, dann wird die letzte Zeichenfolge als letztes Token ‘Zeichenfolge’ zurückgegeben.

bequemer könnten Sie es stattdessen so schreiben, um alle Token auszudrucken:

for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " "))
{
  puts(p);
}

BEARBEITEN:

Wenn Sie die zurückgegebenen Werte von speichern möchten strtok Sie müssen das Token in einen anderen Puffer kopieren, z strdup(p); da die ursprüngliche Zeichenfolge (auf die der statische Zeiger im Inneren zeigt strtok) wird zwischen Iterationen geändert, um das Token zurückzugeben.

  • Es wird also kein Nullzeichen zwischen die Zeichenfolge eingefügt? Warum zeigt meine Uhr an, dass die Zeichenfolge nur noch „THIS“ enthält?

    Benutzer379888

    8. Oktober 2010 um 12:43 Uhr

  • es ersetzt tatsächlich das gefundene ‘ ‘ durch ‘\0’. Und es stellt ‘ ‘ später nicht wieder her, so dass Ihre Zeichenfolge für immer ruiniert ist.

    Benutzer3458

    8. Oktober 2010 um 13:39 Uhr

  • +1 für statischen Puffer, das habe ich nicht verstanden

    – IEatBagels

    15. Juli 2014 um 23:05 Uhr

  • Ein sehr wichtiges Detail, das in der Zeile fehlt “Das erste Token wird zurückgegeben und p zeigt auf diesen Token”ist das strtok muss die ursprüngliche Zeichenfolge mutieren, indem ein Nullzeichen anstelle eines Trennzeichens eingefügt wird (andernfalls würden andere Zeichenfolgenfunktionen nicht wissen, wo das Token endet). Außerdem verfolgt es den Status mithilfe einer statischen Variablen.

    – Groo

    9. Juli 2020 um 8:40 Uhr

  • @AndersK Sie erwähnen immer noch nie explizit, dass das Trennzeichen ersetzt wird durch \0 was notwendig ist. Sie sagen einfach, dass die Zeichenfolge geändert wird.

    – Flori

    18. Dezember 2020 um 12:22 Uhr

Benutzeravatar von Sachin Shanbhag
Sachin Shanbhag

strtok() teilt den String in Tokens. dh beginnend von einem der Trennzeichen zum nächsten wäre Ihr einziger Token. In Ihrem Fall beginnt das Token mit “-” und endet mit dem nächsten Leerzeichen ” “. Dann beginnt das nächste Token mit ” ” und endet mit “,”. Hier erhalten Sie “This” als Ausgabe. In ähnlicher Weise wird der Rest der Zeichenfolge von Leerzeichen zu Leerzeichen in Tokens aufgeteilt und endet schließlich das letzte Token auf “.”

  • Die Endbedingung für einen Token wird zum Starttoken des nächsten Tokens. Gibt es auch ein Nullzeichen an der Stelle der Endbedingung?

    Benutzer379888

    8. Oktober 2010 um 12:32 Uhr

  • @fahad- Ja, alle Trennzeichen, die Sie haben, werden durch NUL-Zeichen ersetzt, wie andere Leute auch vorgeschlagen haben.

    – Sachin Shanbhag

    8. Oktober 2010 um 12:37 Uhr

  • Wenn alle Trennzeichen durch Nul ersetzt werden, warum enthält die Zeichenfolge dann “-this”? Es sollte “\0” enthalten

    Benutzer379888

    8. Oktober 2010 um 12:48 Uhr

  • @fahad – Es ersetzt nur die Trennzeichen durch NUL, nicht alle Zeichen zwischen den Trennzeichen. Seine Art, die Zeichenfolge in mehrere Token aufzuteilen. Sie erhalten “This”, weil es zwischen zwei angegebenen Trennzeichen steht und nicht zwischen “-this”.

    – Sachin Shanbhag

    8. Oktober 2010 um 12:58 Uhr

  • @Fahad – Ja, absolut. Alle Leerzeichen, “,” und “-” werden durch NUL ersetzt, da Sie diese, soweit ich verstehe, als Trennzeichen angegeben haben.

    – Sachin Shanbhag

    8. Oktober 2010 um 13:34 Uhr


strtok behält eine statische, interne Referenz bei, die auf das nächste verfügbare Token in der Zeichenfolge zeigt; Wenn Sie ihm einen NULL-Zeiger übergeben, funktioniert es von dieser internen Referenz aus.

Das ist der Grund strtok ist nicht wiedereintrittsfähig; Sobald Sie ihm einen neuen Zeiger übergeben, wird diese alte interne Referenz überschrieben.

  • Was meinst du mit der alten internen Referenz „verprügelt werden“. Meinten Sie „überschrieben“?

    – ylun.ca

    2. Oktober 2015 um 1:51 Uhr

  • @ylun.ca: ja, das meine ich.

    – Johannes Bode

    2. Oktober 2015 um 2:18 Uhr

strtok ändert nicht den Parameter selbst (str). Es speichert diesen Zeiger (in einer lokalen statischen Variablen). Es kann dann ändern, was dieser Parameter verweist auf bei nachfolgenden Aufrufen, ohne dass der Parameter zurückgegeben wird. (Und es kann den Zeiger, den es behalten hat, vorrücken, wie auch immer es für seine Operationen erforderlich ist.)

Von der POSIX strtok Seite:

Diese Funktion verwendet statischen Speicher, um die aktuelle Zeichenfolgenposition zwischen Aufrufen zu verfolgen.

Es gibt eine Thread-sichere Variante (strtok_r), das diese Art von Magie nicht macht.

strtok tokenisiert einen String, dh konvertiert ihn in eine Reihe von Teilstrings.

Dies geschieht durch die Suche nach Trennzeichen, die diese Token (oder Teilzeichenfolgen) trennen. Und Sie geben die Trennzeichen an. In Ihrem Fall möchten Sie ‘ ‘ oder ‘,’ oder ‘.’ oder ‘-‘ als Trennzeichen.

Das Programmiermodell zum Extrahieren dieser Token besteht darin, dass Sie Ihre Hauptzeichenfolge und den Satz von Trennzeichen per Hand strtok. Dann rufen Sie es wiederholt auf und strtok gibt jedes Mal das nächste Token zurück, das es findet. Bis es das Ende der Hauptzeichenfolge erreicht, wenn es eine Null zurückgibt. Eine andere Regel ist, dass Sie die Zeichenfolge nur beim ersten Mal und NULL für die folgenden Male übergeben. Auf diese Weise können Sie strtok mitteilen, ob Sie eine neue Tokenisierungssitzung mit einer neuen Zeichenfolge starten oder Tokens aus einer vorherigen Tokenisierungssitzung abrufen. Beachten Sie, dass strtok seinen Status für die Tokenisierungssitzung speichert. Und aus diesem Grund ist es nicht reentrant oder threadsicher (Sie sollten stattdessen strtok_r verwenden). Eine andere Sache zu wissen ist, dass es tatsächlich die ursprüngliche Zeichenfolge modifiziert. Es schreibt ‘\0’ für die Trennzeichen, die es findet.

Eine Möglichkeit, strtok kurz und bündig aufzurufen, ist wie folgt:

char str[] = "this, is the string - I want to parse";
char delim[] = " ,-";
char* token;

for (token = strtok(str, delim); token; token = strtok(NULL, delim))
{
    printf("token=%s\n", token);
}

Ergebnis:

this
is
the
string
I
want
to
parse

Benutzeravatar von tibur
Tibur

Wenn Sie es zum ersten Mal aufrufen, geben Sie die Zeichenfolge an, in die tokenisiert werden soll strtok. Und um dann die folgenden Token zu erhalten, geben Sie einfach NULL zu dieser Funktion, solange sie ein Non zurückgibt NULL Zeiger.

Das strtok Die Funktion zeichnet die Zeichenfolge auf, die Sie beim Aufrufen zuerst angegeben haben. (Was für Multi-Thread-Anwendungen wirklich gefährlich ist)

Benutzeravatar von xpmatteo
xpmatteo

strtok ändert seine Eingabezeichenfolge. Es fügt Nullzeichen (‘\0’) ein, sodass Bits der ursprünglichen Zeichenfolge als Token zurückgegeben werden. Tatsächlich weist strtok keinen Speicher zu. Sie können es vielleicht besser verstehen, wenn Sie die Zeichenfolge als eine Folge von Kästchen zeichnen.

1423130cookie-checkWie teilt strtok() den String in C in Token auf?

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

Privacy policy