Sətirləri emal etmək üçün funksiyalar. Man strtok_r(3): Strtok s c təsvirindən elementləri (tokenləri) çıxarın

4 cavab

strtok haqqında bilmək üçün iki şey. Qeyd edildiyi kimi, "daxili vəziyyəti saxlayır". Üstəlik, o onu qidalandırdığınız xətti qarışdırdınız. Əsasən o, təqdim etdiyiniz nişanı tapacağı yerdə "\0" yazacaq və xəttin başlanğıcına göstərici qaytaracaq. Daxili olaraq o, sonuncu işarənin yerini saxlayır; və növbəti dəfə zəng edəndə, oradan başlayacaq.

Mühüm nəticə ondan ibarətdir ki, siz const char* "salam dünya" kimi sətirdə strtok istifadə edə bilməzsiniz; çünki const char* sətirinin məzmununu dəyişdirərkən giriş pozuntusu alacaqsınız.

Strtok-un "yaxşı tərəfi" odur ki, o, əslində sətirləri kopyalamır, ona görə də əlavə yaddaş ayrılmasını idarə etməyə ehtiyac yoxdur və s. Ancaq yuxarıdakıları başa düşməsəniz, ondan istifadə etməkdə çətinlik çəkəcəksiniz.

Misal. Əgər "bu, bir sətir" varsa, strtok-a ardıcıl zənglər bu kimi göstəricilər yaradacaq (^ dəyəri qaytarılan dəyərdir). Qeyd edək ki, tokenlərin tapıldığı yerə "\0" əlavə olunur; bu o deməkdir ki, orijinal xətt dəyişdirilib:

T h i s , i s , a , s t r i n g \0 this,is,a,string t h i s \0 i s , a , s t r i n g \0 bu ^ t h i s \0 i s \0 a , s t r i \ 0i \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 ^

Ümid edirəm ki, bu məntiqlidir.

strtok() funksiyası zənglər arasında məlumatları saxlayır. NULL göstəricisi ilə çağırdığınız zaman bu məlumatlardan istifadə edir.

Son işarənin tapıldığı nöqtə növbəti zəngdə istifadə olunacaq funksiya tərəfindən daxili olaraq saxlanılır (məlumatların nasazlığının qarşısını almaq üçün xüsusi kitabxana tətbiqi tələb olunmur).

strtok daxili vəziyyəti saxlayır. Siz onu qeyri-NULL ilə çağırdığınız zaman o, təmin etdiyiniz sətirdən istifadə etmək üçün özünü yenidən işə salır. Siz onu NULL ilə çağırdığınız zaman o, həmin sətirdən istifadə edir və hazırda növbəti işarəni qaytarmaq üçün lazım olan başqa vəziyyətdən istifadə edir.

Strtok-un işləmə üsuluna görə, əgər siz çox yivli proqram yazırsınızsa, C iş vaxtının çox yivli versiyasına keçid etdiyinizə əmin olmalısınız. Bu, hər ipin strtok üçün öz daxili vəziyyətini almasını təmin edir.

strtok funksiyası məlumatları bütün mövzular arasında paylaşılan daxili statik dəyişəndə ​​saxlayır.

Mövzu təhlükəsizliyi üçün strtok_r istifadə etməlisiniz

Static char *sonuna nəzər salın;

Char * strtok(lar, delim) qeydi char *s; qeydiyyatdan keçin const char *delim; ( register char *spanp; register int c, sc; char *tok; static char *son; əgər (s == NULL && (s = sonuncu) == NULL) qaytarın (NULL); /* * Skip (span) aparıcı ayırıcılar (s += strspn(s, delim), sort == sc) goto cont; ) tok = s - 1; /* * Scan token (bölgəciləri skan edin: s += strcspn(s, delim), bir növ qeyd edək ki, biz bunu görürüksə, biz də dayandırırıq. )delim; do ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); ) ) while (sc != 0 ) /* NOTREACHED */ )

paylaş

Təsvir

strtok funksiyası sətir sətirində işarələri axtarır. Bu funksiyaya edilən zənglər ardıcıllığı sətri ayırıcı simvollarla ayrılmış simvol ardıcıllığı olan tokenlərə bölür.

İlk zəngdə funksiya arqument kimi sətri götürür, onun ilk simvolu tokenlərin axtarışı üçün başlanğıc nöqtəsi kimi istifadə olunur. Sonrakı zənglərdə funksiya boş göstəricini gözləyir və skan etmək üçün yeni yer kimi sonuncu işarənin bitməsindən dərhal sonra mövqedən istifadə edir.

Tokenin başlanğıcını müəyyən etmək üçün funksiya əvvəlcə delim sətirində olmayan simvolları müəyyən edir, yəni onlar ayırıcı simvollardır. Və sonra simli simvolun qalan hissəsini simvolun sonunu bildirən ilk ayırıcı simvola qədər yoxlayır.

Bu arxadakı işarə avtomatik olaraq null simvolu ilə əvəz olunur və işarə funksiya tərəfindən qaytarılır. Bundan sonra strtok funksiyasına sonrakı zənglər bu null simvolla başlayır.

Seçimlər:

  • simli
    Leksemləri axtarmaq üçün sətir. Bu sətirin məzmunu dəyişdiriləcək, o, daha kiçik sətirlərə (tokenlərə) bölünəcək. Bu parametr ehtiva edə bilərnull göstərici, bu halda funksiya əvvəlki uğurlu funksiya çağırışının qaldığı yerdən skan etməyə davam edir.
  • delim
    Məhdudlaşdırıcıları ehtiva edən sətir. Onlar bir funksiya çağırışından digər funksiya çağırışına qədər dəyişə bilər.

Dəyəri qaytarın

Sətirdə tapılan sonuncu işarənin göstəricisi.
Heç bir token tapılmadıqda null göstərici qaytarılır.

Misal: proqramın mənbə kodu

//strtok funksiyasından istifadə nümunəsi #include #daxildir int main () ( char str = "Milli balıqçılıq xüsusiyyətləri - bədii, komediya filmi."; std::cout<< "Разделение строки "" << str << "" на лексемы:n"; char * pch = strtok (str," ,.-"); // во втором параметре указаны разделитель (пробел, запятая, точка, тире) while (pch != NULL) // пока есть лексемы { std::cout << pch << "n"; pch = strtok (NULL, " ,.-"); } return 0; }

Proqramlaşdırma dillərinə sətirləri manipulyasiya etmək üçün xüsusi funksiyalar daxil ola bilər və bununla da proqramçının öz simli emal funksiyalarını yazmasına ehtiyacı aradan qaldırır. Məsələn, tez-tez bir sətir uzunluğunu təyin etməlisiniz və buna görə də dillər onun uzunluğunu ölçən bir funksiya təmin edir.

C proqramlaşdırma dilində sətirlərlə işləmək üçün funksiyalar string.h başlıq faylında elan edilir ki, onu mənbə kodunuza daxil etməyi unutmayın. Simlərlə işləmək üçün təxminən iyirmi funksiya var. Onların arasında sətirdə simvol axtaranlar, müqayisə funksiyaları, sətirlərin surətini çıxarmaq, eləcə də daha konkret olanlar var. Hazırda C dilində mövcud olan əksər funksiyaların siyahısı və təsviri B. Kerniqan və D. Ritçinin “The C Programming Language” adlı kitabının əlavəsində tapıla bilər.

string.h-də elan edilmiş bütün funksiyalar iş zamanı göstəricinin ötürdüyü sətirlərdən birini dəyişə və ya dəyişməyə bilər. Bu, funksiyanın məqsədindən asılıdır. Bununla belə, onların əksəriyyəti nəyisə qaytarır: ya simvola göstərici, ya da tam ədəd. Üstəlik, əgər funksiya öz parametrlərindən birini dəyişirsə və bu məqsədlə çağırılıbsa, onun qaytardığına məhəl qoyula bilməz (yəni çağırış funksiyasında heç nəyə təyin olunmur).

Məsələn, strcpy() funksiyası aşağıdakı bəyannaməyə malikdir: char *strcpy (char *, const char*) . O, ikinci parametrin göstərdiyi sətri birinci parametrin göstərdiyi sətirə kopyalayır. Beləliklə, birinci parametr dəyişdirilir. Bundan əlavə, funksiya sətirin ilk simvoluna göstərici qaytarır:

char s1[ 10 ] , s2[ 10 ] ; char * s3; s3 = s2; alır(s1); s3 = strcpy(s2, s1); qoyur (s2); qoyur (s3); printf("%p, %p \n", s2, s3);

Burada s2 və s3 eyni simvolu göstərir (printf() eyni ünvanları verir). Bununla belə, hansı strcpy() qaytarırsa, seriala təyin edilə bilməz. Bu funksiyanın nəticəsi adətən heç bir şeyə təyin edilmir; Bəzən bunun sadəcə göstəricidən keçən sətirlərdən birini dəyişməsi kifayətdir.

Başqa bir şey, parametrləri dəyişdirməyən, lakin nəticə naminə çağırılan strlen() və ya strcmp() kimi funksiyalardır. strcmp() funksiyası iki arqument sətirini hərf-hərf (leksikoqrafik olaraq) müqayisə edir və 0, -1 və ya 1 qaytarır. Məsələn, strcmp("boy", "body") çağırılması 1-i qaytaracaq, çünki "y" hərfinin kodu "d" hərfindən böyükdür. strcmp("body", "boy") çağırılması -1 qaytarılacaq, çünki birinci arqument leksikoqrafik cəhətdən ikincidən azdır.

strtok funksiyası ()

strtok() funksiyasından istifadə edərək sətri ayrı hissələrə (token) ayıra bilərsiniz. Bu funksiyanın elanı belə görünür: char *strtok (char *, const char *) . Funksiya ilk dəfə çağırıldıqda, birinci parametr bölünməli olan sətirdir. İkinci parametr ayırıcı sətiri təyin edir. Eyni sətir üçün funksiyaya sonrakı çağırışlarda birinci parametr NULL olmalıdır, çünki funksiya nə ilə işlədiyini artıq “xatırladı”. Bir misala baxaq:

char str = "bir, iki, üç, dörd, beş" ; char * sp; sp = strtok (küç, "," ); while (sp) ( qoyur (sp); sp = strtok (NULL, ", " ) ; )

Bu kodun icrası nəticəsində sözlər ekranda sütun şəklində göstərilir:

Bir iki üç dörd beş

İlk dəfə strtok() çağırıldıqda, massivin birinci simvoluna göstərici və ayırıcı sətir funksiyaya ötürülür. Bu çağırışdan sonra str massivi dəyişdirilir, orada yalnız "bir" sözü qalır və funksiya həm də sp-ə təyin edilmiş bu sözə göstərici qaytarır.

Biz çağırış funksiyasında massivin qalan hissəsini itirsək də, massivin qalan hissəsi üçün göstərici strtok() daxilində saxlanılır. NULL ötürüldükdə, funksiya bu "quyruq" ilə işləməyi "bilir".

Sətirlərin hissələrinin kopyalanması

Sadəcə olaraq iki sətri birləşdirmək lazım olduqda, problem birinci arqumentin sonuna ikincini əlavə edən strcat() funksiyasını çağırmaqla asanlıqla həll olunur. Oxşar funksiya, strncat(), ikinci sətirin n simvolunu birinciyə əlavə edir. n üçüncü parametr kimi təyin olunur.

Bəs vəziyyət daha mürəkkəbdirsə? Məsələn, boş olmayan iki sətir var və birincinin əvvəlini və ikincinin sonunu birləşdirmək lazımdır. Bu, strcpy() funksiyasından istifadə etməklə edilə bilər, əgər siz sətirlərin ilk simvollarına deyil, istinadları keçirsəniz:

char s1[ 20 ] = "Piter Smit" , s2 = "Culiya Roberts" ; strcpy (s1+ 5 , s2+ 5 ); qoyur (s1);

Bu halda ekranda “Piter Roberts” görünəcək. Niyə belə oldu? Birinci sətrin altıncı simvoluna göstərici strcpy() funksiyasına ötürüldü. Bu, köçürmə zamanı bu sətrin simvollarının yalnız 6-dan başlayaraq üzərinə yazılmasına səbəb oldu, çünki strcpy() əvvəlki simvollar haqqında heç nə "bilmir". Sətirin yalnız bir hissəsi birinciyə kopyalanan ikinci arqument kimi də ötürülür.

Bir sətri digərinin ortasına necə daxil etmək olar? Bu problemi üçüncü "bufer" sətirindən istifadə etməklə həll edə bilərsiniz, burada əvvəlcə birinci sətri, sonra ikincini köçürə, birincinin sonunu silə, sonra birincinin sonunu əlavə edə bilərsiniz. Ancaq bunu da edə bilərsiniz:

char s1[ 20 ] = "bir üç" , s2[ 20 ] = "iki" ; strcpy (s2+ 3 , s1+ 3 ); strcpy (s1+ 4, s2); qoyur (s1);

Burada əvvəlcə birincinin sonu ikinci sətirə köçürülür və nəticədə “iki üç” olur. Sonra ikinci sətir başlanğıcından yan keçərək birinci sətirə köçürülür.

Sətirlərlə işləmək üçün bəzi funksiyaların təsviri

Məşq edin
Aşağıda sətirlər üzərində əməliyyatları yerinə yetirən bəzi funksiyaların təsviri verilmişdir. Bu funksiyaların necə işlədiyini göstərən kiçik proqramlar hazırlayın və yazın.

  • char *strchr (const char *, int c) . Sətirdə c simvolunun ilk təkrarlanmasına göstərici qaytarır. Sətirdə belə simvol yoxdursa, NULL qaytarır.
  • char *strstr (const char *s2, const char *s1) . s2 sətirində s1 sətirinin ilk təkrarlanmasına göstərici qaytarır. Heç bir uyğunluq yoxdursa, NULL qaytarır.
  • char *strncpy (char *, const char *, size_t n) . İkinci sətrin n simvolunu birinciyə köçürür.
  • size_t strspn (const char *, const char *) . İkinci sətri təşkil edən simvolları ehtiva edən birinci sətirin başlanğıcının uzunluğunu qaytarır.

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

Təsvir:

strtok() funksiyası str1 ilə göstərilən sətirdəki növbəti işarəyə göstərici qaytarır. str2 ilə işarə edilən sətirdəki simvollar nişanı təyin edən ayırıcılar kimi istifadə olunur. Token tapılmazsa, NULL qaytarılır.

strtok()-a ilk zəng əslində göstərici kimi str1-dən istifadə edir. Sonrakı zənglər ilk arqument kimi NULL-dən istifadə edir. Bu yolla bütün sətir tokenlərə bölünə bilər.

strtok() funksiyasının str1 tərəfindən göstərilən sətri dəyişdirdiyini başa düşmək vacibdir. Hər dəfə bir işarə tapıldıqda, ayırıcının tapıldığı yerə sıfır simvol qoyulur. Beləliklə, strtok() xətt boyunca irəliləyir.

strtok() funksiyasına edilən hər bir çağırış sizə məhdudlaşdırıcılar dəstini dəyişməyə imkan verir.

_fstrtok() funksiyası sözügedən funksiyanın FAR versiyasıdır.

Aşağıdakı proqram ayırıcı kimi boşluq və vergüllərdən istifadə edərək "Yay əsgəri, günəşli vətənpərvər" sətirini simvollaşdırır. Proqramın işləməsi nəticəsində aşağıdakı sətir yaranacaq: “The | yay | əsgər | | günəş işığı | vətənpərvər”.
#daxildir
#daxildir
int əsas (boş)
{
char * p;
p = strtok ( "Yay əsgəri, günəşli vətənpərvər", " " ) ;
printf(p);
etmək (
p= strtok(" \0 " , ", " ) ;
əgər (p) printf ("|% s", p);
) while (p) ;
0 qaytarın;
}



Əlaqədar nəşrlər