Funkcie na spracovanie reťazcov. Man strtok_r(3): extrahovanie prvkov (tokenov) z popisu reťazca Strtok s c

4 odpovede

O strtok treba vedieť dve veci. Ako už bolo spomenuté, „udržiava vnútorný stav“. Navyše on pokazil linku, ktorú kŕmite. V podstate napíše "\0", kde nájde token, ktorý ste poskytli, a vráti ukazovateľ na začiatok riadku. Interne zachováva umiestnenie posledného tokenu; a keď nabudúce zavoláte, začne to odtiaľ.

Dôležitým dôsledkom je, že nemôžete použiť strtok na reťazec ako const char* "hello world"; pretože pri zmene obsahu reťazca const char* dôjde k porušeniu prístupu.

„Dobrá vec“ na strtok je, že v skutočnosti nekopíruje reťazce, takže nemusíte spravovať ďalšie prideľovanie pamäte atď. Ak však vyššie uvedenému nerozumiete, budete mať problém ho použiť.

Príklad. Ak máte "toto, je, reťazec", následné volania strtok vygenerujú ukazovatele ako je tento (hodnota ^ je návratová hodnota). Všimnite si, že "\0" sa pridá tam, kde sa nachádzajú tokeny; to znamená, že pôvodný riadok bol upravený:

T h i s , i s , a , s t r i n g \0 this,is,a,reťazec t h i s \0 i s , a , s t r i n g \0 tento ^ t h i s \0 i s \0 a , s t r i n g \0 je ^ \ t h i s \0 i s 0 s t r i n g \0 a ^ t h i s \0 i s \0 a \0 s t r i n g \0 reťazec ^

Dúfam, že to dáva zmysel.

Funkcia strtok() ukladá dáta medzi hovormi. Používa tieto údaje, keď ich zavoláte pomocou ukazovateľa NULL.

Bod, v ktorom bol nájdený posledný token, je interne uložený funkciou, ktorá sa použije pri ďalšom volaní (nie je potrebná žiadna špecifická implementácia knižnice, aby sa predišlo zlyhaniam údajov).

strtok udržiava vnútorný stav. Keď ho zavoláte s inou hodnotou ako NULL, znova sa inicializuje, aby použil reťazec, ktorý zadáte. Keď ho zavoláte s NULL , použije tento reťazec a akýkoľvek iný stav, ktorý momentálne má, na vrátenie ďalšieho tokenu.

Vzhľadom na spôsob fungovania strtok sa musíte uistiť, že ak píšete viacvláknovú aplikáciu, máte prepojenie na viacvláknovú verziu C runtime. To zaisťuje, že každé vlákno dostane svoj vlastný vnútorný stav pre strtok.

Funkcia strtok ukladá údaje do internej statickej premennej, ktorú zdieľajú všetky vlákna.

Pre bezpečnosť vlákien by ste mali použiť strtok_r

Pozrite sa na statický znak *posledný;

Char * strtok(s, delim) register char *s; register const char *delim; ( register char *spanp; register int c, sc; char *tok; statický znak *posledný; if (s == NULL && (s = posledný) == NULL) return (NULL); /* * Preskočiť (span) úvod oddeľovače (s += strspn(s, delim), druh == sc) goto cont ) if (c == 0) ( /* žiadne znaky bez oddeľovača */ last = NULL; return (NULL); ) tok = s - 1 /* * Skenovací token (skenovanie oddeľovačov: s += strcspn(s, delim), druh * Všimnite si, že aj delim musí mať jednu hodnotu NUL; )delim; do ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); ) ) while (sc != 0 ) /* NEDOSAHOVANÉ */ )

zdieľam

Popis

Funkcia strtok hľadá tokeny v reťazci. Postupnosť volaní tejto funkcie rozdelí reťazec na tokeny, čo sú sekvencie znakov oddelené oddeľovacími znakmi.

Pri prvom volaní funkcia berie ako argument reťazec, ktorého prvý znak sa používa ako počiatočný bod na vyhľadávanie tokenov. Pri nasledujúcich volaniach funkcia čaká na nulový ukazovateľ a použije pozíciu bezprostredne po konci posledného tokenu ako nové umiestnenie na skenovanie.

Na určenie začiatku tokenu funkcia najprv určí znaky, ktoré nie sú obsiahnuté v reťazci delim , to znamená, že ide o oddeľovacie znaky. A potom kontroluje zvyšok reťazca znak po znaku až po prvý oddeľovací znak, ktorý signalizuje koniec tokenu.

Tento koncový token sa automaticky nahradí znakom null a funkcia vráti token. Potom nasledujúce volania funkcie strtok začínajú týmto nulovým znakom.

Možnosti:

  • reťazec
    Reťazec, v ktorom sa majú hľadať lexémy. Obsah tohto reťazca sa zmení, bude rozbitý na menšie reťazce (tokeny). Tento parameter môže obsahovaťnulový ukazovateľ, v takom prípade funkcia pokračuje v skenovaní od miesta, kde predchádzajúce úspešné volanie funkcie skončilo.
  • delim
    Reťazec obsahujúci oddeľovače. Môžu sa líšiť od jedného volania funkcie k inému volaniu funkcie.

