strtok функции. Опис на функциите на јазикот C. Опис на некои функции за работа со жици

4 одговори

Две работи што треба да знаете за strtok. Како што споменавме, „ја одржува внатрешната состојба“. Покрај тоа, тој ја збрка линијата што ја храниш. Во суштина, ќе напише „\0“ каде што ќе го најде токенот што го дадовте и ќе врати покажувач на почетокот на линијата. Внатрешно ја одржува локацијата на последниот токен; и следниот пат кога ќе го повикате, ќе започне од таму.

Важна последица е тоа што не можете да користите strtok на низа како const char* „здраво свето“; бидејќи ќе добиете прекршување на пристапот при менување на содржината на низата const char*.

„Добрата работа“ за strtok е што тој всушност не копира низи, така што не мора да управувате со дополнителна распределба на меморија итн. Но, ако не го разбирате горенаведеното, ќе имате проблем да го користите.

Пример. Ако имате „ова, е, низа“, последователните повици до strtok ќе генерираат покажувачи како овој (вредноста на ^ е повратната вредност). Забележете дека „\0“ се додава таму каде што се наоѓаат токените; тоа значи дека оригиналната линија е изменета:

T h i s , i s , a , s t r i n g \0 ова, е, а, низа t h i s \0 i s , a , s t r i n g \0 ова ^ t h i s \0 i s \0 a , s t r i n g \0 е ^ \ 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 низа ^

Се надевам дека ова има смисла.

Функцијата strtok() складира податоци помеѓу повиците. Ги користи овие податоци кога ги повикувате со NULL покажувач.

Точката во која е пронајден последниот токен се зачувува внатрешно со функција која ќе се користи при следниот повик (не е потребна специфична имплементација на библиотеката за да се спречат неуспесите на податоците).

strtok одржува внатрешна состојба. Кога ќе го повикате со не-NULL, тој се реиницијализира за да ја користи низата што ја давате. Кога ќе го повикате со NULL, тој ја користи таа низа и која било друга состојба што моментално ја има за да го врати следниот токен.

Поради начинот на кој работи strtok, треба да се погрижите да се поврзете со верзијата со повеќе нишки на C runtime ако пишувате апликација со повеќе нишки. Ова осигурува дека секоја нишка добива своја внатрешна состојба за strtok.

Функцијата strtok складира податоци во внатрешна статичка променлива која се дели меѓу сите нишки.

За безбедност на конецот треба да користите strtok_r

Погледнете го статичниот знак *last;

Char * strtok(s, delim) register char *s; регистар const char *delim; ( регистрирај char *spanp; регистрирај int c, sc; char *tok; статичен знак *последен; ако (s == NULL && (s = последен) == NULL) врати (NULL); /* * Прескокни (распон) водечки разграничувачи (s += strspn(s, delim), сортирање == sc) ако (c == 0) ( /* нема знаци кои не се разграничуваат */ last = NULL); . )делим (ако ((sc = *spanp++) == в) (ако (c == 0) s = NULL; друго s[-1] = 0; последно = s; врати (ток); ) ) додека (sc != 0 ) /* NOTRACHED */ )

споделување

1) Го наоѓа следниот токен во низата со нула-завршена бајти кон која покажува str. Карактерите за разграничување се идентификуваат со низата од нула бајти кон која е посочена делим.

Оваа функција се нарекува повеќекратно множење за да се добијат последователни токени од истата низа.

  • Ако ул! = NULL ул! = NULL, повикот се третира како прв повик до strtok за тој конкретен ред. Функцијата го бара првиот знак што Несодржани во делим.
  • Ако таков симбол не е пронајден, тогаш во него нема токени, а функцијата враќа нула покажувач.
  • Ако се најде таков симбол, ќе биде почеток на токен. Функцијата потоа го бара од таа точка првиот знак што е содржан во делим.
    • Ако не се најде таков знак, str има само еден токен, а идните повици до strtok враќаат нула покажувач
    • Ако се најде таков симбол, тоа заменетнултиот знак „\0“ и покажувачот кон следниот знак се зачувани на статична локација за последователни повици.
  • Функцијата потоа враќа покажувач на почетокот на токенот
  • Ако str == NULL , повикот се третира како последователни повици до strtok: функцијата продолжува од местото каде што замина во претходниот повик. Однесувањето е исто како претходно зачуваниот покажувач да е пренесен како str .

Однесувањето е недефинирано, освен ако str или delim не е покажувач на низа од бајти со нула завршница.

2) Исто како (1) освен што секој чекор го запишува бројот на знаци што остануваат да се видат во str до *strmax и ја запишува внатрешната состојба на токенизаторот на *ptr. Повторените повици (со нула strmax) мора да поминат strmax и ptr со вредностите зачувани од претходниот повик. Дополнително, следните грешки се среќаваат при извршување и тековно инсталираната функција за управувач со ограничувања се повикува без да се складира ништо во објектот на кој е посочен со ptr

  • strmax , delim или ptr - null покажувач
  • во случај на не-почетен повик (со null str), *ptr - нула покажувач
  • при првиот повик *strmax е нула или поголем од RSIZE_MAX
  • пребарувањето на крајот на токенот го достигнува крајот на оригиналната низа (мерено со почетната вредност *strmax)) без да се сретне со нула терминатор

Однесувањето е недефинирано ако и str покажува на низа со знаци што нема нула знак и strmax покажува на вредност што е поголема од големината на таа низа знаци. Како и сите функции поврзани со граници, strtok_s е загарантирана да биде достапна само ако __STDC_LIB_EXT1__ е дефинирана со имплементација, и ако корисникот дефинира __STDC_WANT_LIB_EXT1__ за целобројната константа 1 пред да го вклучи string.h .

опции

Повратна вредност

Враќа покажувач на почетокот на следниот токен или NULL ако нема повеќе токени.

Белешката

Оваа функција е деструктивна: пишува „\0“ знаци во елементите на низата str . Конкретно, стринг буквално не може да се користи како прв аргумент за strtok .

Секој повик до strtok менува статичка променлива: таа не е безбедна за нишки.

За разлика од повеќето други токенизатори, разграничувачите на strtok може да бидат различни за секој следен токен и дури може да зависат од содржината на претходните токени.

Функцијата strtok_s се разликува од функцијата POSIX strtok_r по тоа што е зачувана надвор од токенизираната низа и проверува за ограничувања на времето на работа.

пример

#дефинирај __STDC_WANT_LIB_EXT1__ 1 #вклучи #вклучи int main(void) ( char влез = „Птица слезе по прошетката“; printf(„Парсирање на влезната низа „%s“\n“, влез); char *token = strtok(влез, „ "); додека( токен) ( puts(token); token = strtok(NULL, " "); ) printf("Содржина на влезната низа сега: ""); for(size_t n = 0; n< sizeof input; ++n) input[n] ? printf("%c", input[n]) : printf("\\0"); puts("""); #ifdef __STDC_LIB_EXT1__ char str = "A bird came down the walk"; rsize_t strmax = sizeof str; const char *delim = " "; char *next_token; printf("Parsing the input string "%s"\n", str); token = strtok_s(str, &strmax, delim, &next_token); while(token) { puts(token); token = strtok_s(NULL, &strmax, delim, &next_token); } printf("Contents of the input string now: ""); for(size_t n = 0; n < sizeof str; ++n) str[n] ? printf("%c", str[n]) : printf("\\0"); puts("""); #endif }

Можен излез:

Парсирање на влезната низа „Птица се спушти на прошетка“ А птица се симна на прошетка Содржина на влезната низа сега: „A\0bird\0came\0down\0the\walk\0“ Парсирање на влезната низа „Птица падна на пешачење“ А птица се спушти на прошетка Содржина на влезната низа сега: „A\0bird\0came\0down\0the\walk\0“

  • C11 (ISO/IEC 9899:2011):
    • 7.24.5.8 Функција strtok (стр: 369-370)
    • K.3.7.3.1 Функција strtok_s (стр: 620-621)
  • C99 (ISO/IEC 9899:1999):
    • 7.21.5.8 Функција strtok (стр: 332-333)
  • C89/C90 (ISO/IEC 9899:1990):
    • 4.11.5.8 Функција strtok
ја наоѓа првата локација на кој било знак во една линија, во друга линија
(функција)

само знаци кои не се пронајдени во друга низа од бајти
(функција)
ја враќа должината на максималниот стартен сегмент, кој се состои од
само знаци кои се наоѓаат во друга низа од бајти
(функција)

(C95) (C11)

го наоѓа следниот знак во широка низа
(функција)
C++ документацијаза Стрток

Други алијас

Стрток

ПРЕГЛЕД

#вклучи

char *strtok(char *ул, const char *делим);
char *strtok_r(char *ул, const char *делим, знак**saveptr);

Барања за макрото за тестирање на имотот за glibc (види функција_тест_макроа(7)):

