strtok funktioner. Beskrivning av C-språkets funktioner. Beskrivning av några funktioner för att arbeta med strängar

4 svar

Två saker att veta om strtok. Som nämnts "upprätthåller det interna tillståndet." Dessutom han förstörde linjen du matar den. I huvudsak kommer den att skriva "\0" där den hittar den token du angav och returnerar en pekare till början av raden. Internt bibehåller den platsen för den sista token; och nästa gång du ringer det börjar det därifrån.

En viktig konsekvens är att du inte kan använda strtok på en sträng som const char* "hello world"; eftersom du kommer att få ett åtkomstbrott när du ändrar innehållet i en const char*-sträng.

Det "bra" med strtok är att den faktiskt inte kopierar strängar, så du behöver inte hantera ytterligare minnesallokering etc. Men om du inte förstår ovanstående kommer du att få problem med att använda det.

Exempel. Om du har en "detta, är en sträng", kommer successiva anrop till strtok att generera pekare som denna (värdet på ^ är returvärdet). Observera att "\0" läggs till där tokens hittas; detta betyder att den ursprungliga raden har ändrats:

T h i s , i s , a , s t r i n g \0 detta,är,en,sträng t h i s \0 i s , a , s t r i n g \0 detta ^ t h i s \0 i s \0 a , s t r i n g \ s \ 0 i 0 är \ 0 i 0 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 string ^

Hoppas detta är vettigt.

Strtok()-funktionen lagrar data mellan anrop. Den använder denna data när du anropar den med en NULL-pekare.

Punkten där den senaste token hittades lagras internt av en funktion som kommer att användas vid nästa anrop (ingen specifik biblioteksimplementering krävs för att förhindra datafel).

strtok upprätthåller internt tillstånd. När du anropar den med en icke-NULL, återinitialiserar den sig själv för att använda strängen du anger. När du anropar den med NULL , använder den den strängen och vilket annat tillstånd den för närvarande har för att returnera nästa token.

På grund av hur strtok fungerar måste du se till att du länkar till den flertrådade versionen av C runtime om du skriver en flertrådad applikation. Detta säkerställer att varje tråd får sitt eget interna tillstånd för strtok .

Strtok-funktionen lagrar data i en intern statisk variabel som delas mellan alla trådar.

För trådsäkerhet bör du använda strtok_r

Ta en titt på statisk char *last;

Char * strtok(s, delim) register char *s; registrera const char *delim; (register char *spanp; register int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Hoppa över (span) ledande avgränsare (s += strspn(s, delim), sort of == sc) goto cont ) if (c == 0) ( /* inga icke-avgränsande tecken */ last = NULL); ) tok = s - 1; /* * Scan token (sök efter avgränsare: s += strcspn(s, delim), typ * Observera att delim måste ha en NUL, vi slutar också. )delim; do ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; annars s[-1] = 0; last = s; return (tok); ) ) medan (sc != 0 ) /* NOTEACHED */ )

dela med sig

1) Hittar nästa token i den nollterminerade bytesträngen som pekas på av str . Avgränsningstecken identifieras av nollbytesträngen som pekas på av delim .

Denna funktion kallas multipel multiplikation för att erhålla successiva tokens från samma sträng.

  • Om str! = NULL str! = NULL , anropet behandlas som det första anropet till strtok för den specifika raden. Funktionen söker efter det första tecknet som Inte ingår i delim.
  • Om en sådan symbol inte hittades finns det inga symboler i den, och funktionen returnerar en nollpekare.
  • Om en sådan symbol hittades kommer den att bli det start av token. Funktionen söker sedan från den punkten efter det första tecknet som finns i delim .
    • Om inget sådant tecken hittas, har str bara en token, och framtida anrop till strtok returnerar en nollpekare
    • Om en sådan symbol hittas, den ersatt nolltecknet "\0" och pekaren till nästa tecken lagras på en statisk plats för efterföljande anrop.
  • Funktionen returnerar sedan en pekare till början av token
  • Om str == NULL behandlas anropet som efterföljande anrop till strtok: funktionen fortsätter från där den lämnades i föregående anrop. Beteendet är detsamma som om den tidigare lagrade pekaren skickades som str .

Beteendet är odefinierat om inte str eller delim är en pekare till en noll-terminerad bytesträng.