Návratová hodnota

Ukazovateľ na posledný token nájdený v reťazci.
Ak sa nenájdu žiadne tokeny, vráti sa nulový ukazovateľ.

Príklad: zdrojový kód programu

//príklad použitia funkcie strtok #include #include int main () ( char str = "Črty národného rybolovu - hraný, komediálny film."; std::cout<< "Разделение строки "" << str << "" на лексемы:n"; char * pch = strtok (str," ,.-"); // во втором параметре указаны разделитель (пробел, запятая, точка, тире) while (pch != NULL) // пока есть лексемы { std::cout << pch << "n"; pch = strtok (NULL, " ,.-"); } return 0; }

Programovacie jazyky môžu obsahovať špeciálne funkcie na manipuláciu s reťazcami, čím sa eliminuje potreba, aby programátor písal svoje vlastné funkcie na spracovanie reťazcov. Napríklad často potrebujete určiť dĺžku reťazca, a preto jazyky poskytujú funkciu, ktorá meria jeho dĺžku.

V programovacom jazyku C sú funkcie na prácu s reťazcami deklarované v hlavičkovom súbore string.h, ktorý musíte nezabudnúť zahrnúť do zdrojového kódu. Funkcií na prácu s reťazcami je asi dvadsať. Medzi nimi sú tie, ktoré hľadajú znaky v reťazci, porovnávacie funkcie, kopírovanie reťazcov, ako aj konkrétnejšie. Zoznam a popis väčšiny funkcií, ktoré v súčasnosti existujú v jazyku C, možno nájsť v prílohe knihy B. Kernighana a D. Ritchieho „The C Programming Language Second Edition“.

Všetky funkcie deklarované v string.h môžu počas svojej práce zmeniť alebo nezmeniť jeden z reťazcov, ktoré prechádzajú ukazovateľom. Závisí to od účelu funkcie. Väčšina z nich však niečo vracia: buď ukazovateľ na znak alebo celé číslo. Navyše, ak funkcia zmení jeden zo svojich parametrov a bola volaná na tento účel, potom to, čo vracia, môže byť ignorované (t. j. nepriradené k ničomu vo volajúcej funkcii).

Napríklad funkcia strcpy() má nasledujúcu deklaráciu: char *strcpy (char *, const char*) . Skopíruje reťazec, na ktorý ukazuje druhý parameter, do reťazca, na ktorý ukazuje prvý parameter. Prvý parameter sa teda zmení. Okrem toho funkcia vráti ukazovateľ na prvý znak reťazca:

char s1[10], s2[10]; char * s3; s3 = s2; dostane(s1); s3 = strcpy(s2, s1); kladie (s2) ; kladie (s3) ; printf("%p, %p \n", s2, s3);

Tu s2 a s3 ukazujú na rovnaký symbol (printf() vypíše rovnaké adresy). To, čo vráti strcpy() však nemožno priradiť k poli. Výsledok tejto funkcie zvyčajne nie je k ničomu priradený; Niekedy stačí, že jednoducho zmení jeden z reťazcov prejdených ukazovateľom.

Ďalšou vecou sú funkcie ako strlen() alebo strcmp() , ktoré nemenia parametre, ale sú volané kvôli výsledku. Funkcia strcmp() porovná dva argumentové reťazce písmeno po písmene (lexikograficky) a vráti 0, -1 alebo 1. Napríklad volanie strcmp("chlapec", "telo") vráti 1, pretože Kód písmena „y“ je väčší ako písmeno „d“. Volanie strcmp("telo", "chlapec") vráti -1, pretože prvý argument je lexikograficky menší ako druhý.

funkcia strtok()

Pomocou funkcie strtok() môžete rozdeliť reťazec na samostatné časti (tokeny). Deklarácia tejto funkcie vyzerá takto: char *strtok (char *, const char *) . Pri prvom volaní funkcie je prvým parametrom reťazec, ktorý je potrebné rozdeliť. Druhý parameter určuje reťazec oddeľovača. V nasledujúcich volaniach funkcie pre rovnaký reťazec musí byť prvý parameter NULL, pretože funkcia si už „pamätala“, s čím pracuje. Pozrime sa na príklad:

char str = "jeden, dva, tri, štyri, päť" ; char * sp; sp = strtok (str, ", " ) ; while (sp) ( vloží (sp); sp = strtok (NULL, ", " ) ; )

V dôsledku vykonania tohto kódu sa na obrazovke v stĺpci zobrazia nasledujúce slová:

Jeden dva tri štyri päť

Pri prvom volaní strtok() je funkcii odovzdaný ukazovateľ na prvý znak poľa a oddeľovací reťazec. Po tomto volaní sa pole str zmení, zostane v ňom len slovo „one“ a funkcia vráti aj pointer na toto slovo, ktorý je priradený sp.

