Windows.  Virus.  Anteckningsböcker.  Internet.  kontor.  Verktyg.  Förare

#omfatta char *strtok(char * str1, konst char * str2);

Strtok()-funktionen returnerar en pekare till nästa token i strängen som parametern pekar på. str1. Tecknen som utgör strängen som adresseras av parametern str2, är avgränsare som definierar en token. Om det inte finns någon token att returnera, returneras en nollpekare.

I C99-versionen, parametrarna str1 Och str2 begränsningskvalificeringen tillämpas.

För att dela en sträng i tokens, första gången funktionen strtok() anropas, parametern str1 måste peka på början av denna rad. Vid efterföljande funktionsanrop som parameter str1 en nollpekare måste användas. På detta sätt tokeniseras hela strängen.

Varje anrop till strtok()-funktionen kan använda en annan uppsättning avgränsare.

Exempel

Detta program bryter strängen "Gräset är grönt, solen skiner" till symboler åtskilda av mellanslag och kommatecken. Resultatet blir

Gräs|Grönt|Solsken|Skinner #inkludera #omfatta int main(void) ( char *p; p = strtok("Gräset är grönt, solen skiner", " "); printf(p); do ( p = strtok("\0", ", ") ; if(p ) printf("|%s", p); ) while(p); return 0; )

Programmeringsspråk kan inkludera speciella funktioner att arbeta med strängar, och därmed rädda programmeraren från att behöva skriva sina egna strängbearbetningsfunktioner. Till exempel är det ofta nödvändigt att bestämma längden på en sträng, och så tillhandahåller språk en funktion för att mäta 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 är de som söker efter tecken i en sträng, jämförelsefunktioner, strängkopiering, såväl som mer specifika. Lista och beskrivning av de flesta befintliga det här ögonblicket i C-språket finns funktioner i bilagan till boken av B. Kernighan, D. Ritchie "The C Programming Language. Second Edition".