2) Samma som (1) förutom att varje steg skriver antalet tecken som återstår att se i str till *strmax och skriver tokenizerns interna tillstånd till *ptr . Upprepade samtal (med en noll strmax) måste passera strmax och ptr med de värden som lagrats av föregående samtal. Dessutom påträffas följande fel under körning och den för närvarande installerade begränsningshanterarfunktionen anropas utan att lagra något i objektet som pekas på av ptr

  • strmax , delim eller ptr - nollpekare
  • vid icke-initialanrop (med noll str), *ptr - nollpekare
  • vid första samtalet *strmax är noll eller större än RSIZE_MAX
  • sökning efter slutet av token når slutet av den ursprungliga strängen (mätt med det initiala värdet *strmax)) utan att stöta på en nollterminator

Beteendet är odefinierat om både str pekar på en teckenmatris som inte har ett nolltecken och strmax pekar på ett värde som är större än storleken på den teckenmatrisen. Liksom alla gränsrelaterade funktioner, garanteras strtok_s endast vara tillgänglig om __STDC_LIB_EXT1__ är implementeringsdefinierad, och om användaren definierar __STDC_WANT_LIB_EXT1__ för heltalskonstanten 1 innan string.h ingår.

alternativ

Returvärde

Returnerar en pekare till början av nästa token eller NULL om det inte finns fler tokens.

Anteckningen

Denna funktion är destruktiv: den skriver "\0"-tecken i elementen i strängen str . I synnerhet kan en bokstavlig sträng inte användas som det första argumentet till strtok .

Varje anrop till strtok modifierar en statisk variabel: den är inte trådsäker.

Till skillnad från de flesta andra tokenizers kan strtoks avgränsare vara olika för varje efterföljande token och kan till och med bero på innehållet i tidigare tokens.

Strtok_s-funktionen skiljer sig från POSIX strtok_r-funktionen genom att den lagras utanför den tokeniserade strängen och kontrollerar för körtidsbegränsningar.

exempel

#define __STDC_WANT_LIB_EXT1__ 1 #inkludera #omfatta int main(void) ( char input = "En fågel kom ner på promenaden"; printf("Parsar inmatningssträngen "%s"\n", input); char *token = strtok(input, " "); while( token) ( puts(token); token = strtok(NULL, " "); ) printf("Innehållet i inmatningssträngen nu: ""); 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 }

Möjlig utgång:

Parsar inmatningssträngen "En fågel kom ner på promenaden" En fågel kom ner för promenaden Innehållet i inmatningssträngen nu: "A\0fågel\0kom\0ned\0the\0walk\0" Parsar inmatningssträngen "En fågel kom ner den gå" En fågel kom ner på promenaden. Innehållet i inmatningssträngen nu: "En\0fågel\0kom\0ned\0den\0promenad\0"

  • C11 (ISO/IEC 9899:2011):
    • 7.24.5.8 Funktion strtok (p: 369-370)
    • K.3.7.3.1 Funktion strtok_s (p: 620-621)
  • C99 (ISO/IEC 9899:1999):
    • 7.21.5.8 Funktion strtok (sid: 332-333)
  • C89/C90 (ISO/IEC 9899:1990):
    • 4.11.5.8 strtok funktion
hittar den första platsen för ett tecken på en rad, på en annan rad
(fungera)

endast tecken som inte finns i en annan bytesträng
(fungera)
returnerar längden på det maximala startsegmentet, som består av
endast tecken som finns i en annan bytesträng
(fungera)

(C95) (C11)

hittar nästa pollett i en bred sträng
(fungera)
C++ dokumentation för strtok

Andra Alias

strtok

RECENSION

#omfatta

char *strtok(char *str, konst char *delim);
char *strtok_r(char *str, konst char *delim,röding**septr);

Krav för egenskapstestningsmakrot för glibc (se feature_test_macros(7)):

strtok_r(): _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

BESKRIVNING

Fungera strtok() delar upp en sträng i en sekvens med noll eller fler icke-tomma tokens. Vid första samtalet strtok() den analyserade strängen måste anges i argumentet str. I varje efterföljande anrop som analyserar samma sträng, värdet str måste vara NULL.

I argumentation delim en uppsättning byte specificeras som anses vara tokenseparatorer i den analyserade strängen. Den som ringer kan ange olika linjer i delim i efterföljande anrop när samma sträng analyseras.

Varje samtal strtok() returnerar en pekare till en noll-terminerad sträng som innehåller nästa token. Denna rad innehåller ingen avgränsningsbyte. Om det inte finns fler polletter, då strtok() returnerar NULL.

Samtalssekvens strtok(), som arbetar på en enda sträng, upprätthåller en pekare som anger punkten där sökningen efter nästa token börjar. Första samtalet strtok() tilldelar denna pekare en referens till den första byten i strängen. Starten på nästa token bestäms genom att söka framåt in str nästa byte är inte en avgränsare. Om en byte hittas tas den som början på nästa token. Om en sådan byte inte hittas finns det inga fler tokens och strtok() returnerar NULL (för en tom eller avgränsad sträng, i vilket fall kommer NULL att returneras första gången den anropas strtok()).

Slutet på varje token hittas genom en framåtsökning tills en avgränsningsbyte eller en avslutande nollbyte ("\0") hittas. Om en avgränsningsbyte hittas, ersätts den med en nollbyte för att avsluta den aktuella token, och strtok() lagrar en pekare till nästa byte; den här pekaren kommer att användas som utgångspunkt när du söker efter nästa token. I detta fall strtok() returnerar en pekare till början av den hittade token.

Av beskrivningen ovan följer att en sekvens av två eller flera sammanhängande avgränsningsbytes i raden som ska skannas betraktas som en enda avgränsare, och avgränsningsbytes i början eller slutet av strängen ignoreras. Med andra ord, polletterna återvände strtok() - alltid icke-tomma strängar. Det vill säga, till exempel, om det finns en linje " aaa;;bbb,", sedan efterföljande samtal strtok() med givna radavgränsare " ;, "skulle returnera strängarna" aaa"och" bbb" och sedan en nollpekare.

Fungera strtok_r() är den återkommande versionen strtok(). Argument septrär en pekare till en variabel röding* som används internt strtok_r() för att ta hänsyn till sammanhanget mellan efterföljande anrop vid analys av samma sträng.

Vid första samtalet strtok_r() betydelse str måste peka på strängen som analyseras och värdet septr ignoreras. Vid efterföljande samtal värdet str måste vara NULL och värdet septr bör inte ändras sedan föregående samtal.

Olika rader kan analyseras samtidigt över flera körningar strtok_r() med olika argument septr.

RETURVÄRDE

Funktioner strtok() Och strtok_r() returnera en pekare till nästa token eller NULL om det inte finns fler tokens.

ATTRIBUT

För en beskrivning av termerna i detta avsnitt, se attribut(7).
Gränssnitt Attribut Menande
strtok() ofarlighet i trådarosäker (MT-Unsafe race:strtok)
strtok_r() ofarlighet i trådarofarlig (MT-Safe)

EFTERLEVANDE

strtok() POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD. strtok_r() POSIX.1-2001, POSIX.1-2008.

DEFEKT

Använd dessa funktioner med försiktighet. Observera att: * Dessa funktioner ändrar sitt första argument. * Dessa funktioner kan inte användas med konstanta strängar. * Identiteten för separatorbyten går förlorad. * Vid analys av funktionen strtok() använder en statisk buffert och är därför inte trådsäker. Använda sig av strtok_r() I detta fall.

EXEMPEL

Programmet nedan använder kapslade loopar för att anropa strtok_r() för att dela en sträng i dess beståndsdelar. I den första parametern kommandorad strängen som ska analyseras anges. Den andra parametern specificerar separatorbyte(n), som används för att dela upp strängen i "sammansatta" tokens. Den tredje parametern anger avgränsningsbyte(n), som används för att separera "sammansatta" tokens i subtokens.

Exempel på programutgång:

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

Programkällkod

#omfatta #omfatta #omfatta int main(int argc, char *argv) ( char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc != 4) ( fprintf(stderr, "Användning: % s string delim subdelim\n", argv); exit(EXIT_FAILURE); ) för (j = 1, str1 = argv; ; j++, str1 = NULL) ( token = strtok_r(str1, argv, &saveptr1); if (token = = NULL) break; printf("%d: %s\n", j, token för (str2 = token; ; str2 = NULL) (subtoken = strtok_r(str2, argv, &saveptr2); if (subtoken ==); NULL) break printf(" --> %s\n", subtoken) ) exit(EXIT_SUCCESS)