strtok_r(): _SVID_SOURCE || _BSD_ИЗВОР || _POSIX_C_SOURCE >= 1 || _XOPEN_ИЗВОР || _POSIX_ИЗВОР

ОПИС

Функција Стрток() разделува низа во низа од нула или повеќе непразни токени. На првиот повик Стрток() анализираната низа мора да биде наведена во аргументот ул. Во секој следен повик што ја анализира истата низа, вредноста улмора да биде NULL.

Во расправија делимодредено е множество бајти кои се сметаат за раздвојувачи на токени во анализираната низа. Повикувачот може да наведе различни линии во делимво следните повици при парсирање на истата низа.

Секој повик Стрток() враќа покажувач на низа со нула-завршена низа што го содржи следниот токен. Оваа линија не вклучува бајт за разграничување. Ако нема повеќе токени, тогаш Стрток() враќа NULL.

Секвенца на повици Стрток(), кои работат на една низа, одржува покажувач кој ја одредува точката во која започнува пребарувањето за следниот токен. Првиот повик Стрток() му доделува на овој покажувач референца на првиот бајт од низата. Почетокот на следниот токен се одредува со пребарување напред внатре улследниот бајт не е разграничувач. Ако се најде бајт, тој се зема како почеток на следниот токен. Ако не се најде таков бајт, тогаш нема повеќе токени и Стрток() враќа NULL (за празна или ограничена низа, во кој случај NULL ќе се врати првиот пат кога ќе се повика Стрток()).

Крајот на секој токен се наоѓа со пребарување напред додека не се најде бајт за разграничување или последен нула бајт („\0“). Ако се најде разграничен бајт, тој се заменува со нула бајт за да се прекине тековниот токен, и Стрток() складира покажувач до следниот бајт; овој покажувач ќе се користи како почетна точка при пребарување на следниот токен. Во овој случај Стрток() враќа покажувач на почетокот на пронајдениот токен.

Од описот погоре, следува дека низа од два или повеќе соседни разграничувачки бајти во линијата што се скенира се смета за единечен разграничувач, а разграничувачките бајти на почетокот или крајот на низата се игнорираат. Со други зборови, жетоните се вратија Стрток() - секогаш непразни низи. Тоа е, на пример, ако има линија " ааа;;ббб,“, потоа последователни повици Стрток() со дадени сепаратори на линии " ;, „Би ги вратил жиците“ ааа"И" ббб“ и потоа нула покажувач.

Функција strtok_r() е верзијата за повторно влегување Стрток(). Аргумент saveptrе покажувач на променлива знак *што се користи внатрешно strtok_r() да се земе предвид контекстот помеѓу последователните повици при парсирање на истата низа.

На првиот повик strtok_r() значење улмора да укаже на низата што се анализира и вредноста saveptrигнорирани. На следните повици вредноста улмора да биде NULL и вредноста saveptrне треба да се менува од претходниот повик.

Различни редови може да се анализираат истовремено низ повеќекратни работи strtok_r() со различни аргументи saveptr.

ПОВРАТНА ВРЕДНОСТ

Функции Стрток() И strtok_r() вратете покажувач на следниот токен или NULL ако нема повеќе токени.

АТРИБУТИ

За опис на термините во овој дел, видете атрибути(7).
Интерфејс Атрибут Значење
Стрток() безопасност во нишкитенебезбедна (MT-Небезбедна трка:strtok)
strtok_r() безопасност во нишкитебезопасен (MT-Safe)

УСОГЛАСУВАЊЕ

Стрток() POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD. strtok_r() POSIX.1-2001, POSIX.1-2008.

ДЕФЕКТИ

Користете ги овие карактеристики со претпазливост. Ве молиме имајте предвид дека: * Овие функции го менуваат нивниот прв аргумент. * Овие функции не можат да се користат со константни низи. * Идентитетот на бајтот на сепараторот е изгубен. * При анализа на функцијата Стрток() користи статички бафер и затоа не е безбеден за нишки. Користете strtok_r() во овој случај.

ПРИМЕР

Програмата подолу користи вгнездени јамки за повикување strtok_r() да се подели низа на нејзините составни токени. Во првиот параметар командна линијасе одредува низата што треба да се анализира. Вториот параметар го одредува бајтот(ите) на сепараторот, кој се користи за делење на низата на „композитни“ токени. Третиот параметар го одредува бајтот(ите) на сепараторот, кој се користи за одделување на „композитните“ токени во подтокени.

Пример за излез од програмата:

$./a.out "a/bbb///cc;xxx:yyyy:" ":;" "/" 1: a/bbb///cc --> a --> bbb --> cc 2: xxx --> xxx 3: yyy --> yyy

