Ablakok.  Vírusok.  Jegyzetfüzetek.  Internet.  hivatal.  Segédprogramok.  Drivers

Egyéb Alias

strtok

FELÜLVIZSGÁLAT

#beleértve

char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char**saveptr);

Tulajdonságteszt makrókövetelmények a glibc-hez (lásd feature_test_macros(7)):

strtok_r(): _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_FORRÁS >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

LEÍRÁS

Funkció strtok() egy karakterláncot nulla vagy több nem üres token sorozatára bont. Első hívásra strtok() az elemzett karakterláncot meg kell adni az argumentumban str. Minden következő hívásban, amely ugyanazt a karakterláncot elemzi, az értéket str NULL-nak kell lennie.

Az érvelésben delim beállít egy bájtkészletet, amely token elválasztónak számít az elemzett karakterláncban. A hívó különböző karakterláncokat adhat meg delim a következő hívásokban ugyanazon karakterlánc elemzésekor.

Minden hívás strtok() egy mutatót ad vissza egy null-végű karakterláncra, amely a következő tokent tartalmazza. Ez a karakterlánc nem tartalmazza a határoló bájtot. Ha nincs több token, akkor strtok() NULL-t ad vissza.

Hívássorozat strtok() amelyek egyetlen karakterláncon működnek, egy mutatót tartanak fenn, amely meghatározza azt a pontot, ahol a következő token keresését kell kezdeni. Első hívás strtok() ehhez a mutatóhoz hivatkozást rendel a karakterlánc első bájtjához. A következő token kezdetét az előre keresés határozza meg str a következő bájt nem határoló. Ha talál egy bájtot, akkor azt a következő token kezdeteként veszi. Ha nem található ilyen bájt, akkor nincs több token és strtok() NULL-t ad vissza (üres karakterlánc esetén, vagy csak határolókból áll, az első híváskor NULL-t ad vissza strtok()).

Minden token végét egy előre irányuló keresés találja meg, amely addig tart, amíg meg nem találjuk a határoló bájtot vagy a befejező null ("\0") bájtot. Ha talál egy határoló bájtot, akkor azt nullbájttal helyettesíti az aktuális token leállításához, és strtok() a következő bájtra mutató mutatót tárol; ez a mutató lesz kiindulópont a következő token keresésekor. Ebben az esetben strtok() egy mutatót ad vissza a talált token elejére.

A fenti leírásból következik, hogy a beolvasott karakterláncban lévő két vagy több összefüggő határoló bájtból álló sorozat egyetlen határolónak minősül, és a karakterlánc elején vagy végén lévő határoló bájtokat figyelmen kívül hagyja. Más szóval, a jelzők visszatértek strtok() - mindig nem üres sorok. Például, ha van egy sor " aaa;;bbb,”, majd a következő hívások strtok() meghatározott sorelválasztókkal " ;, 'visszaadná a húrokat' aaa"És" bbb', amit egy null mutató követ.

Funkció strtok_r() a visszatérő verzió strtok(). Érv saveptr egy változóra mutató mutató char* amelyet belül használnak strtok_r() a következő hívások közötti kontextus figyelembevételéhez ugyanazon karakterlánc elemzésekor.

Első hívásra strtok_r() jelentése str az elemzett karakterláncra és az értékre kell mutatnia saveptr figyelmen kívül hagyva. A következő hívásoknál az érték str NULL-nak és az értéknek kell lennie saveptr nem változott az előző hívás óta.

Egyszerre több karakterlánc is értelmezhető több futtatás során strtok_r() különböző érvekkel saveptr.

VISSZATÉRÍTÉSI ÉRTÉK

Funkciók strtok() És strtok_r() visszaadja a mutatót a következő tokenre, vagy NULL-t, ha nincs több token.

TULAJDONSÁGOK

Az ebben a szakaszban szereplő kifejezések leírását lásd attribútumokat(7).
Felület Tulajdonság Jelentése
strtok() ártalmatlanság a szálakbannem biztonságos (MT-Nem biztonságos verseny:strtok)
strtok_r() ártalmatlanság a szálakbanártalmatlan (MT-Safe)

