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
- strlen, strcpy, strcat
- strcmp i porównywanie
- strtok i tokenizacja
- memcpy i memset