Изворниот код на програмата

#вклучи #вклучи #вклучи int main(int argc, char *argv) (char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc != 4) ( fprintf(stderr, "Употреба: % s стринг delim subdelim\n", argv); излез (EXIT_FAILURE); ) за (j = 1, str1 = argv; ; j++, str1 = NULL) (токен = strtok_r(str1, argv, &saveptr1); ако (токен = = NULL) прекини ("%d: %s\n", j, токен за (str2 = токен; str2 = NULL) (подтокен = strtok_r(str2, argv, &saveptr2); ако (подтокен ==); NULL) прекини (" --> %s\n", подтокен) ) излез (EXIT_SUCCESS)

Друг пример на програма која користи Стрток(), може да се најде во getaddrinfo_a(3).

Програмските јазици може да вклучуваат специјални функцииза работа со стрингови, со што се ослободува програмерот од потребата да напише свои функции за обработка на низи. На пример, честопати треба да ја одредите должината на низата и затоа јазиците обезбедуваат функција што ја мери нејзината должина.

Во програмскиот јазик C, функциите за работа со стрингови се декларирани во заглавието на датотеката string.h, што мора да запомните да го вклучите во вашиот изворен код. Има околу дваесет функции за работа со жици. Меѓу нив има и такви кои бараат знаци во низа, функции за споредба, низи за копирање, како и поспецифични. Список и опис на повеќето постоечки овој моментфункциите во јазикот C може да се најдат во додатокот на книгата од B. Kernighan, D. Ritchie „The C Programming Language“.

Сите функции декларирани во string.h, за време на нивната работа, можат да променат или да не променат една од низите поминати од покажувачот. Тоа зависи од целта на функцијата. Сепак, повеќето од нив враќаат нешто: или покажувач на знак или цел број. Освен тоа, ако функцијата промени еден од нејзините параметри и е повикана за таа цел, тогаш она што го враќа може да се игнорира (т.е. да не се додели на ништо во функцијата за повикување).

На пример, функцијата strcpy() ја има следната декларација: char *strcpy (char *, const char*) . Ја копира низата на која покажува вториот параметар во низата кон која покажува првиот параметар. Така се менува првиот параметар. Дополнително, функцијата враќа покажувач на првиот знак од низата:

знак s1[10], s2[10]; char * s3; s3 = s2; добива(s1); s3 = strcpy(s2, s1); става (s2) ; става (s3) ; printf(„%p, %p \n", s2, s3);

Овде s2 и s3 укажуваат на истиот симбол (printf() ги дава истите адреси). Сепак, она што го враќа strcpy() не може да се додели на низа. Резултатот од оваа функција обично не се доделува на ништо; Некогаш е доволно едноставно да смени една од низите поминати од покажувачот.

Друга работа се функциите како strlen() или strcmp() , кои не ги менуваат параметрите, туку се повикуваат заради резултатот. Функцијата strcmp() споредува две низа аргументи буква по буква (лексикографски) и враќа 0, -1 или 1. На пример, повикувањето strcmp („boy“, „body“) ќе врати 1 затоа што шифрата на буквата „y“ е поголема од буквата „d“. Повикувањето на strcmp("body", "boy") ќе се врати -1 затоа што првиот аргумент е лексикографски помал од вториот.

функција strtok()

Со користење на strtok функции() можете да поделите низа на посебни делови (токени). Декларацијата на оваа функција изгледа вака: char *strtok (char *, const char *) . Кога функцијата се повикува за прв пат, првиот параметар е низата што треба да се подели. Вториот параметар ја одредува низата на сепараторот. Во следните повици до функцијата за истата низа, првиот параметар мора да биде NULL, бидејќи функцијата веќе „се сети“ со што работи. Ајде да погледнеме на пример:

char str = "еден, два, три, четири, пет" ; char * sp; sp = strtok (str, ", " ); додека (sp) ( става (sp); sp = strtok (NULL, ", ") ;)

Како резултат на извршувањето на овој код, следните зборови се прикажуваат на екранот во колона:

Еден два три четири пет

Првиот пат кога ќе се повика strtok(), на функцијата се пренесува покажувач кон првиот знак од низата и низа за разграничување. По овој повик, низата str се менува, во неа останува само зборот „one“, а функцијата враќа и покажувач на овој збор, кој е доделен на sp.

Иако го изгубивме остатокот од низата во функцијата за повикување, покажувачот кон остатокот од низата е зачуван во strtok(). Кога ќе се помине NULL, функцијата „знае“ да работи со оваа „опашка“.

Копирање на делови од жици

Кога само треба да споите две низи, проблемот лесно се решава со повикување на функцијата strcat(), која ја додава втората на крајот од првиот аргумент. Слична функција, strncat(), додава n знаци од втората низа на првата. n е наведен како трет параметар.

Што ако ситуацијата е посложена? На пример, има две непразни линии и треба да го поврзете почетокот на првата и крајот на втората. Ова може да се направи со помош на функцијата strcpy(), ако ги пренесувате референците не на првите знаци од линиите:

char s1[ 20 ] = „Питер Смит“ , s2 = „Џулија Робертс“ ; strcpy (s1+ 5, s2+ 5); става (s1) ;

Во овој случај, на екранот ќе се прикаже „Питер Робертс“. Зошто се случи тоа? Покажувач до шестиот знак од првата линија беше предаден на функцијата strcpy(). Ова доведе до фактот дека при копирање, знаците од овој ред се препишуваат само почнувајќи од 6-ти, бидејќи strcpy() не „знае“ ништо за претходните знаци. Само дел од низата се пренесува и како втор аргумент, кој се копира на првиот.

Како да вметнете една линија во средината на друга? Можете да го решите овој проблем со користење на трета „тампон“ линија, каде што можете прво да ја копирате првата линија, потоа втората, бришејќи го крајот на првата, а потоа додајте го крајот на првата. Но, исто така можете да го направите ова:

char s1[ 20 ] = "еден три" , s2[ 20 ] = "два" ; strcpy (s2+ 3, s1+ 3); strcpy (s1+ 4, s2); става (s1) ;

Овде, прво крајот на првиот се копира во вториот ред, што резултира со „два три“. Потоа втората линија се копира во првата линија, заобиколувајќи го нејзиниот почеток.

Опис на некои функции за работа со жици

Вежбајте
Подолу се дадени описи на некои функции кои вршат операции на жици. Дизајнирајте и напишете мали програми за да илустрирате како функционираат овие функции.

  • char *strchr (const char *, int c) . Враќа покажувач на првото појавување на знакот c во низата. Враќа NULL ако нема таков знак во низата.
  • char *strstr (const char *s2, const char *s1) . Враќа покажувач на првата појава на низата s1 во низата s2. Ако нема совпаѓања, враќа NULL.
  • char *strncpy (char *, const char *, size_t n) . Копира n знаци од вториот ред во првиот.
  • size_t strspn (const char *, const char *) . Ја враќа должината на почетокот на првата низа, која ги вклучува знаците што ја сочинуваат втората низа.

Опис

Функцијата strtok бара токени во низата низа. Секвенца од повици до оваа функција ја дели низата на токени, кои се низи од знаци одделени со разграничувачки знаци.

На првиот повик, функцијата зема низа како аргумент, чиј прв знак се користи како почетна точка за пребарување на токени. На следните повици, функцијата чека нула покажувач и ја користи позицијата веднаш по завршувањето на последниот токен како нова локација за скенирање.

За да се одреди почетокот на токен, функцијата прво ги одредува знаците што не се содржани во низата делим, односно тие се разграничувачки знаци. И потоа го проверува остатокот од низата карактер по знак до првиот разграничувачки знак, кој го сигнализира крајот на токенот.

Овој последен токен автоматски се заменува со нула знак, а токенот се враќа од функцијата. После ова, следните повици до функцијата strtok започнуваат со овој нула знак.

Опции:

  • низа
    Низа за пребарување на лексеми во. Содржината на овој стринг ќе се смени, ќе биде поделена на помали низи (токени). Овој параметар може да содржинула покажувач, во кој случај функцијата продолжува со скенирање од местото каде што престана претходниот успешен повик на функцијата.
  • делим
    Низа што содржи разграничувачи. Тие може да варираат од еден функциски повик до друг функциски повик.

Повратна вредност

Покажувач кон последниот токен пронајден во низата.
Нулта покажувач се враќа ако не се најдат токени.

Пример: изворен код на програмата

//пример за користење на функцијата strtok #include #вклучи int main () ( char str = "Карактеристики на националниот риболов - игран, комедијален филм."; std::cout<< "Разделение строки "" << str << "" на лексемы:n"; char * pch = strtok (str," ,.-"); // во втором параметре указаны разделитель (пробел, запятая, точка, тире) while (pch != NULL) // пока есть лексемы { std::cout << pch << "n"; pch = strtok (NULL, " ,.-"); } return 0; }


Врв