MEGFELELÉS

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

HIBÁK

Óvatosan használja ezeket a funkciókat. Megjegyzés: * Ezek a függvények megváltoztatják az első argumentumukat. * Ezek a függvények nem használhatók állandó karakterláncokkal. * A határoló bájt azonosítója elveszett. * Funkció elemzésekor strtok() statikus puffert használ, ezért nem szálbiztos. Használat strtok_r() ebben az esetben.

PÉLDA

Az alábbi program beágyazott hurkokat használ, amelyek hívnak strtok_r() a karakterlánc felosztása annak alkotó jelzőire. Az első paraméterben parancs sor az elemezni kívánt karakterlánc adott. A második paraméter határozza meg a határoló bájt(oka)t, amely a karakterlánc "összetett" tokenekre való felosztására szolgál. A harmadik paraméter határozza meg az elválasztó bájt(oka)t, amely az „összetett” tokenek résztokenekre való szétválasztására szolgál.

Példa a program kimenetére:

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

Program forráskódja

#beleértve #beleértve #beleértve int main(int argc, char *argv) ( char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc != 4) ( fprintf(stderr, "Használat: % s string delim subdelim\n", argv); exit(EXIT_FAILURE); ) for (j = 1, str1 = argv; ; j++, str1 = NULL) ( token = strtok_r(str1, argv, &saveptr1); if (token = = NULL) break; printf("%d: %s\n", j, token); for (str2 = token; ; str2 = NULL) ( subtoken = strtok_r(str2, argv, &saveptr2); if (subtoken == NULL) break; printf(" --> %s\n", subtoken); ) ) exit(EXIT_SUCCESS); )

Egy másik példa a program használatára strtok() található benne getaddrinfo_a(3).

4 válasz

Két dolog, amit tudni kell a strtok-ról. Mint említettük, "fenntartja a belső állapotot". Ráadásul ő elrontotta a vonalat, amivel eteted. Lényegében "\0"-t ír, ahol megtalálja az Ön által megadott jelölőt, és visszaadja a mutatót a karakterlánc elejére. Belsőleg fenntartja az utolsó token helyét; és ha legközelebb hívod, onnan indul.

Ennek fontos következménye, hogy nem használhatod az strtok-ot olyan karakterláncokon, mint a const char* "hello world"; , mivel a const char* karakterlánc tartalmának megváltoztatásakor hozzáférési szabálysértést kapsz.

Az a "jó" az strtok-ban, hogy valójában nem másol karakterláncokat, így nem kell extra memóriafoglalást kezelni stb. De ha nem érti a fentieket, akkor gondja lesz a használattal.

Példa. Ha a "this, is, string" van, az strtok egymást követő hívásai a következő mutatókat generálják (a ^ érték a visszatérési érték). Ne feledje, hogy a "\0" hozzáadódik ott, ahol a tokenek találhatók; ez azt jelenti, hogy az eredeti sor megváltozott:

T h i s , i s , a , s t r i n g \0 this,is,a,karakterlánc t h i s \0 i s , a , s t r i n g \0 this ^ t h i s \0 i s \0 r i s \0 r i s , isn t s \0 a \ 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 karakterlánc ^

Remélem ennek van értelme.

Az strtok() függvény adatokat tárol a hívások között. Ezeket az adatokat használja, amikor NULL mutatóval hívja meg.

Az utolsó jogkivonat megtalálásának pontját a rendszer belsőleg tárolja egy függvényben, amelyet a következő híváskor kell használni (nincs szükség speciális könyvtári megvalósításra az adatösszeomlások megelőzésére).

strtok fenntartja a belső állapotot. Ha nem NULL-lal hívja meg, akkor újrainicializálja magát, hogy a megadott karakterláncot használja. Ha NULL-lal hívja meg, akkor ezt a karakterláncot és bármely más állapotot használja, amelyet jelenleg vissza kell adnia a következő tokent.

Az strtok működéséből adódóan meg kell győződnie arról, hogy a C futtatókörnyezet többszálas verziójához kapcsolódik, ha többszálú alkalmazást ír. Ez biztosítja, hogy minden szál saját belső állapotot kapjon az strtok számára.

Az strtok függvény egy belső statikus változóban tárolja az adatokat, amely meg van osztva az összes szál között.

A szál biztonsága érdekében használja az strtok_r-t

Vessen egy pillantást a static char *last;

Char * strtok(s, delim) register char *s; register const char *delim; ( regiszter char *spanp; register int c, sc; char *tok; statikus char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Kihagyás (span) kezdő határolók (s += strspn(s, delim), sort of).*/ cont: c = *s++; for (spanp = (char *)delim; (sc = *spanp++) != 0;) ( if (c) == sc) goto cont; ) if (c == 0) ( /* nincsenek nem határoló karakterek */ last = NULL; return (NULL); ) tok = s - 1; /* * Keresési token (határolók keresése : s += strcspn(s, delim), fajta). * Ne feledje, hogy a delimnek egy NUL-nak kell lennie; megállunk, ha ezt is látjuk. */ for (;;) ( c = *s++; spanp = (char *)delim; do ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; else s[-1] = 0; utolsó = s; return (tok); ) ) while (sc != 0); ) /* NOTREACHED */ )

Ossza meg

Az strtok() függvény egy mutatót ad vissza az str1 paraméter által mutatott karakterlánc következő tokenjére. Az str2 paraméter által megcímzett karakterláncot alkotó karakterek a tokent meghatározó határolók. Ha nincs visszaadandó token, nulla mutató kerül visszaadásra.

A C99 verzióban a korlátozó minősítő az str1 és str2 paraméterekre vonatkozik.

Egy karakterlánc tokenekre való felosztásához az strtok() függvény első meghívásakor az str1 paraméternek a karakterlánc elejére kell mutatnia. A következő függvényhívásoknál str1 paraméterként null mutatót kell használni. Ebben az esetben a teljes karakterlánc minden függvényhíváskor frissül.

Az strtok() függvény minden hívása más-más token elválasztó készletet használhat.

Az strtok() függvény lehetőséget biztosít a karakterláncok alkotórészeire való redukálására. Például a következő program tokenizálja az "Egy, kettő és három" karakterláncot.

#beleértve #beleértve int main(void) char *p; p = strtok("Egy, kettő és három.", ","); printf(p); do ( p = strtok(NULL, ",. "); if(p) printf("|%s", p); ) while(p), visszatér 0; )

A program kimenete a következő.

egy | kettő | és | három

Figyelje meg, hogyan hívják meg először az strtok() függvényt az eredeti karakterlánccal, de a további hívások NULL-t használnak első argumentumként. Az strtok() függvény egy belső mutatót tart fenn a feldolgozandó karakterláncra. Ha az strtok() első argumentuma egy karakterláncra mutat, a belső mutató a karakterlánc elejére kerül. Ha az első érv egyenlő az értékkel NULL, az strtok() függvény folytatja az előző sor feldolgozását, az előző lépésben tárolt pozícióból kiindulva, és a következő token fogadásakor továbbítja a belső mutatót. Így az strtok() függvény "bejárja" a teljes karakterláncot. Figyelje meg azt is, hogyan változik a határoló karakterlánc a függvény első és azt követő meghívásakor. A határolók minden hívásnál eltérően definiálhatók.

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

Leírás:

Az strtok() függvény egy mutatót ad vissza az str1 által mutatott karakterlánc következő tokenjére. Az str2 által mutatott karakterlánc karakterei határolóként használatosak, amelyek meghatározzák a tokent. Ha a tokent nem találja, a rendszer NULL-t ad vissza.

Az strtok() első hívása valójában az str1-et használja mutatóként. A további hívások NULL-t használnak első argumentumként. Így a teljes karakterlánc tokenizálható.

Fontos megérteni, hogy az strtok() függvény módosítja az str1 által mutatott karakterláncot. Minden alkalommal, amikor egy tokent talál, egy null karakter kerül arra a helyre, ahol a határolót megtalálták. Tehát az strtok() a karakterlánc mentén halad előre.

Az strtok() minden egyes meghívásával változtathatja a határolók készletét.

Az _fstrtok() függvény a kérdéses függvény FAR verziója.

A következő program a „Nyári katona, a napfény hazafi” karakterláncot szóközökkel és vesszőkkel határolóként tokenizálja. A program eredményeként a következő formátumú sor keletkezik: „A | nyár | katonák | a | napsütés | hazafi".
#beleértve
#beleértve
int main(void)
{
char*p;
p = strtok( "A nyári katona, a napfény hazafi", " " ) ;
printf(p);
do(
p=strtok(" \0 " , ", " ) ;
if (p) printf("|%s" , p) ;
) míg (p);
return 0 ;
}

A programozási nyelvek tartalmazhatnak speciális funkciók stringekkel dolgozni, ezzel megkímélve a programozót attól, hogy saját karakterlánc-feldolgozó függvényeket kelljen írnia. Például gyakran meg kell határozni egy karakterlánc hosszát, így a nyelvek funkciót biztosítanak a hosszának mérésére.

A C programozási nyelvben a karakterláncokkal való munkavégzés függvényei a string.h fejlécfájlban vannak deklarálva, amelyeket feltétlenül szerepeltetni kell a forráskódban. Körülbelül húsz függvény létezik a karakterláncokkal való munkához. Köztük vannak olyanok, amelyek karaktereket keresnek egy karakterláncban, összehasonlító függvények, karakterlánc-másolás, valamint konkrétabbak is. A legtöbb létező listája és leírása Ebben a pillanatban a C nyelvben a függvények megtalálhatók B. Kernighan, D. Ritchie "A C programozási nyelv. Második kiadás" című könyvének függelékében.

A string.h-ban deklarált összes függvény módosíthatja vagy nem módosíthatja a mutató által átadott karakterláncokat a munkája során. Ez a funkció céljától függ. A legtöbb azonban visszaad valamit: vagy egy karakterre mutató mutatót, vagy egy egész számot. Sőt, ha a függvény megváltoztatja az egyik paraméterét és erre hívták, akkor amit visszaad, az figyelmen kívül hagyható (vagyis nem rendelhető hozzá semmihez a hívó függvényben).

Például az strcpy() függvénynek a következő deklarációja van: char *strcpy (char *, const char*) . A második paraméter által mutatott karakterláncot átmásolja az első paraméter által mutatott karakterláncba. Tehát az első paraméter megváltozik. Ezenkívül a függvény egy mutatót ad vissza a karakterlánc első karakterére:

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

Itt s2 és s3 ugyanarra a karakterre mutat (a printf() ugyanazt a címet adja ki). Azonban amit az strcpy() ad vissza, azt nem lehet tömbhöz rendelni. Ennek a függvénynek az eredménye általában nincs hozzárendelve semmihez; néha elég, ha egyszerűen megváltoztatja a mutató által átadott karakterláncok egyikét.

Egy másik dolog az olyan függvények, mint például az strlen() vagy strcmp() , amelyek nem változtatják meg a paramétereket, hanem az eredmény érdekében hívódnak meg. Az strcmp() függvény betűnként (lexikográfiailag) összehasonlítja a két argumentum karakterláncot, és 0, -1 vagy 1 értéket ad vissza. Például az strcmp("boy", "body") hívása 1-et ad vissza, mert "y" betűkód több mint egy levél"d". Az strcmp("body", "boy") hívása -1-et ad vissza, mert az első érv lexikográfiailag kisebb, mint a második.

strtok() függvény

Az strtok() függvény segítségével egy karakterláncot különálló részekre (tokenekre) oszthatunk fel. Ennek a függvénynek a deklarációja így néz ki: char *strtok (char *, const char *) . A függvény első meghívásakor az első paraméter a felosztandó karakterlánc. A második paraméter a határoló karakterláncot adja meg. Ugyanazon sor további függvényhívásainál az első paraméternek NULL-nak kell lennie, mert a függvény már "emlékezett", hogy mivel működik. Vegyünk egy példát:

char str = "egy, kettő, három, négy, öt" ; char*sp; sp = strtok (str, ", " ) ; while (sp) ( elhelyezi (sp) ; sp = strtok (NULL, ", " ) ; )

A kód végrehajtásának eredményeként a következő szavak jelennek meg egy oszlopban:

Egy, kettő, három, négy, öt

Az strtok() első meghívásakor a függvény egy mutatót ad át a tömb első karakterére és egy határoló karakterláncot. E hívás után az str tömb megváltozik, csak az "one" szó marad benne, és a függvény egy mutatót is visszaad erre a szóra, ami az sp-hez van rendelve.

Bár a tömb többi részét elveszítettük a hívó függvényben, a tömb többi részére mutató mutató megmarad a strtok()-ban. Amikor a NULL értéket adjuk meg, a függvény "tudja", hogy ezzel a farokkal működik.

A karakterláncok részeinek másolása

Ha csak két karakterláncot kell összekapcsolnia, a probléma könnyen megoldható az strcat() függvény meghívásával, amely az első argumentum végéhez fűzi a másodikat. Egy hasonló függvény, az strncat(), n karaktert fűz hozzá a második karakterláncból az elsőhöz. n van megadva harmadik paraméterként.

Mi van, ha a helyzet bonyolultabb? Például van két nem üres sor, és össze kell kapcsolnia az első elejét és a második végét. Ezt a strcpy() függvény segítségével teheti meg, ha nem a karakterláncok első karaktereire ad át hivatkozásokat:

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

BAN BEN ez az eset"Peter Roberts" jelenik meg a képernyőn. Miért történt ez? Az első karakterlánc hatodik karakterére mutató mutatót átadtuk az strcpy() függvénynek. Ez oda vezetett, hogy másoláskor ennek a karakterláncnak a karakterei csak a 6-tól kezdődően íródnak felül, mert Az strcpy() nem "tud" semmit a korábbi karakterekről. A karakterláncnak csak egy része kerül átadásra második argumentumként is, amely az elsőbe másolódik.

Hogyan lehet beszúrni egy sort a másik közepébe? Ezt a problémát a harmadik "puffer" sor segítségével oldhatja meg, ahol először az első sort másolja, majd a másodikat, felülírva az első végét, majd csatolja az első végét. De ezt is megteheti:

char s1[20] = "egy három" , s2[20] = "kettő" ; strcpy (s2+ 3 , s1+ 3 ); strcpy (s1+4, s2); tesz(ek1) ;

Itt először az első végét másoljuk a második sorba, kiderül, hogy „két három”. Ezután a második sort az első sorba másolja, megkerülve annak elejét.

Néhány funkció leírása karakterláncokkal való munkához

Gyakorlat
Az alábbiakban néhány olyan függvény leírása található, amelyek karakterláncokon hajtanak végre műveleteket. Tervezzen és írjon kis programokat, amelyek bemutatják ezeknek a funkcióknak a működését.

  • char *strchr (const char *, int c) . Egy mutatót ad vissza a c karakter első előfordulására a karakterláncban. NULL értéket ad vissza, ha nincs ilyen karakter a karakterláncban.
  • char *strstr (const char *s2, const char *s1) . Egy mutatót ad vissza az s1 karakterlánc első előfordulására az s2 karakterláncban. Ha nincs egyezés, NULL értéket ad vissza.
  • char *strncpy (char *, const char *, size_t n) . A második karakterlánc n karakterét másolja az elsőbe.
  • size_t strspn (const char *, const char *) . Az első karakterlánc elejének hosszát adja vissza, amely tartalmazza a második karakterláncot alkotó karaktereket.

Ha hibát észlel, jelöljön ki egy szövegrészt, és nyomja meg a Ctrl + Enter billentyűket
OSSZA MEG: