0Pricing
C Academy · Lekcja

strtok i tokenizacja

Dzielenie napisów

strtok i tokenizacja to bezpłatna lekcja C Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.

Czym jest tokenizacja?

Tokenizacja oznacza dzielenie napisu na mniejsze fragmenty (tokeny) oddzielone znakami ograniczającymi.

Na przykład podzielenie "a,b,c" po przecinkach daje tokeny a, b i c. C udostępnia do tego funkcję strtok.

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

int main(void) {
    char text[] = "a,b,c";
    char *token = strtok(text, ",");
    printf("First token: %s\n", token);
    return 0;
}

Sygnatura strtok

char *strtok(char *str, const char *delim);

Przy pierwszym wywołaniu przekazujesz napis. Przy kolejnych wywołaniach przekazujesz NULL, aby funkcja kontynuowała od miejsca, w którym skończyła. Zwraca następny token albo NULL, gdy przetwarzanie dobiegnie końca.

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

int main(void) {
    char text[] = "red green blue";
    char *tok = strtok(text, " ");
    while (tok != NULL) {
        printf("%s\n", tok);
        tok = strtok(NULL, " ");
    }
    return 0;
}

strtok modyfikuje napis

Ważne: strtok zmienia oryginalny napis. Zastępuje każdy separator znakiem '\0' i zwraca wskaźniki do tego samego bufora.

Oznacza to, że nie można tokenizować literału napisowego, takiego jak "a,b", ponieważ jest on tylko do odczytu.

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

int main(void) {
    char data[] = "x:y:z";
    strtok(data, ":");
    printf("data[1] is now: %d (the null byte)\n", data[1]);
    return 0;
}

Utwórz kopię możliwą do modyfikacji

Ponieważ strtok niszczy dane wejściowe, najpierw skopiuj napis, jeśli później potrzebujesz oryginału.

Użyj lokalnej tablicy typu char albo skopiuj napis za pomocą strcpy do bufora.

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

int main(void) {
    const char *original = "one-two-three";
    char copy[64];
    strcpy(copy, original);
    char *tok = strtok(copy, "-");
    while (tok) {
        printf("%s\n", tok);
        tok = strtok(NULL, "-");
    }
    printf("Original intact: %s\n", original);
    return 0;
}

Wiele separatorów

Argument delim jest zbiorem znaków, a nie sekwencją. Każdy znak należący do tego zbioru działa jako separator.

Dlatego " ,;" dzieli tekst jednocześnie po spacjach, przecinkach i średnikach.

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

int main(void) {
    char text[] = "a,b;c d";
    char *tok = strtok(text, ",; ");
    while (tok) {
        printf("[%s]\n", tok);
        tok = strtok(NULL, ",; ");
    }
    return 0;
}

Kolejne separatory

strtok traktuje ciągi separatorów jako jeden separator i pomija puste tokeny.

Dlatego "a,,b" daje tylko a i b, bez pustego tokenu pomiędzy nimi. Pamiętaj o tym podczas analizowania plików CSV, w których puste pola mają znaczenie.

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

int main(void) {
    char text[] = "a,,b";
    char *tok = strtok(text, ",");
    while (tok) {
        printf("token: %s\n", tok);
        tok = strtok(NULL, ",");
    }
    return 0;
}

Zliczanie tokenów

Częstym zadaniem jest policzenie tokenów zawartych w napisie. Zwiększaj licznik wewnątrz pętli.

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

int main(void) {
    char sentence[] = "the quick brown fox";
    int count = 0;
    char *tok = strtok(sentence, " ");
    while (tok) {
        count++;
        tok = strtok(NULL, " ");
    }
    printf("Word count: %d\n", count);
    return 0;
}

strtok przechowuje ukryty stan

strtok przechowuje swoją pozycję w statycznej zmiennej wewnętrznej. Dlatego przekazanie NULL umożliwia kontynuowanie przetwarzania poprzedniego napisu.

Wadą jest to, że funkcja nie jest reentrant ani bezpieczna wątkowo. Nie można tokenizować dwóch napisów jednocześnie.

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

int main(void) {
    char a[] = "1 2";
    char *t = strtok(a, " ");
    printf("%s\n", t);
    t = strtok(NULL, " ");
    printf("%s\n", t);
    return 0;
}

Przechowywanie tokenów

Aby korzystać z tokenów po podziale, przechowuj zwrócone wskaźniki w tablicy. Wskazują one na zmodyfikowany już bufor źródłowy, który musi nadal istnieć.

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

int main(void) {
    char csv[] = "name,age,city";
    char *fields[10];
    int n = 0;
    char *tok = strtok(csv, ",");
    while (tok && n < 10) {
        fields[n++] = tok;
        tok = strtok(NULL, ",");
    }
    for (int i = 0; i < n; i++)
        printf("Field %d: %s\n", i, fields[i]);
    return 0;
}

Wariant reentrant

POSIX oferuje strtok_r, która zamiast ukrytego stanu przyjmuje jawny argument char **saveptr. Dzięki temu można bezpiecznie zagnieżdżać wywołania i korzystać z funkcji w wielu wątkach.

W przenośnym standardzie C zwykła funkcja strtok wystarcza do analizowania danych w jednym przebiegu.

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

int main(void) {
    char text[] = "p:q:r";
    char *save;
    char *tok = strtok_r(text, ":", &save);
    while (tok) {
        printf("%s\n", tok);
        tok = strtok_r(NULL, ":", &save);
    }
    return 0;
}

Praktyka: dzielenie ścieżki

Tokenizacja świetnie sprawdza się podczas analizowania uporządkowanego tekstu, takiego jak ścieżki plików. Dzielenie po znaku / ujawnia poszczególne składniki ścieżki.

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

int main(void) {
    char path[] = "usr/local/bin";
    char *part = strtok(path, "/");
    while (part) {
        printf("-> %s\n", part);
        part = strtok(NULL, "/");
    }
    return 0;
}

Szybki test

Sprawdź swoją wiedzę na temat działania strtok.

Podsumowanie

Nauczyłeś(-aś) się dzielić napisy za pomocą strtok:

  • Przy pierwszym wywołaniu przekazuje się napis, a przy kolejnych — NULL.
  • Funkcja modyfikuje dane wejściowe, zastępując separatory znakami '\0' — najpierw kopiuj napisy tylko do odczytu.
  • Argument separatorów jest zbiorem; kolejne separatory są traktowane jako jeden.
  • Funkcja używa stanu statycznego i nie jest bezpieczna wątkowo; w razie potrzeby użyj strtok_r.

Często zadawane pytania

Czy lekcja „strtok i tokenizacja” jest bezpłatna?

Tak — pełny tekst „strtok i tokenizacja” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „strtok i tokenizacja”?

Dzielenie napisów Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C Academy?

Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „strtok i tokenizacja”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?

Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. strlen, strcpy, strcat
  2. strcmp i porównywanie
  3. strtok i tokenizacja
  4. memcpy i memset
← Powrót do C Academy