Mäu reserveerimiseks kasutatakse tavaliselt funktsioone calloc(), malloc() ja realloc() või siis nende vastavaid funktsioone üldisest vabast mälust reserveerimiseks: farmalloc(), farcalloc() ja farrealloc(). Neid funktsioone käsitleti juba peatükis "Mälu haldamine". Tüüpiliselt loovutavad need funktsioonid reserveeritud mälublokile näitava viida. See viit on alati tüübist void * või void far * ja teda tuleb seepärast soovitud tüübiks konverteerida. Kui soovitud suurusega mälublokki ei õnnestunud reserveerida, siis loovutavad need funktsioonid väärtuse NULL. Saadud viita tuleb alati kontrollida, sest kui te üritate kasutada NULL viita, siis katkestab operatsioonisüsteem teie programmi töö. Funktsioonid calloc() ja farcalloc() täidavad reserveeritud mälubloki nullidega, mis ka enamiku programmide jaoks sobib. Sümbolite jada puhul on lõpumärgiks null ja ka andmestruktuuride salvestamisel kasutatakse sageli salvestatud struktuuride loendamise asemel nullidega täidetud andmestruktuuri elemendi lõpus. Nimetatud funktsioonid on defineeritud päisefailis ALLOC.H, kuid ka päisefail STDLIB.H sisaldab nende definitsioone.
Päisefailis MALLOC.H on defineeritud funktsioonid alloca() ja stackavail().
size_t stackavail( void ); void * alloca(size_t size);
Funktsioon alloca() reserveerib mälu programmi pinult. Saadud viit tuleb salvestada hetkelise funktsiooni kohalikku muutujasse. Peale selle funktsiooni töö lõppu vabastatakse reserveeritud mälu automaatselt, ilma et te kasutaksite funktsiooni free(). Teadmaks, kui palju mälu programmi pinult veel on vaba, kasutage funktsiooni stackavail(). Neid funktsioone kasutavad nii DOSi, kui ka osa UNIXi translaatoreist, kuid need ei ole standardsed ANSI C funktsioonid.
Päisefail MEM.H defineerib mitmeid funktsioone mälublokkide haldamiseks. Sarnaseid ja osalt samu funktsioone on defineeritud ka päisefailis STRING.H. Päisefail STRING.H defineerib funktsioone sümbolijadade haldamiseks. Põhiline vahe on selles, et sümbolijadu töötlevad funktsioonid oletavad, et tegemist on C - keele sümbolijadadega. Viimased koosnevad üksikutest baitidest, kusjuures jada lõpus on sümbol '\0'. Mälublokke haldavad funktsioonid seevastu ei omista mingit tähelepanu üksikute baitide väärtusele, vaid vajavad mälubloki pikkust määravat parameetrit.
Mälublokke haldavad funktsioonid sisaldavad kolme funktsiooni mälu kopeerimiseks:
void * memccpy(void *dest, const void * src, int c, size_t n); void * memcpy(void *dest, const void * src, size_t n); void * memmove(void *dest, const void * src, size_t n);
Kõik nimetatud funktsioonid kopeerivad viida src poolt määratud mälublokist n baiti viida dest poolt näidatud mälublokki. Funktsioon memccpy() võib kopeerimise ka enne n baidi teisaldamist lõpetada, kui ta satub baidile väärtusega c, mis on sel juhul viimaseks kopeeritud baidiks. Funktsioonid memcpy() ja memmove() kopeerivad kindlasti määratud arvu baite. Kui aga kopeeritavad piirkonnad omavahel kattuvad, siis on funktsiooni memcpy() tulemus ebakorrektne. Funktsioon memmove() seevastu kopeerib ka kattuvate või osaliselt kattuvate piirkondade puhul õigesti, kuid on seetõttu aeglasem. Funktsioonide memcpy() ja memmove() tulemuseks on viit, mis langeb kokku funktsiooni esimese parameetriga - dest. Kui funktsioon memccpy() lõpetas oma töö väärtusega c baidi leidmise tulemusena, siis näitab funktsiooni poolt loovutatav viit sellele järgnevale baidile, vastasel juhul on funktsiooni tulemuseks NULL.
Funktsioonid _fmemccpy(), _fmemcpy() ja _fmemmove() täidavad samu ülesandeid üldisest mälust reserveeritud mälublokkide puhul.
void far * _fmemccpy(void far *dest, const void far * src, int c, size_t n); void far * _fmemcpy(void far *dest, const void far * src, size_t n); void far * _fmemmove(void far *dest, const void far * src, size_t n);
Funktsioon memset() ja _fmemset() täidavad parameetri ptr poolt osutatud mälubloki esimesed n baiti väärtusega c.
void* memset(void* ptr, int c, size_t n); void far* _fmemset(void far* ptr, int c, size_t n);
Mälublokkide võrdlemiseks võib kasutada funktsioone memcmp() je memicmp() (ning vastavaid funktsioone _fmemcmp() ja _fmemicmp()).
int memcmp(const void* ptr1, const void* ptr2, size_t n); int memicmp(const void* ptr1, const void* ptr2, size_t n); int _fmemcmp(const void far* ptr1, const void far* ptr2, size_t n); int _fmemicmp(const void far* ptr1, const void far* ptr2, size_t n);
Funktsioon memcmp() võrdleb baidikaupa viitade ptr1 ja ptr2 poolt määratud mälublokkide n esimest baiti. Funktsiooni tulemus on:
Seejuures ei mõjuta funktsioon memcmp() mingil määral baitide väärtust enne nende võrdlemist, funktsioon memicmp() seevastu võrdleb ilma väike- ja suurtähtede vahel vahet tegemata.
Mingi kindla väärtuse otsimiseks kasutage funktsiooni memchr() (või funktsiooni _fmemchr())
void* memchr(void* ptr, int c, size_t n); void far* _fmemchr(void far* ptr, int c, size_t n);
Funktsioon memchr() otsib parameetri ptr poolt määratud mälublokist n baidi ulatuses baiti väärtusega c ja loovutab esimesele sellisele baidile näitava viida. Kui nimetatud mälublokk sellist baiti ei sisalda, siis on funktsiooni tulemuseks NULL.
Päisefail STRING.H sisaldab kõiki eespool nimetatud funktsioone ja lisaks sellele funktsioone sümbolijadade töötlemiseks. Sümbolijadade kopeerimiseks võib kasutada funktsiooni strcpy().
char* strcpy(char *dest, const char* src); char far* _fstrcpy(char far*dest, const far* src);
Funktsioon strcpy() kopeerib parameetri src poolt osutatud sümbolijada parameetri dest poolt osutatud puhvrisse ja loovutab viida nimetatud puhvrile. Esimene sümbolijada peab olema lõpetatud sümboliga '\0' (ehk arvuga 0), mis samuti kopeeritakse teise puhvrisse.
Funktsioon stpcpy() erineb funktsioonist strcpy() vaid selle poolest, et esimese sümbolijada lõpumärki ei kopeerita teise puhvrisse ja seega tuleb see vajaduse korral sinna ise lisada. Selle funktsiooniga saab aga kirjutada juba olemasoleva sümbolijada keskele mingeid sümboleid, ilma seejuures nimetatud jada lühendamata.
char* stpcpy(char *dest, const char* src); char far* _fstpcpy(char far*dest, const far* src);
Kindla arvu sümbolite kopeerimiseks kasutage funktsiooni strncpy().
char* strncpy(char *dest, const char* src, size_t size); char far* _fstrncpy(char far*dest, const char far* src, size_t size);
Funktsioon strncpy() kopeerib maksimaalselt size baiti parameetri src poolt osutatud puhvrist parameetri dest poolt osutatud puhvrisse. Kui esimene puhver sisaldas vähem sümboleid, siis kopeeritakse vaid need. Kui ta aga sisaldab rohkem sümboleid, siis kopeeritakse vaid esimesed size baiti.
Funktsioon strdup() loob teise samasuguse sümbolitejada. Selleks reserveerib ta funktsiooni malloc() abil sobiva suurusega mälubloki, kopeerib soovitud sümbolitejada loodud puhvrisse ja loovutab nimetatud puhvrile näitava viida.
char * strdup(const char* src); char far* _fsrtdup(const char far* src);
Sümblitejada pikkuse mõõtmiseks tuleks kasutada funktsiooni strlen().
size_t strlen(const char* ptr); size_t far _fstrlen(const char far* ptr);
Vajaliku sümboli otsimiseks võib kasutada funktsiooni strchr().
char* strchr(const char* ptr, int c); char far* _fstrchr(const char far* ptr, int c);
Kui funktsioon leiab soovitud sümboli määratud jadast, siis loovutab ta sellele sümbolile näitava viida, vastasel juhul aga väärtuse NULL. Seejuures loetakse lõpumärk '\0' jada osaks, näiteks:
char nimi[] = "Jaanus", *ptr; ... ptr = strchr(nimi, 0);
loovutab sümbolitejada lõppu näitava viida. Funktsioon strchr() otsib niisiis soovitud sümboli esimese positsiooni määratud jadas. Kui aga nimetatud sümbol esineb määratud jadas mitu korda, siis võib vaja olla otsida ka esimesele positsioonile järgnevaid positsioone. Selleks võite kasutada samuti funktsiooni strchr(), loovutades talle igal järgmisel korral eelmisel korral saadud viida, kuni funktsiooni väärtus on NULL, näiteks:
char string[] = "metallitehnoloogia", *ptr;
...
ptr = string;
while(NULL != (ptr = strchr(ptr, 'l'))) {
printf("Tähe l %d positsioon: %s\n", (int)string - (int)ptr + 1, ptr);
}
Toodud näites väljastatakse tähe 'l' iga positsioon määratud sümbolijadas. Seejuures kasutatakse tõsiasja, et viidad on lihtsalt aadressid. Kui nad eelnevalt konverteerida täisarvudeks, siis saab neid üksteisest lahutada ja saadud vahe annabki otsitud sümboli positsiooni. Kuna aga C - keel alustab loendamisega nullist, mitte aga ühest, siis tuleb veel liita 1.
Viimase positsiooni leidmiseks on lihtsam kasutada funktsiooni strrchr().
char* strrchr(const char* ptr, int c); char far* _fstrrchr(const char far* ptr, int c);
Funktsioon strrchr() erineb funktsioonist strchr() vaid selle poolest, et ta alustab otsimisega sümbolitejada lõpust ja liigub alguse poole.
Paljude sümbolite otsimiseks sümbolijadast tuleks kasutada funktsiooni strstr().
char* strstr(char* str1, char* str2); char far* _fstrstr(char far* str1, char far* str2);
Funktsioon strstr() otsib sümbolitejadast str1 jada str2 esimest positsiooni ja loovutab sellele näitava viida või väärtuse NULL, kui soovitud jada ei leidunud.
Sümbolijadade võrdlemiseks kasutage funktsioone strcmp(), stricmp() ja strcmpi().
int strcmp(const char *s1, const char *s2); int strcmpi(const char *s1, const char *s2); int stricmp(const char *s1, const char *s2); int far _fstrcmp(const char far *s1, const char far *s2); int far _fstricmp(const char far *s1, const char far *s2);
Kõik need funktsioonid võrdlevad üle antud sümbolijadasid ja loovutavad väärtuse, mis näitab, kas jada s1 on väiksem (negatiivne väärtus), suurem (positiivne väärtus) või võrdne (0) jadaga s2. Funktsioonid strcmpi() ja stricmp() loevad suujuures väikesed ja suured tähed võrdseks. Näiteks stricmp("AAA", "aaa") annab tulemuse 0, aga strcmp("AAA", "aaa") annab negatiivse tulemuse, kuna suurtähed omavad väiksemat ASCII koodi kui väiketähed.
Järgnevad funktsioonid täidavad sama ülesannet, kui eespool toodud funktsioonid, kuid kontrollivad vaid mõlema jada esimesi maxlen sümbolit.
int strncmp (const char *s1, const char *s2, size_t maxlen); int strncmpi(const char *s1, const char *s2, size_t maxlen); int strnicmp(const char *s1, const char *s2, size_t maxlen); int far _fstrncmp (const char far *s1, const char far *s2, size_t maxlen); int far _fstrnicmp(const char far *s1, const char far *s2, size_t maxlen);
Sümbolijadade uurimiseks kasutatakse veel funktsioone strspn() ja strcspn().
size_t strcspn(const char *s1, const char *s2); size_t strspn(const char *s1, const char *s2); size_t far _fstrcspn(const char *s1, const char far *s2); size_t far _fstrspn(const char far *s1, const char far *s2);
Funktsioon strspn() ostsib jadast s1 jadas s2 leiduvaid sümboleid ja loovutab kõige pikema jada s1 selle osa pikkuse, mis koosneb ainult jadas s2 leiduvatest sümbolitest. Viimaste sümbolite hulka ei loeta aga jada s2 lõpumärki - '\0'. Funktsioon strcspn() seevastu loovutab jada s1 suurima osa pikkuse, mis ei sisalda ühtegi jadas s2 leiduvatest sümbolitest.
Programmi argumentide töötlemiseks kasutatakse sageli funktsiooni strtok().
char* strtok(const char* str1, const char* str2); char far* _fstrtok(const char far* str1, const char far* str2);
Funktsioon strtok() käsitleb sümbolite jada s1 kui mitmest osajadast koosnevat jada, mille osasid lahutavad jadas s2 leiduvad sümbolid. Näiteks kui te loeksite mingist *.BAT failist järgmise käsu:
ARJ.EXE a -r -p -va A:\ARHIIV C:\DOC\*.*
ja sooviksite seda käsku jaotada programmi nimest ja eraldi tähistest koosnevateks osajadadeks, siis saaksite kasutada funktsiooni strtok(). Nagu näete, koosneb toodud käsk osajadadest, mis on üksteisest lahutatud ühe või enama tühiku või tabulaatoriga. Seega tuleks nüüd kasutada funktsiooni strtok() osajadade (token) leidmiseks järgmiselt:
char jada[] = "ARJ.EXE a -r -p -va A:\ARHIIV C:\DOC\*.*", *ptr;
...
ptr = strtok(jada, " \t");
while(NULL != (ptr = strtok(NULL, " \t"))) {
printf("Järgmine osajada on: %s", ptr);
}
Esimene kord funktsiooni strtok() kasutades loovutab funktsioon esimesele osajadale näitava viida ja sisestab jadasse selle osajada lõppu sümboli '\0'. Iga järgmine funktsiooni strtok() kasutamine esimese parameetriga NULL loovutab järgmisele osajadale näitava viida ja lisab tolle lõppu jällegi sümboli '\0'. See kestab kuni funktsioon strtok() loovutab väärtuse NULL näitamaks, et rohkem osajadasid ei leidu. Funktsioon strtok() niisiis purustab uuritava jada töö käigus (jaotab ta osajadadeks). Kui see jada on teile veel vajalik, siis salvestage ta sisu mujale, kasutades selleks näiteks funktsiooni strdup().
Sümbolijadade ühendamiseks kasutage funktsiooni strcat() või strncat().
char *strcat(char *dest, const char *src); char far * far _fstrcat(char far *dest, const char far *src); char *strncat(char *dest, const char *src, size_t maxlen); char far * far _fstrncat(char far *dest, const char far *src, size_t maxlen);
Funktsioon strcat() lisab jada src jada dest lõppu. Jada dest peab seega olema küllalt suur, mahutamaks mõlemat jada. Funktsioon strncat() kopeerib maksimaalselt maxlen sümbolit jadast src jada dest lõppu.
Sümbolite jada täitmiseks mingi kindla sümboliga kasutage funktsioone strset() ja strnset().
char *strset(char *s, int ch); char far * far _fstrset(char far *s, int ch); char *strnset(char *s, int ch, size_t n); char far * far _fstrnset(char far *s, int ch, size_t n);
Funktsioon strset() täidab kogu jada s sümbolitega ch. Funktsioon strnset() täidab aga vaid esimesed n jada s sümbolit sümbolitega ch.
Sümbolite jada sisu konvetreerimiseks võib kasutada funktsioone strlwr(), strupr() ja strrev().
char *strlwr(char *s); char far * far _fstrlwr(char far *s); char *strupr(char *s); char far * far _fstrupr(char far *s); char *strrev(char *s); char far * far _fstrrev(char far *s);
Funktsioon strlwr() konverteerib kõik jada s suurtähed (A-Z) vastavateks väiketähtedeks. Funktsioon strupr() seevastu konverteerib kõik jada s väiketähed suurtähtedeks. Ning lõpuks funktsioon strrev() pöörab jada ümber, s.t. viimane sümbol saab esimeseks, lõpust teine teiseks jne. Näiteks strrev("ABC") annab tulemuseks jada "CBA".