Aj keď sme pri volaní funkcie stratili zvyšok poľa, vo vnútri strtok() je uložený ukazovateľ na zvyšok poľa. Keď prejde NULL, funkcia „vie“ pracovať s týmto „chvostom“.

Kopírovanie častí reťazcov

Keď jednoducho potrebujete spojiť dva reťazce, problém sa dá ľahko vyriešiť zavolaním funkcie strcat(), ktorá pripojí druhý na koniec prvého argumentu. Podobná funkcia strncat() pripája n znakov druhého reťazca k prvému. n je špecifikovaný ako tretí parameter.

Čo ak je situácia zložitejšia? Napríklad, existujú dva neprázdne riadky a musíte spojiť začiatok prvého a koniec druhého. Dá sa to urobiť pomocou funkcie strcpy(), ak neodovzdáte odkazy na prvé znaky riadkov:

char s1[ 20 ] = "Peter Smith", s2 = "Julia Roberts" ; strcpy (s1+ 5 , s2+ 5 ); kladie (s1) ;

V tomto prípade sa na obrazovke zobrazí „Peter Roberts“. Prečo sa to stalo? Ukazovateľ na šiesty znak prvého riadku bol odovzdaný funkcii strcpy(). To viedlo k tomu, že pri kopírovaní sa znaky tohto riadku prepisujú až od 6., pretože strcpy() „nevie“ nič o predchádzajúcich znakoch. Iba časť reťazca sa odovzdá aj ako druhý argument, ktorý sa skopíruje do prvého.

Ako vložiť jeden riadok do stredu druhého? Tento problém môžete vyriešiť použitím tretieho „bufferového“ riadku, kde môžete najskôr skopírovať prvý riadok, potom druhý, vymazať koniec prvého riadku a potom pridať koniec prvého. Môžete však urobiť aj toto:

char s1[ 20 ] = "jedna tri" , s2[ 20 ] = "dva" ; strcpy (s2+ 3, s1+ 3); strcpy (s1+ 4, s2); kladie (s1) ;

Tu sa najskôr skopíruje koniec prvého do druhého riadku, výsledkom čoho sú „dva tri“. Potom sa druhý riadok skopíruje do prvého riadku, pričom sa obíde jeho začiatok.

Popis niektorých funkcií pre prácu s reťazcami

Cvičenie
Nižšie sú uvedené popisy niektorých funkcií, ktoré vykonávajú operácie s reťazcami. Navrhnite a napíšte malé programy na ilustráciu toho, ako tieto funkcie fungujú.

  • char *strchr (const char *, int c) . Vráti ukazovateľ na prvý výskyt znaku c v reťazci. Vráti NULL, ak v reťazci takýto znak nie je.
  • char *strstr (const char *s2, const char *s1) . Vráti ukazovateľ na prvý výskyt reťazca s1 v reťazci s2. Ak neexistujú žiadne zhody, vráti hodnotu NULL.
  • char *strncpy (char *, const char *, size_t n) . Skopíruje n znakov z druhého riadku do prvého.
  • size_t strspn (const char *, const char *) . Vráti dĺžku začiatku prvého reťazca, ktorý zahŕňa znaky, ktoré tvoria druhý reťazec.

char far * far _fstrtok(const char far *str1, const char far *str2)

Popis:

Funkcia strtok() vracia ukazovateľ na ďalší token v reťazci, na ktorý ukazuje str1. Znaky z reťazca, na ktorý ukazuje str2, sa používajú ako oddeľovače, ktoré definujú token. Ak sa token nenájde, vráti sa NULL.

Prvé volanie strtok() v skutočnosti používa str1 ako ukazovateľ. Nasledujúce volania používajú ako prvý argument hodnotu NULL. Týmto spôsobom je možné celý reťazec rozdeliť na žetóny.

Je dôležité pochopiť, že funkcia strtok() upravuje reťazec, na ktorý ukazuje str1. Pri každom nájdení tokenu sa na miesto, kde sa našiel oddeľovač, umiestni nulový znak. Takže strtok() postupuje pozdĺž čiary.

Každé volanie strtok() vám umožňuje meniť množinu oddeľovačov.

Funkcia _fstrtok() je FAR verzia príslušnej funkcie.

Nasledujúci program tokenizuje reťazec „Letný vojak, slnečný patriot“ pomocou medzier a čiarok ako oddeľovačov. V dôsledku činnosti programu sa vygeneruje nasledujúci riadok: „The | leto | vojak | | slniečko | patriot."
#include
#include
int main (void)
{
char * p;
p = strtok ( "Letný vojak, slnečný patriot", " " ) ;
printf(p);
robiť (
p= strtok(" \0 " , ", " ) ;
if (p) printf ("|% s" , p) ;
) zatiaľ čo (p) ;
návrat 0;
}



Súvisiace publikácie