Ett annat exempel på ett program som använder strtok(), finns i getaddriinfo_a(3).

Programmeringsspråk kan inkludera speciella funktioner för att arbeta med strängar, och därigenom befria programmeraren från behovet av att skriva sina egna strängbearbetningsfunktioner. Till exempel behöver du ofta bestämma längden på en sträng, och därför tillhandahåller språk en funktion som mäter dess längd.

I programmeringsspråket C deklareras funktioner för att arbeta med strängar i rubrikfilen string.h, som du måste komma ihåg att inkludera i din källkod. Det finns ett tjugotal funktioner för att arbeta med strängar. Bland dem finns de som söker efter tecken i en sträng, jämförelsefunktioner, kopieringssträngar, såväl som mer specifika. Lista och beskrivning av de flesta befintliga det här ögonblicket funktioner i C-språket finns i bilagan till boken av B. Kernighan, D. Ritchie "The C Programming Language".

Alla funktioner som deklareras i string.h, under deras drift, kan ändra eller inte ändra en av strängarna som skickas av pekaren. Det beror på syftet med funktionen. Men de flesta av dem returnerar något: antingen en pekare till ett tecken eller ett heltal. Dessutom, om en funktion ändrar en av sina parametrar och anropades för detta ändamål, kan det som den returnerar ignoreras (dvs. inte tilldelas någonting i den anropande funktionen).

Till exempel har funktionen strcpy() följande deklaration: char *strcpy (char *, const char*) . Den kopierar strängen som den andra parametern pekar på till strängen som den första parametern pekar på. Därmed ändras den första parametern. Dessutom returnerar funktionen en pekare till det första tecknet i strängen:

char s1[10], s2[10]; char * s3; s3 = s2; får(s1); s3 = strcpy(s2, s1); sätter (s2); sätter (s3) ; printf("%p, %p \n" s2, s3);

Här pekar s2 och s3 på samma symbol (printf() matar ut samma adresser). Det som strcpy() returnerar kan dock inte tilldelas en array. Resultatet av denna funktion är vanligtvis inte tilldelat någonting; Ibland räcker det att den helt enkelt ändrar en av strängarna som pekaren passerar.

En annan sak är funktioner som strlen() eller strcmp() , som inte ändrar parametrar, utan anropas för resultatets skull. Strcmp()-funktionen jämför två argumentsträngar bokstav för bokstav (lexikografiskt) och returnerar 0, -1 eller 1. Om du till exempel anropar strcmp("boy", "body") returneras 1 eftersom koden för bokstaven "y" är större än bokstaven "d". Att anropa strcmp("body", "boy") kommer att returnera -1 eftersom det första argumentet är lexikografiskt mindre än det andra.

funktion strtok()

Genom att använda strtok funktioner() du kan dela en sträng i separata delar (tokens). Deklarationen av denna funktion ser ut så här: char *strtok (char *, const char *) . När funktionen anropas för första gången är den första parametern strängen som måste delas. Den andra parametern anger separatorsträngen. I efterföljande anrop till funktionen för samma sträng måste den första parametern vara NULL, eftersom funktionen har redan "kommit ihåg" vad den fungerar med. Låt oss titta på ett exempel:

char str = "ett, två, tre, fyra, fem" ; char * sp; sp = strtok (str, "," ); while (sp) ( sätter (sp); sp = strtok (NULL, ", " ) ; )

Som ett resultat av att köra denna kod visas följande ord på skärmen i en kolumn:

Ett två tre Fyra Fem

Första gången strtok() anropas skickas en pekare till det första tecknet i arrayen och en avgränsningssträng till funktionen. Efter detta anrop ändras array str, bara ordet "one" finns kvar i den, och funktionen returnerar också en pekare till detta ord, som är tilldelad sp.

Även om vi har tappat resten av arrayen i den anropande funktionen, lagras en pekare till resten av arrayen inuti strtok(). När NULL har passerats, "vet" funktionen att fungera med denna "svans".

Kopiera delar av strängar

När du bara behöver sammanfoga två strängar löses problemet enkelt genom att anropa strcat()-funktionen, som lägger till det andra i slutet av det första argumentet. En liknande funktion, strncat(), lägger till n tecken i den andra strängen till den första. n anges som den tredje parametern.

Vad händer om situationen är mer komplex? Till exempel finns det två rader som inte är tomma och du måste ansluta början av den första och slutet av den andra. Detta kan göras med funktionen strcpy() om du skickar referenser som inte är de första tecknen i raderna:

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

I det här fallet kommer "Peter Roberts" att visas på skärmen. Varför hände det? En pekare till det sjätte tecknet i den första raden skickades till strcpy()-funktionen. Detta ledde till det faktum att vid kopiering skrivs tecknen i denna rad över först från och med den 6:e, eftersom strcpy() "vet" ingenting om tidigare tecken. Endast en del av strängen skickas också som det andra argumentet, som kopieras till det första.

Hur infogar man en rad i mitten av en annan? Du kan lösa detta problem genom att använda en tredje "buffert"-rad, där du först kan kopiera den första raden, sedan den andra, radera slutet av den första och sedan lägga till slutet av den första. Men du kan också göra detta:

char s1[ 20 ] = "en tre" , s2[ 20 ] = "två" ; strcpy (s2+3, s1+3); strcpy (s1+4, s2); sätter (s1);

Här kopieras först slutet av den första till den andra raden, vilket resulterar i "två tre". Sedan kopieras den andra raden till den första raden, utan dess början.

Beskrivning av några funktioner för att arbeta med strängar

Träning
Nedan finns beskrivningar av några funktioner som utför operationer på strängar. Designa och skriv små program som illustrerar hur dessa funktioner fungerar.

  • char *strchr (const char *, int c) . Returnerar en pekare till den första förekomsten av tecknet c i strängen. Returnerar NULL om det inte finns något sådant tecken i strängen.
  • char *strstr (konst char *s2, const char *s1) . Returnerar en pekare till den första förekomsten av sträng s1 i sträng s2. Om det inte finns några matchningar, returnerar NULL.
  • char *strncpy (char *, const char *, size_t n) . Kopierar n tecken från den andra raden till den första.
  • size_t strspn (konst char *, const char *) . Returnerar längden på början av den första strängen, som inkluderar tecknen som utgör den andra strängen.

Beskrivning

Strtok-funktionen söker efter tokens i strängsträngen. En sekvens av anrop till den här funktionen delar upp strängen i tokens, som är sekvenser av tecken separerade med avgränsare.

Vid det första anropet tar funktionen sträng som ett argument, vars första tecken används som utgångspunkt för sökning efter tokens. Vid efterföljande samtal väntar funktionen på en nollpekare och använder positionen omedelbart efter slutet av den sista token som den nya platsen att skanna.

För att bestämma början av en token bestämmer funktionen först de tecken som inte finns i strängen delim , det vill säga de är avgränsare. Och sedan kontrollerar den resten av strängen tecken för tecken tills det första avgränsningstecknet, vilket signalerar slutet på token.

Denna efterföljande token ersätts automatiskt med ett nolltecken, och token returneras av funktionen. Efter detta börjar efterföljande anrop till strtok-funktionen med detta nolltecken.

Alternativ:

  • sträng
    En sträng att söka efter lexem i. Innehållet i denna sträng kommer att ändras, den kommer att delas upp i mindre strängar (tokens). Denna parameter kan innehållanoll-pekare, i vilket fall funktionen fortsätter att skanna från där det tidigare framgångsrika funktionsanropet slutade.
  • delim
    En sträng som innehåller avgränsare. De kan variera från ett funktionsanrop till ett annat funktionsanrop.

Returvärde

En pekare till den sista token som hittades i strängen.
En nollpekare returneras om inga tokens hittas.

Exempel: programkällkod

//exempel på att använda strtok-funktionen #include #omfatta int main () ( char str = "Funktioner för nationellt fiske - långfilm, komedi."; std::cout<< "Разделение строки "" << str << "" на лексемы:n"; char * pch = strtok (str," ,.-"); // во втором параметре указаны разделитель (пробел, запятая, точка, тире) while (pch != NULL) // пока есть лексемы { std::cout << pch << "n"; pch = strtok (NULL, " ,.-"); } return 0; }


Topp