Alla funktioner som deklareras i string.h kan eventuellt modifiera en av strängarna som skickas av pekaren under arbetets gång. 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 funktionen ändrar en av sina parametrar och anropades för detta, kan det som den returnerar ignoreras (det vill säga 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å. Så den första parametern ändras. 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 tecken (printf() matar ut samma adress). 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 de två argumentsträngarna bokstav för bokstav (lexikografiskt) och returnerar 0, -1 eller 1. Om du till exempel anropar strcmp("boy", "body") returneras 1 eftersom bokstavskod "y" mer än ett brev"d". Att anropa strcmp("body", "boy") kommer att returnera -1, eftersom det första argumentet är lexikografiskt mindre än det andra.

strtok() funktion

Med funktionen strtok() kan du dela upp en sträng i separata delar (tokens). Deklarationen av denna funktion ser ut så här char *strtok (char *, const char *) . Första gången funktionen anropas är den första parametern strängen som ska delas. Den andra parametern anger avgränsningssträngen. Vid efterföljande funktionsanrop för samma rad måste den första parametern vara NULL, eftersom funktionen har redan "kommit ihåg" vad den fungerar med. Tänk på ett exempel:

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

Som ett resultat av att köra denna kod visas följande ord i en kolumn:

ett två tre Fyra Fem

Första gången strtok() anropas skickas funktionen en pekare till det första tecknet i arrayen och en avgränsningssträng. Efter detta anrop ändras arrayen 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 förlorat resten av arrayen i den anropande funktionen, finns en pekare till resten av arrayen kvar inuti strtok(). När NULL har passerats, "vet" funktionen att fungera med den svansen.

Kopiera delar av strängar

När du bara behöver sammanfoga två strängar löses problemet enkelt genom att anropa funktionen strcat() som lägger till det andra i slutet av det första argumentet. En liknande funktion, strncat(), lägger till n tecken från 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. Du kan göra detta med funktionen strcpy() om du skickar referenser som inte är de första tecknen i strängar:

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

I det här fallet"Peter Roberts" kommer att visas på skärmen. Varför hände det? En pekare till det sjätte tecknet i den första strängen skickades till strcpy()-funktionen. Detta ledde till att vid kopiering skrivs tecknen i denna sträng ö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 mitt i en annan? Du kan lösa det här problemet med den tredje "buffertraden", där du först kan kopiera den första raden, sedan den andra, skriva över slutet av den första och sedan bifoga 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, det visar sig "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 av den andra strängen 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.

Syntax:

#omfatta
char *strtok(char *str, const char *sep);

Argument:

str är en pekare till strängen som ska delas.
sep är en pekare till en sträng som innehåller en uppsättning avgränsare.

Returvärde:

NULL - om strängen str inte kan delas upp i delar.
Pekare till det första tecknet i den valda delen av strängen.

Beskrivning:

Strtok-funktionen extraherar nästa del av strängen som str-argumentet pekar på, separerad av ett av avgränsningstecknen som anges i strängen som pekas på av sep-argumentet. Ett successivt anrop till strtok-funktionen resulterar i att strängen str delas upp i delar (tokens).

"Det första anropet till strtok-funktionen anger början av en sträng som ska separeras (str) och början av en sträng som innehåller avgränsare (sep). I början slagfunktion itererar genom tecknen i strängen str en efter en och letar efter ett tecken som inte finns i avgränsningssträngen sep. Om i strängen str linjeslutstecknet påträffas innan ett tecken som inte ingår i strängen sep hittades, kan strängen str inte delas upp i delar och en nollpekare (NULL) returneras. Om en sådan karaktär hittas, anses den vara början på den första delen av str."

Därefter letar strtok-funktionen efter avgränsaren, det vill säga tecknet som ingår i strängen sep. Om inget sådant tecken hittas, anses strängen str vara en del, och efterföljande uppdelningar av strängen str kommer att returnera en nollpekare. Om en sådan karaktär hittas. sedan ersätts det med ett nolltecken (radslutstecken). Därefter kommer strtok-funktionen ihåg den aktuella positionen (en pekare till tecknet från vilket sökningen efter nästa del av strängen kommer att börja) och returnerar en pekare till början av den först valda delen av strängen.

Om strtok-funktionen returnerade en icke-null-pekare kan du fortsätta dela upp str i delar. För att fortsätta dela strängen anropas strtok-funktionen igen, men istället för en pekare till strängen som ska delas anges NULL som första augment. I det här fallet kommer strtok-funktionen att fortsätta dela från den minnesvärda adressen. Partitioneringsalgoritmen förblir densamma.

Exempel:

I exemplet delas strängen "test1/test2/test3/test4" upp i delar av separatorn "/" med hjälp av strtok-funktionen. Det delade resultatet skrivs ut på konsolen.

Resultat:

Konsolutgång:


4 svar

Två saker att veta om strtok. Som nämnts "upprätthåller det interna tillståndet". Dessutom har han förstörde raden du matar henne. I huvudsak kommer den att skriva "\0" där den hittar markören du angav och returnerar en pekare till början av strängen. 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 får en åtkomstöverträdelse 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 extra minnesallokering osv. Men om du inte förstår ovanstående kommer du att få problem med att använda det.

Exempel. Om du har "detta, är, sträng", kommer successiva anrop till strtok att generera pekare enligt följande (^-värdet är returvärdet). Observera att "\0" läggs till där tokens finns; detta betyder att den ursprungliga raden ändras:

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 i 0 är 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 med en funktion som ska användas vid nästa anrop (ingen specifik biblioteksimplementering krävs för att förhindra datakrascher).

strtok upprätthåller internt tillstånd. När du anropar den med 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 alla andra 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ådig 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), sorts).*/ forts: c = *s++; för (spanp = (char *)delim; (sc = *spanp++) != 0;) ( if (c) == sc) goto forts; ) if (c == 0) ( /* inga icke-avgränsande tecken */ sista = NULL; return (NULL); ) tok = s - 1; /* * Skanna token (sök efter avgränsare : s += strcspn(s, delim), typ). * Observera att delim måste ha en NUL; vi slutar om vi ser det också. */ för (;;) ( c = *s++; spanp = (char) *)delim; do ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; annars s[-1] = 0; last = s; return (tok); ) ) while (sc != 0); ) /* INTE NÅDD */ )

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 få på varandra följande 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 karaktär hittades kommer det att bli det token start. 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 karaktär hittades, det byts ut 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 där den slutade 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 kvar att slå upp i str till *strmax och skriver tokenizerns interna tillstånd till *ptr . Upprepade anrop (med null strmax) måste passera strmax och ptr med värdena som lagrats av föregående anrop. Dessutom, under körning, följande fel och den nuvarande kallas ställ in funktion begränsningshanterare utan att lagra något i objektet som pekas på av ptr

  • strmax , delim eller ptr - nollpekare
  • på ett icke initialt anrop (med en noll str), är *ptr en nollpekare
  • vid första samtalet är *strmax noll eller större än RSIZE_MAX
  • slutet av tokensökning når slutet av den ursprungliga strängen (mätt med det initiala *strmax-värdet) 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änskontrollrelaterade 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 inkluderas.

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 tecknen "\0" 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: inte trådsäker.

Till skillnad från de flesta andra tokenizers kan avgränsningarna i strtok 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 lagra den utanför den tokeniserade strängen och kontrollera körtidsgränser.

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 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 Strtok-funktionen (sid: 369-370)
    • K.3.7.3.1 strtok_s funktion (p: 620-621)
  • C99 (ISO/IEC 9899:1999):
    • 7.21.5.8 Strtok-funktionen (sid: 332-333)
  • C89/C90 (ISO/IEC 9899:1990):
    • 4.11.5.8 strtok funktion
hittar den första platsen för ett tecken i en sträng, i en annan sträng
(fungera)

endast tecken som inte finns i en annan bytesträng
(fungera)
returnerar längden på det maximala initiala segmentet, 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

Om du upptäcker ett fel, välj en textbit och tryck på Ctrl + Retur
DELA MED SIG: