Proszę wyjaśnij mi działanie strtok()
funkcji. Instrukcja mówi, że dzieli ciąg na tokeny. Nie jestem w stanie zrozumieć na podstawie instrukcji, co to właściwie robi.
Dodałem zegarki włączone str
i *pch
żeby sprawdzić jak działa, kiedy pojawiła się pierwsza pętla while, zawartość str
była tylko "ta". W jaki sposób wyniki pokazane poniżej zostały wydrukowane na ekranie?
/* 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;
}
Wynik:
Dzielenie ciągu „- to jest przykładowy ciąg”. na żetony: To za próba strunowy
strtok()
modyfikuje swój argument, kończąc tokeny z wartością NUL przed zwróceniem. Jeśli spróbujesz zbadać cały bufor (str []), zobaczysz, że jest on modyfikowany między kolejnymi wywołaniami funkcjistrtok()
.str
, oglądaćstr[0]
,str[1]
,str[2]
, ...Odpowiedzi:
strtok()
dzieli ciąg na tokeny. tj. zaczynając od jednego z ograniczników do następnego, będzie to twój jeden token. W twoim przypadku token początkowy będzie zaczynał się od „-” i kończył się następną spacją „”. Następnie następny token będzie zaczynał się od „” i kończył na „,”. Tutaj otrzymujesz „To” jako wyjście. Podobnie reszta ciągu zostaje podzielona na tokeny z przestrzeni do przestrzeni i ostatecznie kończy ostatni token znakiem „.”źródło
funkcja środowiska wykonawczego strtok działa w ten sposób
przy pierwszym wywołaniu strtok podajesz ciąg, który chcesz tokenizować
w powyższym miejscu wydaje się być dobrym separatorem między słowami, więc użyjmy tego:
dzieje się teraz to, że 's' jest przeszukiwane do momentu znalezienia znaku spacji, zwracany jest pierwszy token ('this'), a p wskazuje na ten token (string)
aby uzyskać następny token i kontynuować z tym samym ciągiem, jako pierwszy argument przekazywana jest wartość NULL, ponieważ strtok utrzymuje statyczny wskaźnik do poprzedniego przekazanego ciągu:
p wskazuje teraz na „jest”
i tak dalej, aż nie będzie można znaleźć więcej spacji, ostatni ciąg jest zwracany jako ostatni token „ciąg”.
wygodniej byłoby napisać to w ten sposób, aby wydrukować wszystkie tokeny:
EDYTOWAĆ:
Jeśli chcesz przechowywać zwracane wartości
strtok
, musisz skopiować token do innego bufora, np.strdup(p);
Ponieważ oryginalny ciąg (wskazywany przez statyczny wskaźnik wewnątrzstrtok
) jest modyfikowany między iteracjami, aby zwrócić token.źródło
p
wskazuje na ten token” , jest koniecznośćstrtok
zmiany oryginalnego ciągu przez umieszczenie pustych znaków w miejscu ogranicznika (w przeciwnym razie inne funkcje łańcuchowe nie wiedziałyby, gdzie żeton się kończy). Śledzi również stan za pomocą zmiennej statycznej.strtok
utrzymuje statyczne, wewnętrzne odniesienie wskazujące na następny dostępny token w ciągu; jeśli przekażesz mu wskaźnik NULL, będzie działać na podstawie tego wewnętrznego odniesienia.To jest powód, dla którego
strtok
nie powraca; jak tylko przekażesz mu nowy wskaźnik, stare wewnętrzne odniesienie zostanie zbite.źródło
strtok
nie zmienia samego parametru (str
). Przechowuje ten wskaźnik (w lokalnej zmiennej statycznej). Następnie może zmienić to, na co wskazuje ten parametr w kolejnych wywołaniach, bez zwracania parametru. (I może przesuwać ten wskaźnik, który zachował, niezależnie od potrzeb, aby wykonywać swoje operacje).Ze strony POSIX
strtok
:Istnieje wariant bezpieczny dla wątków (
strtok_r
), który nie wykonuje tego typu magii.źródło
ctime
zwrot statycznego sznurka - praktyczny (nikt nie musi się zastanawiać, kto powinien go zwolnić), ale nie należy go ponownie wprowadzać i potykać, jeśli nie jesteś tego bardzo świadomy.strtok
nie zmienia samego parametru (str
)”.puts(str);
wypisuje "- To" od czasustrtok
modyfikacjistr
.Przy pierwszym wywołaniu podajesz ciąg do tokenizacji
strtok
. A następnie, aby uzyskać następujące tokeny, po prostu podajeszNULL
tej funkcji, o ile zwraca onaNULL
wskaźnik inny niż wskaźnik.strtok
Funkcja zapisuje ciąg najpierw podane podczas nazwać. (Co jest naprawdę niebezpieczne w przypadku aplikacji wielowątkowych)źródło
strtok tokenizuje łańcuch, tj. konwertuje go na serię podciągów.
Robi to, wyszukując ograniczniki oddzielające te tokeny (lub podciągi). I określasz ograniczniki. W twoim przypadku chcesz „” lub „,” lub „”. lub „-” jako separator.
Model programowania służący do wyodrębniania tych tokenów polega na ręcznym obrysowaniu głównego ciągu i zestawu ograniczników. Następnie wywołujesz go wielokrotnie i za każdym razem strtok zwróci następny znaleziony token. Dopóki nie osiągnie końca głównego ciągu, kiedy zwraca wartość null. Inną zasadą jest to, że przekazujesz ciąg tylko za pierwszym razem, a NULL przy kolejnych. Jest to sposób na poinformowanie strtok, czy rozpoczynasz nową sesję tokenizacji z nowym ciągiem, czy też pobierasz tokeny z poprzedniej sesji tokenizacji. Zauważ, że strtok pamięta swój stan dla sesji tokenizacji. Z tego powodu nie jest ponownie wprowadzany ani bezpieczny dla wątków (zamiast tego powinieneś używać strtok_r). Inną rzeczą, którą należy wiedzieć, jest to, że faktycznie modyfikuje oryginalny ciąg. Zapisuje „\ 0” dla znalezionych separatorów.
Jeden ze sposobów, aby wywołać strtok, zwięźle, jest następujący:
Wynik:
źródło
strtok modyfikuje swój ciąg wejściowy. Umieszcza w nim znaki null ('\ 0'), aby zwróciło bity oryginalnego ciągu jako tokeny. W rzeczywistości strtok nie przydziela pamięci. Możesz to lepiej zrozumieć, jeśli narysujesz ciąg jako sekwencję pudełek.
źródło
Aby zrozumieć, jak
strtok()
działa, należy najpierw wiedzieć, czym jest zmienna statyczna . Ten link wyjaśnia to całkiem dobrze ....Kluczem do działania
strtok()
jest zachowanie lokalizacji ostatniego separatora między kolejnymi wywołaniami (dlategostrtok()
kontynuuje analizowanie bardzo oryginalnego ciągu, który jest do niego przekazywany, gdy jest wywoływany za pomocą anull pointer
w kolejnych wywołaniach).Przyjrzyj się mojej własnej
strtok()
implementacji, tzw.zStrtok()
, Która ma odrobinę inną funkcjonalność niż ta dostarczona przezstrtok()
A oto przykład użycia
Kod pochodzi z biblioteki przetwarzającej ciągi, którą prowadzę na Github , zwanej zString. Spójrz na kod, a nawet pomóż :) https://github.com/fnoyanisi/zString
źródło
W ten sposób zaimplementowałem strtok, niezbyt dobrze, ale po 2 godzinach pracy nad nim w końcu udało się. Obsługuje wiele ograniczników.
źródło
strtok zamienia znaki w drugim argumencie na NULL, a znak NULL jest jednocześnie końcem łańcucha.
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
źródło
Oto moja implementacja, która używa tablicy skrótów jako separatora, co oznacza, że O (n) zamiast O (n ^ 2) (tutaj jest link do kodu) :
źródło
strtok () przechowuje wskaźnik w zmiennej statycznej, w której ostatnio przerwałeś, więc w drugim wywołaniu, kiedy przekażemy wartość null, strtok () pobiera wskaźnik ze zmiennej statycznej.
Jeśli podasz tę samą nazwę ciągu, zacznie się ona ponownie od początku.
Ponadto strtok () jest destrukcyjna, tj. Wprowadza zmiany w oryginalnym ciągu znaków. więc upewnij się, że zawsze masz kopię oryginalnego.
Jeszcze jednym problemem związanym z używaniem strtok () jest to, że gdy przechowuje adres w zmiennych statycznych, w programowaniu wielowątkowym wywoływanie strtok () więcej niż raz spowoduje błąd. W tym celu użyj strtok_r ().
źródło
Dla tych, którzy nadal mają trudności ze zrozumieniem tej
strtok()
funkcji, spójrz na ten przykład w języku Python , jest to świetne narzędzie do wizualizacji kodu w C (lub C ++, Python ...).W przypadku zerwania linku, wklej:
Kredyty trafiają do Andersa K.
źródło
możesz zeskanować tablicę znaków w poszukiwaniu tokena, jeśli go znalazłeś, po prostu wypisz nową linię, w przeciwnym razie wypisz znak.
źródło
To jest fragment kodu, który pomoże lepiej zrozumieć ten temat.
Drukowanie tokenów
Zadanie: Biorąc pod uwagę zdanie, wypisz każde słowo zdania w nowej linii.
Wejście:
How is that
Wynik:
Objaśnienie: Więc tutaj używana jest funkcja "strtok ()" i jest ona iterowana przy użyciu pętli for, aby wydrukować tokeny w oddzielnych wierszach.
Funkcja przyjmie parametry jako „ciąg” i „punkt przerwania” i przerwie łańcuch w tych punktach przerwania i utworzy tokeny. Teraz te tokeny są przechowywane w „p” i są dalej używane do drukowania.
źródło