C standard függvénytár
Ebben a részben a C nyelv standard függvényeiről lesz szó. Ezek természetesen C++-ban is ugyanúgy használhatók. Mivel rendkívül sok van belőlük, ezért nem próbálom meg ledokumentálni mindet, csak a leggyakrabban használt fejlécek függvényeit írom itt le.
Tartalomjegyzék
-
Az stdio.h
- Definiált típusai
- Globális változói
- printf – szöveg kiírása
- scanf – adatok beolvasása billentyűzetről
- fopen – fájl megnyitása
- fclose – fájl bezárása
- fseek – fájlmutató beállítása
- ftell – fájlmutató helyének lekérdezése
- fprintf és fscanf – szöveges fájlokba való írás és olvasás
- sprintf és sscanf – stringbe írás és olvasás onnan
- vprintf, vscanf, vfprintf, vfscanf, vsprintf, vscanf – print és scanf vektoros változatai
- fgets – egyetlen egy sor beolvasása fájlból
- fputs – szöveg írása a fájlba
- fputc – egyetlen byte kiírása fájlba
- fgetc – egyetlen byte beolvasása
- fwrite – bytesorozat fájlba írása
- fread – byte-sorozat olvasása fájlból
- fflush – fájlbaírás véglegesítése
- feof – fájl végén vagyunk-e?
- ferror – visszatér az utolsó fájlművelet hibakódjával
- clearerr – hibaállapot törlése
- perror – hiba szöveges kiírása
- rename – fájl átnevezése
- remove – fájl törlése
- tmpnam – egy ideiglenes fájlnév kérése
- tmpfile – ideiglenes fájl létrehozása
- Egyéb függvények
-
Az stdlib.h
- Definiált típusok
- rand – véletlenszám generálása
- srand – véletlenszám-generátor alaphelyzetbe állítása
- malloc – memória lefoglalása futás közben
- calloc – nullázott memóriaterület allokálása
- free – lefoglalt memóriaterület felszabadítása
- realloc – lefoglalt terület átméretezése
- strtod – szöveg konvertálása valós számmá
- strtol és strtoul – szöveg konvertálása egész számmá
- exit – kilépés a programból
- atexit – függvény regisztrálása kilépéskori végrehajtásra
- abort – program azonnali leállítása
- getenv – környezeti változó lekérdezése
- system – shell parancs végrehajtása
- qsort – gyorsrendező algoritmus futtatása tömbön
- bsearch – bináris keresés rendezett tömbben
- abs és fabs – abszolút érték számolása
- div és ldiv – egész osztás
- Egyéb függvények
- A math.h
-
A string.h
- memcpy és memmove – memóriablokkok mozgatása
- strcpy és strncpy – szöveges érték másolása
- strcat és strncat – szöveg összefűzése
- memcmp – két memóriaterület összehasonlítása
- strcmp és strncmp – két string összehasonlítása
- memchr, strchr és strrchr – karakter vagy byte keresése a stringben és memóriaterületen
- strcspn és strpbrk – több karakter keresése stringben
- strspn – illeszkedő karakterek számolása a string elején
- strstr – string keresése egy másik stringben
- strtok – string darabokra szedése
- A memset függvény – memóriaterület nullázása
- Az strerror függvény – rendszerhibák szöveges kiírása
- Az strlen függvény – szöveg hosszának lekérdezése
- Egyéb függvények
- Az assert.h fejléc
- Az errno.h fejléc
-
A time.h fejléc
- Típusai
- clock – elhasználnál processzoridő mérése
- difftime – két időpont összehasonlítása
-
mktime –
tm
struktúratime_t
-vé alakítása - time – aktuális idő lekérése
- asctime – idő szöveggé alakítása
- ctime – idő szöveggé alakítása
- gmtime – time_t -ből tm struktúra feltöltése
- localtime – time_t -ből tm struktúra feltöltése
- strftime – formázott kiírása az időnek
- Egyéb fejléc fájlok
Az stdio.h
Ez a fejléc tartalmazza a fájlkezelési és alapvető input/output függvényeket.
Definiált típusai
- FILE
- Struktúra mely egy fájlt ír le. Az elemeit nem kell piszkálni, ezért nem írom őket le itt.
- fpos_t
- Adattípus, mely egy pozíciót jelent egy fájlban.
- size_t
- Előjel nélküli egész szám. Méretekhez használatos, fontos tudni róla, hogy ez egy olyan egész szám, mely annyi bites, ahány bites platformra íródott a program,
tehát 32 biten 4 byte-ot foglal, 64 biten 8-at.
A
sizeof
operátor értéke is ez a típus.
Globális változói
- FILE *stdin
- A standard bemenet handle-je. Alapértelmezésben ez a billentyűzet.
- FILE *stdout
- A standard input handle-je. Alapértelmezésben ez a terminálképernyő.
- FILE *stderr
- A standard hibaeszköz handle-je. Alapértelmezésben ez a terminálképernyő. Nincs pufferelve.
Ezek a standard dolgok átirányíthatók pl. fájlba. De hogy hogyan, az a használt operálciós rendszertől és parancssortól függ. Itt nem megyek ebbe bele.
printf – szöveg kiírása
Segítségével szöveget írhatunk ki a terminálképernyőre.
Prototípusa:
int printf(const char *formatum, ... );
Ez az egyik legfontosabb függvény a C-ben. Így megéri, hogy részletesen is foglalkozzunk vele.
A formatum
paraméter a kiírandó szöveg mintája, a rákövetkező paraméterek pedig a kiírandó adatokat tartalmazzák.
A függvény egy számmal tér vissza, mely a sikeresen kiírt karakterek száma lesz. Hiba esetén az EOF
konstanssal tér vissza.
Egyszerű szöveg kiíratása
Semmi extra:
printf("Hello world!\n");
Értékek beszúrása a kiírt szövegbe
Ha % jelet teszünk a formátum stringbe, akkor azzal jelölhetjük, hogy egy értéket akarunk kiírni. A használathoz érdemes megnézni a nyelvleíró oldal elején a példaprogramot. Az utána írt betűk határozzák meg, hogy mit is akarunk kiírni.
Az adatot pedig a formatum
paraméter után megadott extra paraméterekből veszi szépen sorban.
Formátumkód | Várt adat | Jelentés | Példa | Kiírt érték |
---|---|---|---|---|
%% | - | % jel kiírása | printf("%%") |
% |
%d, %i | int | Előjeles egész szám kiíratása | printf("%d", 6) |
6 |
%u | unsigned int | Előjel nélküli szám kiíratása | printf("%u", 2345678901U) |
2345678901 |
%x és %X | unsigned int | Előjel nélküli szám kiíratása hexadecimálisan. Az %x kisbetűvel a %X nagybetűvel írja a 9 feletti számjegyeket. | printf("%x", 2345678901U) |
8bd03835 |
%o | unsigned int | Előjel nélküli szám kiíratása oktálisan (8-as számrendszerben). | printf("%o", 17) |
21 |
%e és %E | double | Lebegőpontos szám kiíratása exponenciális alakban. A kettő között csak az exponenst jelölő E betű a különbség (hogy kicsi vagy nagybetű-e). | printf("%e", 0.123456789) |
1.234568e-01 |
%f | double | Lebegőpontos szám kiíratása tizedestörtként | printf("%f", 0.123456789) |
0.123457 |
%g és %G | double | Lebegőpontos szám kiíratása, a %g az %e és az %f közül választja ki a rövidebbet, %G esetén pedig az %E és %f közül. | printf("%g", 0.123456789) |
0.123457 |
%c | int | Karakter kiírása. | printf("%c", 65) |
A |
%s | const char* | String kiíratása | printf("%s", "Akármi.") |
Akármi. |
%p | const void* | Kiírja az átadott mutató által mutatott hely sorszámát. | printf("%p", "Akármi.") |
0x8048672 |
%n | int* | Nem ír ki semmit, de az átadott mutató által mutatott helyre beírja, hogy eddig hány karaktert írt ki. | printf("1234%n", &x) |
Az x típusa int, értéke 4 lesz. |
Hossz módosítók
Az előbb említett formátumtípusok az alapértelmezett típusra, tehát int
-re és double
-ra vonatkoztak.
Ha szeretnénk, hogy más méretű adatokat is tudjunk kezelni, arra is van mód. Ekkor a típus jelölő elé a hosszt jelölő betűt is oda kell írni.
Ezek a betűk a következők:
- h
- Egész számot váró típusok (i, d, o, u, x, X) esetén
int
ésunsigned int
helyettshort
-ot ésunsigned short
-ot vár majd. - l
-
- Egész számot váró típus (i, d, o, u, x, X) esetén.
long
-ot ésunsigned long
-ot vár majd. Ezek a típusok lehetnek nagyobbak, mint azint
, ezért kell jelölni őket. - Karakteres adatot váró típus (c, s) esetén
wchar_t
típusú karaktert, illetve stringet vár.
- Egész számot váró típus (i, d, o, u, x, X) esetén.
- L
- Lebegőpontos számot váró típusoknál (e, E, f, g, G), a paramétert
long double
típusúként fogja kezelni.
Néhány példa: %hu
(unsigned short-hoz), %ls
(wchar_t stringekhez).
Ha long long
típusú adatot akarunk kiíratni,
akkor annak van az ll
hossz módosító,
de ez nem szabványos, és fordítónként más és más való a 64 bites számok kezelésére.
Mezőszélesség
A típus, hosszmegadás elé írható még számmal a mezőszélesség, azaz, hogy hány karakteren szeretnénk kiírni az adott dolgot, ez akkor hasznos, hogy ha táblázatosan akarunk kiírni valamit.
Ez a mezőszélesség minimális érték, ha a szám hosszabb ennél, akkor teljes mértékben ki lesz írva. Ha *-ot írunk a szám helyére, akkor a soron következő (int
) paraméterből veszi a mezőszélesség értékét.
Alapértelmezésben ebben a mezőben jobbra igazítja az értéket. Alapértelmezett értéke 0.
Példa: %20s
- legalább 20 karakter hosszú szöveg kiíratása jobbra igazítva.
Pontosság
A mezőszélesség kiegészíthető pontossággal, hogy ha utána ponttal elválasztva odaírjuk számként. Jelentése típusonként változhat:
- Egész számok (d, i, o, u, x, X) esetén, a kiírandó számjegyek minimális száma. Ha a szám rövidebb ennél, akkor az balról nullákkal lesz kiegészítve.
Alapértelmezett értéke ez esetben 1. Ha 0-ra állítjuk, akkor a 0 számot nem fogja kiírni. Pl.
printf("%.8d", 12)
, a 00000012-t írja ki. - Lebegőpontos számok esetén, a e, E, f típus esetén, a kiírandó tizedes számjegyek számát határozza meg.
Alapértelmezése erre az esetre 6. Pl.
printf("%10f", 0.123456789)
a 0.1234567890-t fogja kiírni. - Lebegőpontos számok esetén a g és G típus esetén, a kiírandó legnagyobb helyirértékű számjegyek számát határozza meg. Alapértelmezése 6 ebben az esetben is.
Pl.
printf("%.5g", 1234.56789)
1234.6-ot fog kiírni. - Stringek esetén (s típus). A maximálisan kiírandó karakterek számát határozza meg. Alapértelmezésben a kiírás addig tart, amíg az stringet lezáró 0 kódú karakter el nem éri.
Pl.
printf("%.10s", "Hello world!")
Annyi fog csak kiírni, hogy „Hello world”. - A többi típusra nincs hatással.
Néhány hasznos példa:
%.0f
: lebegőpontos szám kiírása egészre kerekítve.%20.20s
: szöveg kiírása 20 karakter hosszú mezőbe, levágva ha túl hosszú.
Flag-ek
Az egész eddigi elé még oda tehetjük a következő flag-eket (mindegyikből legfeljebb egyet tetszőleges sorrendben:
- -
- Balra igazít a megadott mezőben, jobbra igazítás helyett. Nyilván csak akkor van értelme, ha adtunk meg mezőszéllességet.
- +
- Kiírja a + jelet a pozitív számok esetén, az o, x és X típusok kivételével.
- (szóköz)
- Ha nem lesz előjel írva, akkor egy szóközt ír. Hasznos adatsorok kiírásánál, ha azt szeretnénk, hogy függőlegesen azonos pozíción kezdődjenek a számok.
- #
-
- Az o, x és X típusok esetén a szám elé kiírja a 0, 0x és 0X típusokat.
- Az e, E, f típusok esetén a tizedespont akkor is ki lesz írva, hogy ha nincs utána tizedesjegy.
- A g és G típusok esetén a tizedespont után törtrész végén a nullák meg lesznek hagyva (alapértelmezésben levágja őket).
- 0
- A mezőt balról nullákkal tölti fel az érték előtt. Nyilván csak akkor van értelme, hogy ha adtunk meg mezőszélességet, és jobbra igazítunk. Akkor sincs sok értelme, hogy ha meg van adva a - flag, mert akkor tuti nem lesz semmi sem az adat előtt, amit feltölthetnénk nullákkal.
Példák:
%#010x
: Szám kiírása 16-os számrendszerben, balról nullákkal kibővítve, 8 számjegyen 0x-et elé téve (beleszámít a mezőbe).%-20.20x
: Szöveg kiírása 20 karakter mezőszélességen, levágva, ha túl hosszú, balra igazítva.
És ezzel a függvény végére értünk.
scanf – adatok beolvasása billentyűzetről
A kiíró függvény párja a beolvasó, mellyel a billentyűzetről kérhetünk be adatokat adott formátumban. A függvény hívásakor a program megáll, és arra vár, hogy beírjunk valamit a terminálba és entert üssünk rá (mint valami parancsértelmező esetén). Ezt azért teszi, mert a standard inputról olvas, és ha nem áll rendelkezésre adat (tehát az input puffer üres), akkor vár, hogy a felhasználó begépelje azt, az enter leütése adja hozzá az adatot az input pufferhez. Ez azért fontos, hogy megértsük, hogy hogyan is működik ez a függvény.
Szintaxis:
int scanf ( const char * formatum, ... );
A formatum
paraméter tartalmazza a beírandó szöveg formátumát, a többi paraméter pedig memóriacím, ahová a beolvasott értékek kerülnek.
A standard inputról beolvassa a szükséges karaktereket, a többit az input pufferben hagyja.
A függvény visszatérési értéke a sikeresen beolvasott értékek száma lesz. (Viszont a %n -hez beolvasott adatot nem számolja bele.)
Ha egy értéket se tudtunk sikeresen beolvasni és az input végére érünk mielőtt a függvény végigérne a formatum
stringen, akkor a függvény EOF konstans értékkel tér vissza (ezt az stdio.h-ban #define-olták).
Alapértelmezésben a standard input a billentyűzet, melynek nincs vége, ha a standard input puffer kiürül, akkor a programunk egyszerűen vár, hogy beírjunk valamit. Így ebben az esetben soha sem kaphatunk EOF-ot. Egyetlen eset, amikor EOF-ot kaphatunk, amikor parancssorban átirányítjuk a standard bemenetet, hogy fájlból olvasson, na annak van vége valahol.
A függvény az általunk beírt szöveget elkezdi értelmezni miközben olvassa a formátum stringet. A formátum string karakterei a következőket jelentik:
- Whitespace karakter (' ', '\b', '\t', '\n', '\v', '\f', '\n')
- Jelzi, hogy az aktuális helyen tetszőleges számú (több is, de akár egy sem) whitespace karakter következhet. Addig olvas, amíg egy nem whitespace karakterbe nem ütközik.
- % karakter
- A printf-hez hasonlóan ez is egy adatformátumot határoz meg, csak most nem kiíráshoz, hanem a beolvasáshoz.
- Egyéb karakter
- Ez esetben a beolvasáskor az megadott szövegben az adott karaktert fogja várni, ha nem egyezik meg, akkor hiba történt, és a függvény kilép.
Formátum típusok
A következő táblázatban foglalom össze ezeket.
Típus kód | Várt típus | Jelentés | Példa | Beírt szöveg | Beolvasott érték |
---|---|---|---|---|---|
c | char * | Egy darab karaktert olvas és eltárolja a változóban | scanf("%c", &c) |
ABCDEFGHI |
'A' |
d | int * | Előjeles egész számot olvas be és tízes számrendszerben értelmezi azt, opcionálisan lehet előtte egy + vagy egy - karakter előjel gyanánt,
illetve az olvasás elején elfogyasztja a whitespace karaktereket is. A számnak az int típus értelmezési tartományába kell esnie,
ezen kívül eső esetekre a függvény nincs definiálva, valószínűleg valami szemetet ír a változóba. |
scanf("%d", &d) |
2131233 |
2131233 |
u | unsigned int * | Előjel nélküli egész számot olvas be és tízes számrendszerben értelmezi azt, opcionálisan lehet előtte egy + vagy egy - karakter előjel gyanánt.
A számnak az unsigned int típus értelmezési tartományába kell esnie,
ezen kívül eső esetekre a függvény nincs definiálva, valószínűleg valami szemetet ír a változóba.
|
scanf("%u", &u) |
2345678901 |
2345678901 |
i | int * | Egész számot olvas be és adattól függően 8-as, 16-os vagy 10-es számrendszerben értelmezi azt (attól függően, hogy 0-val vagy 0x-szel kezdődik-e), opcionálisan lehet előtte egy + vagy egy - előjelnek.
Az olvasás elején előtte elfogyasztja a whitespace karaktereket is. A számnak az int típus értelmezési tartományába kell esnie,
ezen kívül eső esetekre a függvény nincs definiálva, valószínűleg valami szemetet ír a változóba. |
scanf("%i", &i) |
011 |
9 |
e, E, f, g, G | float * | Lebegőpontos számot olvas be. Lehet tizedes tört alakban (123.3456), lehet előtte előjel, illetve lehet tudományos alakban is elfogadja (123.24676e+20). Az olvasás elején előtte elfogyasztja a whitespace karaktereket is. Ha a szám túl nagy vagy túl kicsi, akkor az érték 0 lesz, ha a szám nagyságrendje túl nagy, akkor az IEEE szerinti mínusz vagy plusz végtelen. | scanf("%f", &f) |
1234.5678e4 |
12345678.0f |
o | unsigned int * | Egész számot olvas be 8-as számrendszerben. Az olvasás elején előtte elfogyasztja a whitespace karaktereket is. A számnak az unsigned int típus értelmezési tartományába kell esnie,
ezen kívül eső esetekre a függvény nincs definiálva, valószínűleg valami szemetet ír a változóba. |
scanf("%o", &o) |
12 |
10 |
x, X | unsigned int * | Egész számot olvas be 16-os számrendszerben. Az olvasás elején előtte elfogyasztja a whitespace karaktereket is. A számnak az unsigned int típus értelmezési tartományába kell esnie,
ezen kívül eső esetekre a függvény nincs definiálva, valószínűleg valami szemetet ír a változóba. |
scanf("%x", &x) |
FF |
255 |
s | char * | Beolvas egy szót a standard inputról. Az olvasás elején előtte elfogyasztja a whitespace karaktereket is. Addig olvas, míg egy whitespace karaktert nem talál. Az eredményt a címen lévő memóriaterületre írja. Mivel semmi ellenőrzés nincs, hogy arra a területre mennyi karakter fér el, ezért meg van a lehetősége annak, hogy többet olvassunk a kelleténél, így túl írjuk a területet, ezért nem javasolt a scanf-fel szavakat olvasni. Inkább használjunk fgets-t. | scanf("%s", s); s egy karaktertömb. |
Hello world! |
"Hello" |
n | int * | Nem olvas semmit sem a standard inputról, hanem letárolja az eddig beolvasott karakterek számát. | scanf("%d%n", &d, &n); |
1234567 |
n = 7 |
% | - | A % jelet várja az adott helyen | scanf("%% %d", &d); |
%1234 |
d = 1234 |
Hossz módosítók
Ha nem int-be vagy float-ba akarunk beolvasni, hanem más adattípusokba, akkor arra is van lehetőségünk, ha a típusok elé egy hossz módosítót írunk.
- h
- Segítségével egész számok esetén (d, i, o, u, x, X)
int
ésunsigned int
helyettshort
ésunsigned short
típusú értéket olvas. - l
- Segítségével egész számok esetén (d, i, o, u, x, X típusok)
int
helyettlong
, illetveunsigned int
helyettunsigned long
típusú értéket olvas változóba. Lebegőpontos számok (e, E, f, g, G típusok),float
helyettdouble
típusú adatot olvas. - L
- Lebegőpontos számok esetén (e, E, f, g, G típusok),
float
helyettlong double
típusú adatot olvas.
Például a %lf típus alkalmazandó, amikor double
értéket olvasunk be.
Maximálisan beolvasandó karakterek száma
A típusmegadás elé számmal odaírhatjuk, hogy legfeljebb mennyi karaktert olvashatunk be, a megadott számú karakter beolvasása után aktuális olvasási művelet leáll (és megy tovább az input, ha van még valami olvasandó).
Például, ha azt írjuk, hogy scanf("%5d", &d)
, és azt írjuk be, hogy 123456789, akkor azt olvassa be, hogy 12345, többi karakter az input pufferben marad.
Ha %s
-t használunk, érdemes megadni a maximálisan beolvasható hosszt is.
Kihagyandó értékek
Ha a formátum megadás legelejére *-ot teszünk, akkor az az érték értelmezve lesz, de nem lesz eltárolva a változókban. A *-gal jelölt értékek nem számolódnak bele a visszatérési értékbe.
Például hogy azt írjuk, hogy scanf("%d %*d %d", &d, &d2)
és azt írjuk be, hogy 123 456 789
, akkor d=123 és d2=789 lesz, a középső egész szám ki lesz hagyva,
és a függvény visszatérési értéke 2 lesz, mert mind a két változónak sikerült értéket adni.
Példák
Pontosvesszővel elválasztott értékek beolvasása
scanf("%d;%d;%d", &a, &b, &c)
. Ez a forma szigorú, ha az összes számot be akarjuk olvasni, akkor nem üthetünk szóközt a számok közé, tehát ezt kell írnunk:
123;567;2134
. Ha szóközt írnánk, akkor a beolvasás meghiúsul, és a függvény 1-gyel tér vissza a 3 helyett (mivel csak 1 értéket sikerült neki beolvasnia, a többit nem.)
A szeretnénk szóközt engedni, akkor tegyünk szóközt a formátum stringbe: scanf("%d ; %d ; %d", &a, &b, &c)
. Ekkor már a 123 ; 123123 ; 5656
, esetet is kezelni tudja.
Az input pufferben maradt karakterek esete
Tegyünk fel, hogy 3 egész számot kérünk be egymás után 3 scanf utasítást használva, valahogy így:
printf("Kérem az első számot:"); scanf("%d", &a); printf("Kérem a második számot:"); scanf("%d", &b); printf("Kérem a harmadik számot:"); scanf("%d", &c);
És erre mi beírjuk, hogy 1 2 3
. Ekkor a második és a harmadik scanf nem fog várni, hanem azonnal visszatér, és a terminálban valami ilyesmi fog megjelenni:
Kérem az első számot:1 2 3 Kérem a második számot:Kérem a harmadik számot:
Az történt, hogy beletettük az input pufferbe az 1 2 3
stringet, az első scanf csak az 1-et olvasta ki, a maradék 4 karakter ott maradt, melyet a következő scanf utasítások használtak fel.
Az ilyen dolog nyilván nem szerencsés egy párbeszédes (parancssoros) rendszerben. Ennek a megoldására az fgets és az sscanf-et kell kombinálni, erről majd később.
fopen – fájl megnyitása
És ezzel áttérünk a fájlkezelésre.
Ez a függvény megnyit egy fájt. Természetesen ilyenkor nem arra kell gondolni, mint a mindennapi életben, hogy elindul a hozzá társított program, hanem arra, hogy az operációs rendszer betölti a memóriába azt, és ekkor beleírhatunk, illetve olvashatunk belőle.
Szintaxis:
FILE * fopen(const char * fajlnev, const char * mod);
- fájlnév
- A fájl neve, mely lehet relatív az aktuális könyvtárhoz képest, de lehet abszolút is. Értelmezése a használt operációs rendszertől függ.
- mód
- A fájl megnyitásának a módja, ezt mindjárt bővebben részletezem.
A visszatérési értéke egy mutató FILE struktúrára, amit nem kell babrálnunk, csak a mutatót továbbpasszolni a többi fájlkezelő függvénynek. Ha a megnyitás sikertelen (általában azért, mert nincs meg a fájl), akkor NULL mutatóval tér vissza.
Fájl megnyitás módjai
A mód stringek a következők lehetnek:
- r
- Fájl megnyitása olvasásra, a fájlmutató a fájl elején lesz. Írásvédett fájlok megnyithatók ebben a módban. A fájlnak léteznie kell.
- r+
- Mint az "r". A fájl megnyitása olvasásra és írásra is.
- w
- Üres fájl megnyitása írásra, ha a fájl már létezik, akkor felül lesz írva.
- w+
- Mint a "w", csak ebben a módban olvasni is lehet a fájlból, nem csak írni bele.
- a
- Fájl megnyitása hozzáfűzésre, ekkor a fájlmutató a fájl végén áll, tehát hozzáírni tudunk. (Jó dolog, például naplófájlok írására.)
- a+
- Mint a "a", csak ebben a módban olvasni is tudunk a fájlból.
A formátum string végére még odaírhatunk egy b-t és egy t-t jelezve, hogy a fájlt bináris módban akarjuk megnyitni, vagy szöveges módban. Bináris módban a fájlt úgy kezeljük, mint byte-ok sorozatát. szöveges módban, mint karakterek sorozatát, ilyenkor a byte-oknak operációs rendszertől függően speciális jelentésük lehet. Például Windows-on "\r\n" karakterpárost veszi az újsor karakternek, és azt "\n"-re fordítja, íráskor meg visszafelé, valamint a 26-os kódú karaktert fájl vége karakternek értelmezi. A szöveges módot akkor érdemes használni, hogy ha tudjuk, hogy a fájlban szöveg van, különben bináris módot használjunk.
A + -os módok ritkán használatosak, egyszerűen azért, mert a fájlba általában már csak a végeredményt írjuk, ritka, hogy egyszerre olvasnunk kellene, és írni is.
Ha fájlba írás után olvasni is szeretnénk, véglegesíteni kell a módosításokat majd az fflush
függvénnyel.
Az előbb említett fájlmutató pedig egy olyan dolog, mint a szövegszerkesztéskor a kurzor, tehát ha írunk a fájlba, akkor előre ugrik a következő byte-ra,
ha olvasunk, akkor is (mintha csak egy jobbra nyilat nyomtunk volna). Ez a kurzor viszont átíró módban van, tehát nem lehet csakúgy beszúrni dolgokat a fájlba.
Csak a kurzornál lévő adatot olvashatjuk, vagy írhatjuk. A kurzor helyét az ftell
függvény mondja meg, beállítani pedig az fseek
függvénnyel lehet.
Tehát ezért a későbbiekben külön nem fogom említeni, hogy hova írjuk az adatot a fájlba, mindig a fájlmutatóhoz, mely annyit ugrik előre, ahány byte-ot írtunk. Olvasásnál is.
fclose – fájl bezárása
Ha végeztünk a fájllal, akkor ezzel a függvénnyel lezárhatjuk.
Szintaxisa:
int fclose(FILE *fajlHandle);
Ez a függvény lezárja a korábban megnyitott fájl handle-t. A függvény visszatérési értéke 0, ha minden rendben zajlott, különben az EOF konstans. Ez a függvény írja ki a lemezre a kimeneti pufferből a még ki nem írt adatokat, és az operációs rendszerrel lezáratja a fájlt. A lemezre írás lehet, hogy sikertelen lesz, ezért lezáráskor is ellenőrizni kell, hogy függvény mivel tér vissza. (Eddig én sem törődtem ezzel. De most már fogok :) )
A bezárás után a fájl handle érvénytelen lesz, tovább nem használható.
fseek – fájlmutató beállítása
Ez beállítja a fájlmutatót egy adott pozícióra a fájlon belül.
Szintaxis:
int fseek(FILE *fajlHandle, long int relativPozicio, int viszonyitasiPont);
- fájlHandle
- Az fopen által visszaadott handle.
- relatívPozíció
- Relatív pozíció a viszonyítási ponthoz képest
- viszonyitásiPont
-
A következő értékei lehetnek:
- SEEK_SET
- A fájl eleje
- SEEK_CUR
- A fájlmutató aktuális helye.
- SEEK_END
- A fájl vége.
A függvény visszatérési értéke 0, hogy ha a függvény sikeresen lefutott, különben egy nem nulla érték.
ftell – fájlmutató helyének lekérdezése
Szintaxis:
long int ftell(FILE *fájlHandle);
Visszatér a fájlmutató pozíciójával, mely bináris mód esetén a byte-ok száma a fájl elejétől számolva. Szöveges mód esetén ez nem biztos,
de arra használható, hogy később fseek
-kel újra visszatérjünk az aktuális pozícióra. Hiba esetén -1-gyel tér vissza.
A függvény egyetlen paramétere egy érvényes fájl handle.
fprintf és fscanf – szöveges fájlokba való írás és olvasás
Ideje, hogy írjunk és olvassunk is fájlokból. Első körben a szöveges fájlokról lesz szó, melyek szöveget tartalmaznak. A printf és scanf függvényeket már ismerjük korábbról, fájlok esetén is ugyanazt csinálják. A fájlok esetén a szintaxis hasonló:
int fscanf(FILE *fajlHandle, const char *formatum, ...); int fprintf(FILE *fajlHandle, const char *formatum, ...);
Az egyetlen extra paraméter egy fájl handle, melyet a fájlba való íráshoz illetve az onnan való olvasáshoz használunk. A fprintf a fájlmutató helyétől kezdve felülírja a fájl tartalmát. Az fscanf pedig a fájlmutató aktuális helyétől olvas.
Az fprintf
függvény visszatérési értéke a sikeresen kiírt byte-ok száma, hiba esetén EOF. Ilyen hiba akkor történik, hogy ha megtelik a
lemez, vagy elérjük a kvótát.
Az fscanf
függvény a sikeresen beolvasott értékek számával tér vissza, hiba esetén az EOF konstans értékével.
sprintf és sscanf – stringbe írás és olvasás onnan
A printf és a scanf azon változata, mely egy stringből olvas, illetve ír oda, tehát a memóriában végez műveleteket. Szintaxisuk:
int sprintf(char *str, const char * format, ... ); int sscanf(const char *str, const char * format, ...);
Az sprintf
az str
által megadott memóriaterületre írja a kimenetet.
Mivel nincs mód arra, hogy megadjuk, hogy legfeljebb mennyit írjon, így könnyen túl sokat írhat ki,
és ebből baj lehet. Ezt elkerülhetjük megfelelő formátummegadással, %s esetén megadni a maximális hosszt, %f-t pedig nem használni.
Az sscanf
használata biztonságos, mivel a függvény addig olvas, amíg a 0-ás kódú karakterig el nem jut, olyankor pedig úgy viselkedik, mintha a fájl végére ért volna.
vprintf, vscanf, vfprintf, vfscanf, vsprintf, vscanf – print és scanf vektoros változatai
Teljesen ugyanazt csinálják, mint a v nélküli párjuk, csak ezek ... helyett egy va_list-et kapnak utolsó paraméterként. Szintaxis:
int vfscanf(FILE *fajlHandle, const char *formatum, va_list extraArgumentumok); int vfprintf(FILE *fajlHandle, const char *formatum, va_list extraArgumentumok); int vsscanf(const char *string, const char *formatum, va_list extraArgumentumok); int vsprintf(char *string, const char *formatum, va_list extraArgumentumok); int vscanf(const char *formatum, va_list extraArgumentumok); int vprintf(const char *formatum, va_list extraArgumentumok);
Ezek akkor használatosak, hogy ha olyan függvényben vagyunk, amely tetszőleges számú paraméterrel rendelkezhet. Nyilván a függvényparaméterek végén lévő ...-ot nem lehet továbbadni a hasonló paraméterezésű függvényeknek sehogy másképp.
fgets – egyetlen egy sor beolvasása fájlból
Beolvas a fájlból egy sort. Szintén szöveges módban megnyitott fájloknál használatos. Szintaxisa:
char *fgets(char *str, int maxhossz, FILE *fajlHandle);
- str
- A mutató a területre, amelybe olvasunk.
- maxhossz
- A maximális hossza a stringnek.
- fajlHandle
- Handle a fájlra, melyből olvasunk.
Sikeres beolvasás esetén az str
paraméter értéke, különben NULL.
Ez a függvény addig olvas a fájlból, amíg be nem olvasott maxhossz-1 db karaktert, egy sorvégjelet nem talált vagy elérte a fájl végét. Azért maxhossz-1 db karakternél áll meg, mert kell a hely a szöveget lezáró 0 byte-nak. Ha sorvégjel állítja meg a beolvasást, akkor a stringben benne lesz a sorvég jel is.
A függvény használható arra, hogy egy teljes sort olvashassunk be a standard inputról, így nem kell attól tartanunk, hogy a maradék adat átfolyik a többi scanf-re (ezt a problémát korábban említettem):
char string[1000]; fgets(string, 1000, stdin);
Ez egy max. 1000 byte hosszúságú sort olvas be a standard inputról.
Ezt a szöveget később a sscanf
függvénnyel a scanf-hez hasonlóan kezelhetjük.
fputs – szöveg írása a fájlba
Az fgets
párja, ez a fájlba írja a szöveget. Szintaxisa:
int fputs(const char *str, FILE *fajlHandle);
- str
- A kiírandó szöveg
- fajlHandle
- Handle a fájlra, amelybe írunk.
Sikeres művelet esetén, egy 0 vagy pozítív értéket kapunk, hiba esetén EOF-ot.
Használjuk ezt a függvényt fprintf
helyett, ha egy kész stringünk van, amelyet fájlba akarunk írni,
mert gyorsabb (nem kell a % jeles dolgokkal külön foglalkoznia).
fputc – egyetlen byte kiírása fájlba
Egyetlen egy tetszőleges byte fájlba való írására szolgál. Szintaxisa:
int fputc(int byte, FILE *fajlHandle);
- byte
- A kiírandó byte. Hiába int a típusa csak a legalsó helyi értékű byte lesz kiírva.
- fájlHandle
- A fájl handle-je, melybe írunk.
A függvény visszatérési értéke az byte, amit kiírtunk, hiba esetén az EOF konstans értéke.
fgetc – egyetlen byte beolvasása
Egyetlen egy byte beolvasása a fájlból. Szintaxisa:
int fgetc(FILE *fajlHandle);
- fájlHandle
- A fájlhandle a fájlhoz, melybe írni akarunk.
A függvény visszatérési értéke az olvasott byte. Hiba esetén pedig az EOF konstans (mely negatív).
fwrite – bytesorozat fájlba írása
Tetszőleges bytesorozat fájlba írása. Ez bináris módban megnyitott fájlok esetén használandó. Szintaxisa:
size_t fwrite(const void *adat, size_t rekordmeret, size_t darabszam, FILE *fajlHandle);
- adat
- Mutató az adatra, amit a fájlba akarunk írni.
- rekordméret
- Egy adatrekord mérete.
- darabszám
- Kiírandó adatrekordok száma.
- fájlHandle
- A fájlhandle a fájlhoz, melybe írni akarunk.
A függvény visszatérési értéke a sikeresen kiírt adatrekordok száma, mely jó esetben pont a megadott darabszám, vagy kevesebb, ha kevesebb, akkor az hibát jelent.
A függvény rekordméret*darabszám byte-ot fog kiírni az data mutató által mutatott területről a fájlba. A függvény hívójának kell gondoskodnia arról, hogy megfelelőek mennyiségű adatot írunk ki.
Gyakori használati eset, hogy a darabszám értéke 1, és a rekordméret adja meg a teljes kiírandó adat méretét.
Fontos dolog, amire figyelnünk kell, hogy az adatokhoz tartozó byte-sorozatok processzor architektúránként és fordítónként mások lehetnek. Ezért soha ne írjunk fájlokba vagy olvassunk fájlokból teljes struktúrákat, hanem egyenként a mezőket. Egész számok lehetnek little endian, big endian, esetleg middle endian formában tárolva, a lebegőpontos számok se feltétlenül IEEE formában vannak tárolva (ez a leggyakoribb formátum a lebegőpontos számok tárolására). Ha valami saját fájlformátumot csinálunk, akkor azt érdemes ledokumentálni.
fread – byte-sorozat olvasása fájlból
Tetszőleges byte-sorozat fájlból való beolvasása. Ez is bináris módban használandó.
Az eggyel fentebb említett fwrite
függvénnyel analóg, csak ez épp a fordított irányban működik. Szintaxisa:
size_t fread(void *adatterulet, size_t rekordmeret, size_t rekordszam, FILE *fajlHandle);
- adat
- Mutató a területre, ahová a fájlból akarunk olvasni.
- rekordméret
- Egy adatrekord mérete.
- darabszám
- A beolvasandó adatrekordok száma.
- fájlHandle
- A fájlhandle a fájlhoz, melyből olvasni akarunk.
A függvény visszatérési értéke a sikeresen beolvasott adatrekordok száma, mely jó esetben pont a megadott darabszám, vagy kevesebb, ha kevesebb, akkor az hibát jelent.
fflush – fájlbaírás véglegesítése
Írási műveletek után véglegesíti az írást (tehát kiírja a lemezre azt). Tehát e függvény hívása után biztos, hogy lemezre kerül, amit kiírtunk. Szintaxisa:
int fflush(FILE *fajlHandle);
- fájlHandle
- A fájlhandle a fájlhoz, melyen a műveletet végeztük.
A függvény visszatérési értéke 0, ha a művelet sikeres, EOF, ha sikertelen.
A írási művelet véglegesítése manapság már nem jelenti azt, hogy tényleg ott lesz a lemezen az adott dolog. Mivel az operációs rendszer fenntarthat valamilyen cache-t, illetve a merevlemezekbe is lehet egyfajta cache építve. De annyi biztos, hogy e művelet sikeressége után más programok is biztosan elérhetik, mindazt, amit kiírtunk. A művelet például akkor lehet sikertelen, hogy ha megtelt a lemez. Fájlok bezárásakor automatikusan megtörténik ez a művelet.
feof – fájl végén vagyunk-e?
Megnézi, hogy a fájl végén vagyunk-e. Szintaxis:
int feof(FILE *fajlHandle);
Visszatérési értéke nullától különböző (tehát igaz), ha tényleg a fájl végén vagyunk, különben nulla.
Tehát a fájlmutató az utolsó utáni helyen áll. Ilyenkor további olvasás nem lehetséges, az írási műveletek pedig hozzáfűznek adatokat a fájlhoz.
ferror – visszatér az utolsó fájlművelet hibakódjával
Megnézi, hogy történt-e hiba a fájl kezelése közben. Szintaxis:
int ferror ( FILE *fajlHandle);
- fájlHandle
- A fájlhandle a fájlhoz, melyen a műveletet végeztük.
Ha a fájlban történt hiba, akkor értéke nullától különböző (igaz), különben nulla (hamis).
Hiba például akkor történik, hogy ha egy olvasásra megnyitott fájlba írni szeretnénk.
clearerr – hibaállapot törlése
Törli a hibaindikátorokat.
void clearerr(FILE *fajlHandle);
Mivel ha korábban hibát okoztunk (tehát az ferror hibát jelez), akkor az összes művelet, melyet a fájlon végzünk hibát fog jelezni addig, amíg nem töröljük a hiba állapotot. Így a hiba állapotát törölni kell.
perror – hiba szöveges kiírása
Értelmezi a globális errno
változó értékét, és az alapján kiír egy hibát a hibaeszközre (stderr). Szintaxis:
void perror(const char *str);
- str
- Egy string, amit a hibaüzenet elé ír majd ki.
Ez a függvény különösen hasznos, ha csak a hibát akarjuk kiírni, ugyanis nem
nekünk kell külön-külön az összes hibakódhoz a megfelelő hibaüzenetet előállítanunk.
Tipikus használat:
//... FILE *f = fopen("nincsilyen.txt", "r"); if (!f) { perror("Nem sikerült megnyitni a fájlt."); return -1; } //...
Ilyenkor valami ilyesmit ír ki:
Nem sikerült megnyitni a fájlt: No such file or directory
rename – fájl átnevezése
Fájl átnevezése. Szintaxis:
int rename(const char *regiNev, const char *ujNev);
A régiNév nevű fájlt átnevezi az újNév névre. Rendszertől függően az újNév lehet komplett elérési útvonal, ekkor átmozgatás történik.
Ha a művelet sikeres volt, akkor a visszatérési értéke 0. Különben egy különböző érték.
remove – fájl törlése
Fájlt töröl. Szintaxisa:
int remove(const char *fajlNev);
A megadott nevű fájlt véglegesen letörli.
Sikeres művelet esetén a visszatérési értéke 0. Különben egy más érték.
tmpnam – egy ideiglenes fájlnév kérése
Egy olyan fájlnévvel tér vissza, mely biztos nem egyezik egyik meglévő nevével sem. Szintaxis:
char *tmpnam(char *str);
- str
-
Egy karaktertömb, melyben tárolva lesz a név. Ez lehet NULL, ha azt akarjuk, hogy egy belső statikus tömbbe kerüljön a név.
Tömbnek legalább
L_tmpnam
db (ez egy konstans) karaktert kell tudnia tárolnia.
Ha megadtunk egy saját tömböt paraméterként, akkor abba írja a fájlnevet, és visszatér vele. Ha NULL-t adunk meg, akkor a belső tömbbe írja a fájlnevet, és azzal tér vissza. Ha nem sikerül valamiért fájlnevet találnia, akkor NULL értékkel tér vissza.
A kapott fájlnevet felhasználhatjuk arra, hogy egy ideiglenes fájlt hosszunk létre.
tmpfile – ideiglenes fájl létrehozása
Léterhoz egy ideiglenes fájlt, mely automatikusan törlődik, amikor bezárjuk. Szintaxis:
FILE *tmpfile(void);
A függvény visszatér egy fájl handle-val, mely "w+b" módban lett megnyitva, tehát egy üres bináris módban megnyitott fájl, melybe írhatunk, és olvashatunk is belőle.
A fájl fclose
hívásakor, vagy a programból való kilépéskor törlődni fog.
Egyéb függvények
Sok függvény van, még ebben a fejlécben, csak a legfontosabbakat emeltem ki a külön. A következő listában a többiről is írok pár szót azért. Nyilván a tájékoztatás nem teljeskörű, meg általában ezeket a függvényeket nem szoktuk használni.
- FILE *freopen(const char *fajlNev, const char *mod, FILE *fajlHandle);
- Mint az
fopen
, csak előtte még lezár egy létező fájl handlet, mely ha sikeres volt, akkor újra megnyit egy fájlt. - void setbuf(FILE *fajlHandle, char *puffer);
- Saját cache puffert állít be a fájlhoz. Ez a függvény főleg akkor hasznos, amikor azt akarjuk, hogy egy fájl ne használjon cache puffert, hanem amint lehet írja lemezre, amit ráírunk, ekkor a puffer paramétere NULL. Természetesen a puffer nélküli írásnak az az ára, hogy lassabb lesz. Fájl megnyitása után hívandó, mielőtt bármi mást csinálnánk a fájllal.
- int setvbuf(FILE *fajlHandle, char *puffer, int mod, size_t meret);
- Mint az előző, csak finomabb hangolás lehetséges. Ez is közvetlenül fájlnyitás után hívandó.
- int getc(FILE *fajlHandle);
- Teljesen ugyanaz, mint az
fgetc
csak ez makró, így nem javaslom a használatát, mert furcsa bugok történhetnek. - int getchar(void);
- Lényegében
fgetc(stdin)
. - char *gets(char *str);
-
Az
fgets
csak az standard inputon (stdin). Történelmi okokból ez a függvény nem támogatja azt, hogy megadjuk a karaktertömb maximális méretét, így nem ajánlott használni. - int putc(int character, FILE *fajlHandle);
- Teljesen ugyanaz, mint az
fputc
csak ez makró, így nem javaslom a használatát, mert furcsa bugok történhetnek. - int putchar(int karakter);
- Lényegében
fputc(karakter, stdin)
. - int puts(const char *str);
- Lényegében
fputs(str, stdout)
, csak az még egy entert üt utána (újsor karaktert ír). - int ungetc(int karakter, FILE *fajlHandle);
-
Visszarakja a legutóbb olvasott karaktert (vagy egy másikat) az input-ba. Lényegében az előző
fgetc
visszavonása. Azonban ennek a soron következő input műveletekre van csak hatása a fájlba ténylegesen nem fog bekerülni semmi. A fájlmutató helyének a megváltoztatása töröl minden így visszarakott karaktert. Mindennapi használatban nincs szükség erre a függvényre, viszont nagyon jól jön, amikor fordítóprogramot, vagy valami összetettebb parsert készítünk. Több karakter is visszarakható így egymás után. A szabvány csak egyetlen egy karakter visszarakását támogatja. - int fgetpos(FILE *fajlHandle, fpos_t *pozicio);
-
Az
ftell
függvény rokona. Ez is visszaadja az aktuális pozíciót, csak éppen nem számként, hanem egy handle-ként adja vissza azt. Így később visszaugorhatunk az aktuális pozícióra. Szöveges fájlokkal mondjuk lehet, hogy érdemes ezt használni az ftell helyett. - int fsetpos(FILE *fajlHandle, const fpos_t *pozicio);
- Egy korábban fgetpos-sal lekért pozícióra ugorhatunk vissza ezzel.
- void rewind(FILE *fajlHandle);
- Lényegében
fseek(fajlHandle, 0, SEEK_SET)
, és még a hibaindikátorokat is törli.
Az stdlib.h
Ez a fejléc sok különböző témában tartalmaz függvényeket. Nagy része hasznos, kisebb részét soha se használom.
Definiált típusok
- div_t
-
A
div
egész osztó függvény által visszaadott érték.Mezői:
- int quot
- Osztás hányadosa.
- int rem
- Osztás maradéka.
- ldiv_t
- A div_t típus változata, melynek mezői
long
típusúak. Azldiv
függvény tér vissza vele. - size_t
- Lásd stdio.h.
rand – véletlenszám generálása
Ezzel a függvénnyel véletlen számokat generálhatunk. Szintaxis:
int rand(void);
A visszaadott véletlenszám 0 és RAND_MAX konstans közötti érték. A RAND_MAX értéke minimum 32767. Mivel gyakran egy adott tartományon belül kell véletlen számot generálni, ezért általában a használata valami ilyesmi módon történik:
rand() % (felső_határ - alsó_határ) + alsó_határ
Ezzel a megadott határok között generálhatunk véletlenszámot, az alsó határ értéke még benne lesz a tartományban, a felső határ értéke pedig már nem. Így ha 1 és 90 közötti lottószámot akarunk generálni, akkor 1 és 91 között számot kell generálnunk a fenti képlettel:
rand() % (91 - 1) + 1 , azaz rand() % 90 + 1
Az a dolog, hogy a az alsó határ még benne van a tartományban, a felső pedig már nincs, nagyon gyakori mintázat, egyszerűen azért, hogy az ilyen felső-alsó kivonás után ne kelljen még egy +1. Tehát érdemes a dolgainkat így tervezni.
Másrészt számítógép egyébként nem tud találomra mondani egy számot.
A véletlen számokat is csak kiszámolja, így a rand
függvény egymás utáni hívogatásai mindig ugyanazt a számsort eredményezik.
Hogy ne így legyen, az srand
függvényt kell használnunk.
srand – véletlenszám-generátor alaphelyzetbe állítása
Ezzel a függvénnyel be lehet állítani a vétetlenszám-generátor magszámát. Szintaxis:
void srand(unsigned int magSzam);
Az előbb említett rand
függvény egymás utáni hívogatásai mindig ugyanazzal az számsorral tér vissza.
Az srand használatával beállíthatjuk a véletlenszám generátor magszámát. Így innentől kezdve a rand
függvény hívogatásaival egy másik számsort lehet előállítani. Természetesen azonos magszámhoz azonos számsor fog tartozni ugyanúgy.
Tipikus használat az, amikor a rendszeridőt használjuk arra, hogy beállítsuk a magszámot.
A rendszeridőt (mely tulajdonképpen az 1970 jan 1 óta eltelt másodpercek száma), a time.h
fejléc time
függvényének a használatával érhetjük el:
srand(time(NULL));
Ha kriptográfiai vagy olyan célra használjuk kellenek a véletlenszámok, ahol életbevágó fontosságú, hogy a véletlenszámok tényleg véletlenek legyenek, más algoritmust kell használnunk, és esetleg még analóg inputot belekeverni (például, megkérni a felhasználót, hogy mozgassa az egeret, és az egér kurzor pozícióját belekeverni a dologba.)
malloc – memória lefoglalása futás közben
A következő téma a dinamikus memóriakezelés. Ez a függvény futás közben megadott mennyiségű memóriát foglal le. Szintaxis:
void *malloc(size_t meret);
- meret
- A lefoglalni kívánt memóriaterület mérete byte-ban.
Visszatérési értéke: Ha a művelet sikeres, akkor egy mutató a lefoglalt területre, amit használhatunk bármire,
különben NULL mutatóval tér vissza (nincs a memóriában akkora blokk, amit nekünk tudna adni).
A lefoglalt terület nincs inicializálva, így ott bármilyen memóriaszemét lehet korábbról.
Tipikus használat:
int *szazElemuTomb = malloc(sizeof(int) * 100); szazElemuTomb[0] = 123; szazElemuTomb[99] = 1212;
Attól függetlenül, hogy tömbként használjuk a területet, a szazElemuTomb
még mindig csak egy mutató. Erről ne feledkezzünk el.
A tömbök és a mutatók kapcsolatáról korábban írtunk.
A mutatóra, amit visszakaptunk vigyáznunk kell, mert ha elveszítjük az értékét, akkor a memória lefoglalt marad, de elérni már többé nem tudjuk. Ez akkor okozhat problémát, ha a programunk futása közben folyamatosan lefoglal és szabadít fel memóriát. Az így elveszett területek ott maradnak a memóriában, és az idők során felhalmozódnak. Ezt nevezik memóriaszivárgásnak (memory-leak). Ekkor a programunk egyre több és több memóriát használ, látszólag ok nélkül.
calloc – nullázott memóriaterület allokálása
A malloc
-hoz hasonló függvény, csak ezt elsősorban tömbök allokálására találták ki, és az allokált terület byte-jait nullázza is. Szintaxis:
void * calloc(size_t elemszam, size_t elemmeret);
Lényegében egy malloc(elemszam * elemmeret)
, majd kinullázza a területet.
free – lefoglalt memóriaterület felszabadítása
Korábban a malloc
, calloc
és realloc
-cal lefoglalt memóriaterületet szabadíthatjuk fel vele. Szintaxis:
void free(void *mutato);
- mutato
- Egy mutató, mely lehet egy korábban
malloc
,calloc
vagyrealloc
-cal leglalt terület vagy NULL.
Ha korábban lefoglalt területről van szó, akkor az fel lesz szabadítva. Ha NULL-t adunk meg, akkor nem fog történni semmi, így nem kell a free
hívása előtt ellenőrizni, hogy NULL-e.
A függvény hívása után a mutatók (beleértve a paraméterként átadottat), melyek a korábban lefoglalt területre mutattak érvénytelenek lesznek, így azokat át kell állítani, hogy ne arra a területre mutassanak (például NULL-ra). Ha ez elmarad, akkor a programunk összeomolhat, mert a mutatott terület már nem a miénk, vagy más változókban tárolt értékek íródhatnak felül, mert a felszabadított terület újra lett foglalva valami más számára. Ez a problémát nevezik logó mutatóknak (dangling pointer).
Tehát akárhányszor ezt a függvényt hívjuk gondoljunk arra, hogy mely mutatók lehetnek azok, amelyek a felszabadítani kívánt területre mutatnak.
realloc – lefoglalt terület átméretezése
Korábban lefoglalt terület más méretűre allokálása. Szintaxis:
void *realloc(void *mutato, size_t ujMeret);
- mutató
- Korábban
malloc
,calloc
vagyrealloc
-cal allokálit memóriaterület, vagy NULL. - újMéret
- Az új mérete a lefoglalt blokknak.
Visszatérési értéke egy mutató az átméretezett terület elejére.
Ha a mutatónak NULL-t adtunk meg, akkor ugyanazt csinálja, mint a malloc
. Ha nem, akkor egy korábban lefoglalt területet
méretez át, a tartalmat pedig átmásolja az új területre. Ha nagyobbra méreteztük a blokkot, akkor az átmásolt byte-ok utáni terület
nem lesz inicializálva. Ha kisebbre, akkor is átmásolja az adatokat az új területre, amennyi elfér, a maradékot levágja.
Ha új méretnek 0-t adunk meg, akkor a függvény úgy viselkedik, mint a free
, tehát felszabadítja a korábban
lefoglalt területet, és NULL-lal tér vissza.
Mivel az átméretezés eredményeképpen jó eséllyel az adat egy másik területen lesz, ezért az összes mutatót, mely a korábbi adatterületre mutatott frissíteni kell, hogy az új területre mutasson, különben ismét az előbb említett lógó mutatók helyzetével állunk szemben.
strtod – szöveg konvertálása valós számmá
Ismét témát váltunk, ezúttal stringeket konvertálunk számmá.
Ez a függvény double
típusra konvertálja a paraméterként megadott stringet.
double strtod(const char *string, char **elsoKarakterUtana);
- string
- A szöveg, amelyet számmá akarunk konvertálni.
- elsoKarakterUtana
- A függvény beállítja a mutatott területen a mutatót, mely az első szintaktikailag nem odaillő karakterre fog mutatni. Ha ezt a paramétert NULL-ra állítjuk be, akkor nem fogja ezt tenni.
Először a szöveg elején kihagyja a whitespace karaktereket, majd elkezdi a szöveget lebegőpontos számként értelmezni.
Az első karakternél, amely szintaktikailag nem odaillő, megáll, és addig értelmezett szám értékével tér vissza.
Ha egyáltalán semmilyen számot sem tudott értelmezni, akkor 0-val.
Amikor a szám kívül esik a double
értelmezési tartományán, akkor a globális errno
változó
ERANGE
konstansra lesz állítva. Ha a szám nagyságrendje túl nagy, akkor a visszaadott érték pozitív vagy
negatív HUGE_VAL
, ha nagyságrend túl kicsi, akkor pedig 0.
strtol és strtoul – szöveg konvertálása egész számmá
Ezek a függvények a paraméterként megadott stringet long
-ként illetve unsigned long
-ként értelmezik.
Szintaxis:
long int strtol(const char *string, char **elsoKarakterUtana, int szamrendszerAlapja); unsigned long int strtoul(const char *string, char **elsoKarakterUtana, int szamrendszerAlapja);
- string
- A szöveg, amelyet számmá akarunk konvertálni.
- elsőKarakterUtána
- A függvény beállítja a mutatott területen a mutatót, mely az első szintaktikailag nem odaillő karakterre fog mutatni. Ha ezt a paramétert NULL-ra állítjuk be, akkor nem fogja ezt tenni.
- számrendszerAlapja
- A számrendszer alapja, mely számrendszerben a stringet értelmezni kell. Ha 0, akkor automatikusan detektálja a 8-as és 16-os számrendszereket, aszerint, hogy 0-val vagy 0x, 0X-szel kezdődik a szám. Különben 10-esben próbálja értelmezni. Ha megadjuk az értéket, akkor annak 2 és 36 között kell lennie. 2 a kettes számrendszer, 36 pedig a 36-os, ahol a 9-es után az angol ábécé számjegyei következnek (mind a 26 betű). Ha megadjuk, hogy 16-os számrendszert akarunk, akkor elfogadja és figyelmen kívül hagyja a szám elején a 0x-et vagy a 0X-et.
Visszatérési értéke az értelmezett szám az első szintaktikailag nem odaillő karakterig (melynek a pozícióját el is tárolja nekünk, ha kérjük).
Ha a szám nem fér be az értelmezési tartományba, akkor az ERANGE
hibát írja a globális errno
változóba,
és a visszatérési érték LONG_MIN
vagy LONG_MAX
lesz az előjeles esetben,
előjel nélküliben pedig ULONG_MAX
.
A függvény először figyelmen kívül hagyja az összes szóközt a szöveg elején, utána jöhet egy + vagy - karakter, majd a számjegyek. Az első nem odaillő karakternél beállítja a mutatót az általunk megadott területre, majd visszatér az eddig értelmezett értékkel.
exit – kilépés a programból
Ismét témát váltunk, most a hívó környezettel kapcsolatos függvényekről lesz szó.
Ez használható arra, hogy kilépjünk a programból, bárhonnét. A normális módja a kilépésnek természetesen az, hogy a main függvényből return-ölünk.
Szintaxis:
void exit(int status);
Először atexit
függvény által regisztrált függvények futnak le fordított sorrendben, mint amelyben regisztráltuk őket,
minden nyitott fájl handle lezáródik majd a program kilép a megadott státuszkóddal. A 0-ás státuszkód jelenti a sikeres kilépést,
más kódok általában hibát jelentenek.
atexit – függvény regisztrálása kilépéskori végrehajtásra
Kilépéskor lefuttatandó függvényt regisztrál. Szintaxis:
int atexit(void (*fuggveny)(void));
- függvény
- Ez a void visszatérési értékű paramétereket nem fogadó függvény.
Sikeres regisztráció esetén 0 a visszatérési érték, ellenkező esetben egy tőle különböző érték.
A paraméterként átadott függvény akkor fut le, amikor a programunk normálisan kilép (az exit
függvény használatával) vagy
a main
függvényből van kilépés esetén. Több függvény is regisztrálható, fordított sorrendben fognak lefutni, mint
amilyen sorrendben regisztráltuk őket.
abort – program azonnali leállítása
Abnomrálisan leállítja a programot. Szintaxis:
void abort(void);
A függvény egy SIGABRT szignált generál, melytől a program egyszerűen kilép (kilővődik), mindenféle atexit
vagy
hasonló dolog lekezelése nélkül.
getenv – környezeti változó lekérdezése
Egy környezeti változó értékét kérdezi le. A függvény működése rendszerfüggő (pl. Windowson mindegy a kis és nagybetű, Linuxon nem). Szintaxis:
char *getenv(const char *valtozoNev);
- valtozoNev
- A környezeti változó neve.
A függvény egy mutatóval tér vissza, mely a környezeti változó értékére mutat (egy string). Ha a környezeti változó nem létezik, akkor a visszatérési érték NULL.
Környezeti változót beállító függvény, tehát setenv
nem létezik, azt máshogy kell megcsinálni, például a system
parancson keresztül.
system – shell parancs végrehajtása
Segítségével parancsértelmezővel parancsot hajthatunk végre. Nyilván rendszerfüggő, hogy miként fut le a parancs. Szintaxis:
int system(const char *parancs);
- parancs
- A parancs, amit le akarunk futtatni, vagy NULL.
A függvény visszatérési értéke rendszerfüggő, ha parancsot hajtunk végre. Ha NULL-t adtunk meg paraméternek, akkor a visszatérési érték igaz (nullától különböző), ha rendelkezésre áll parancsértelmező, különben hamis (0), ha nem.
qsort – gyorsrendező algoritmus futtatása tömbön
Ismét témát váltunk, most tömböket rendezünk.
Tömb sorba rendezése a gyorsrendező algoritmussal. Szintaxis:
void qsort(void *tomb, size_t elemszam, size_t elemMeret, int (*osszehasonlitoFuggveny)(const void*,const void*));
- tömb
- Mutató a tömb első elemére.
- elemszam
- A tömb elemeinek a száma.
- elemMeret
- Egy tömb elem mérete.
- osszehasonlitoFuggveny
- Mutató egy összehasonlító függvényre, mely két mutatót kap a két összehasonlítandó elemre. A függvénynek pozitív értékkel kell visszatérni, hogy ha az második elem jön a sorban előbb. Nullával, hogy ha mindegy. Negatív értékkel, hogy ha az első elem jön előbb a sorban.
A függvény a megadott paraméterek alapján rendezi nekünk a tömböt. A rendezéshez szükséges lépések számának nagyságrendje n log2 n. Ez azt jelenti, hogy egy 1000 elemű tömböt, kb. 10000 lépésből tud rendezni.
bsearch – bináris keresés rendezett tömbben
Bináris keresést végez egy rendezett tömbben. Szintaxis:
void *bsearch( const void *kulcs, const void *tomb, size_t elemszam, size_t elemmeret, int (*osszehasonlitoFuggveny)(const void *, const void *) );
- kulcs
- Egy mutató arra a dologra, amit keresünk.
- tömb
- A rendezett tömb, amelyben keresünk.
- elemszám
- A tömb elemszáma.
- elemméret
- Egy tömbelem mérete.
- összehasonlitóFüggvény
- Egy függvény, az első paramétere egy mutató a megadott kulcsra, a második egy mutató egy elemre a tömbben. A függvény visszatérési értéke pozitív, hogy ha az elem a kulcsnál hátrébb van a tömbben a rendezettsség szerint. Nulla, hogy az elem és a kulcs értéke megegyezik (tehát a kereső megtalálta). Negatív, hogy ha az elem a tömbben a kulcsnál előrébb van.
A függvény visszatérési értéke egy mutató tömbelemre, melynek értéke megegyezik a kulcs értékével. Ha az elem nincs a tömbben, akkor a visszatérési érték NULL.
A keresés úgy működik, hogy először veszi a tömb középső elemét, és hívja rá az összehasonlító függvényt. Ha nem találtuk el, akkor az alapján, amit az összehasonlító függvény mond, már a tömb elemeinek a felét ki is hagytunk. Mivel, ha rendezett tömbben a kulcs előrébb van az középsőhöz képest, akkor hátrébb nem lehet, és fordítva. Ezt a felezgetést ismételgeti addig, amíg eléggé le nem szűkül a tartomány, és állíthatja, hogy megvan az elem, avagy nincs.
A felezgetés miatt ez a kereső algoritmus nagyon gyors. 1000 elemű tömbnél 10db felezés elég, hogy eldöntsük megvan-e az elem.
A lépésszám log2 n -nel arányos (ahol n a tömb elemeinek a száma). Ahhoz, hogy ilyen gyorsan tudjunk keresni,
ahhoz a tömböt rendezni kell, mondjuk a qsort
függvénnyel. Mivel annak a lépésszáma n log2 n-nel arányos, így
n log2 n log2 n = n log22 n-nel lesz arányos. Így csak akkor csináljunk rendezést
és bináris keresést, ha tudjuk, hogy sok keresés lesz a tömbön egymás után, várhatóan log22 n-nél több.
Ha ennél kevesebb, akkor rendezés nélkül, ezen függvény használata nélkül, egyesével végig mehetünk a tömbön, és megkereshetjük
ez elemeket úgy, így gyorsabb.
abs és fabs – abszolút érték számolása
Ezzel áttérünk az egész aritmetika függvényeire.
Ezekkel egész számok abszolút értékét lehet kiszámolni. Szintaxisuk:
int abs(int x); long labs(long x);
A függvény visszatérési értéke a paraméterként átadott szám abszolútértéke.
div és ldiv – egész osztás
Egészoszást végeznek és visszaadják az osztási maradékot is. Szintaxisuk:
div_t div(int osztando, int oszto); ldiv_t ldiv(long osztando, long oszto);
A két függvény elosztja a két számot, és a visszatérési érték struktúrába beleteszi a hányadost és az osztási maradékot.
Van a / és a % operátor, azokkal is el lehet végezni ezt a feladatot. Viszont a processzorok általában úgy implementálják az osztás műveletét, hogy közben melléktermékként előáll az osztási maradék is. Így ha külön osztunk és maradékot képzünk utána, azzal tulajdonképpen két osztást végeztetünk el a géppel. Az osztás művelete pedig a számítógépnek is relatíve lassú. Ezek a függvények akkor hasznosak, amikor egyszerre kell a hányados és az osztási maradék is.
Egyéb függvények
- double atof(const char *str)
- Lebegőpontossá konvertálja a stringet, ugyanaz, mint az
strtod
csak kevesebb lehetőséggel. Valamint a tartományon kívül eső értékekre nem állít hibakódot. - int atoi(const char *str)
- Int-té konvertálja a stringet, ugyanaz, mint az
strtol
csak kevesebb lehetőséggel. Valamint a tartományon kívül eső értékekre nem állít hibakódot. - long atol(const char *str)
- Long-gá konvertálja a stringet, ugyanaz, mint az
strtol
csak kevesebb lehetőséggel. Valamint a tartományon kívül eső értékekre nem állít hibakódot. - mblen, mbtowc, wctomb, mbstowcs, wcstombs
- Ezek a függvények wchar_t stringek és rendszerbeállításoktól függő karakterkészlet (pl. ANSI) között konvertálnak.
Mivel működésük erősen nyelvi beállításfüggő, ezért nem javaslom használatukat. A wchar_t Windowson 2 byte-os, máshol meg 4 byte-os, így abból is lehetnek gondok.
Érdemes mindig mindenkor UTF-8 kódolást használni, és akkor az egyszerű
char
típus használható mindenkor.
A math.h
Ebben a fejlécben a matematikai függvények vannak. Különösebb magyarázatra nem szorulnak. Hogy ezeket a matematikai függvényeket mire használják a gyakorlatban, az nem ennek a dokumentumnak a hatásköre.
Hatványfüggvények
- double pow(double x, double y)
- Kiszámolja xy-t.
Ha az eredmény túl nagy vagy túl kicsi, az
errno
beállítódikERANGE
-ra, és pozitív vagy negatívHUGE_VAL
vagy 0 lesz az eredmény. - double sqrt(double x)
- Kiszámolja x négyzetgyökét. Negatív számra nincs definiálva a viselkedése.
Trigonometrikus függvények
- double cos(double x)
- Radiánban megadott szög koszinuszát adja vissza.
- double sin(double x)
- Radiánban megadott szög szinuszát adja vissza.
- double tan(double x)
- Radiánban megadott szög tangensét adja vissza.
- double acos(double x)
- Az érték arkusz koszinuszát adja vissza radiánban.
- double asin(double x)
- Az érték arkusz szinuszát adja vissza radiánban.
- double atan(double x)
- Az érték arkusz tangensét adja vissza radiánban.
- double atan2(double y, double x)
- Az y/x arkusz tangensét adja vissza radiánban. Viszont ez a függvény tekintettel van arra is, hogy melyik síknegyedben van az x és y kordináta így ez használható irányszög megállapítására is (360°-ban működik).
Hiperbolikus függvények
- double sinh(double x)
- Kiszámolja a megadott hiperbola szög hiperbolikus szinuszát.
- double cosh(double x)
- Kiszámolja a megadott hiperbola szög hiperbolikus koszinuszát.
- double tanh(double x)
- Kiszámolja a megadott hiperbola szög hiperbolikus tangensét.
Exponenciális és logaritmikus függvények
- double exp(double x)
- Kiszámolja az ex értékét
- double frexp(double x, int *kitevo)
- Kettes normálalakra hozza a számot, a kitevőt a kimenőparaméterbe írja a mantissza pedig a visszatérési érték lesz. Pl.: 8 = 0.5 * 2^4
- double ldexp(double x, int kitevo)
- Az előző függvény ellentéte. Adott mantisszából és karakterisztikából előállítja magát a számot. Pl.: 0.6 * 2^5 = 19.2
- double log(double x)
- Kiszámolja a természetes alapú logaritmust.
- double log10(double x)
- Kiszámolja a 10-es alapú logaritmust.
- double modf(double x, double *egeszResz)
- Egész részre és törtrészre bontja a számot. A törtrésszel visszatér, az egész részt a megadott címre írja be.
Egyéb függvények
- double ceil(double x)
- Felfelé kerekít egész számra.
- double floor(double x)
- Lefelé kerekít egész számra.
- double fabs(double x)
- Lebegőpontos abszolút értéket számol.
- double fmod(double osztando, double oszto)
- Lebegőpontos osztási maradékot számol. Azaz:
y * (x/y - floor(x/y))
.
Függvények float és long double verziója
Külön nem említettem, de ezeknek az aritmetikai függvényeknek van float
és long double
változatunk is.
A float-oshoz egy f betűt, a long double-oshoz egy l betűt kell a függvény neve után írni. Tehát sin
mellett lehet sinf
és
sinl
is. C++ nyelv esetén overload létezik ezekre a függvényekre így ott az azonos nevű függvények tudják kezelni a többi típust is.
Természetesen C esetén se kell nagyon konvertálgatni, implicit megtörténik a konverzió.
A string.h
Ebben a fejlécben a C stringek és memóriablokkok kezelésével foglalkozó függvényekről van szó.
Mikor memóriablokkokkal bánunk figyeljünk oda, hogy jó helyre írunk, mert a legtöbb elszállást, és exploitot elrontott memóriamozgatások szokták okozni.
A függvények mindegyike végigmegy a paraméterként átadott stringeken vagy memóriaterületen, így az időbonyolultsága mindnek O(n).
memcpy és memmove – memóriablokkok mozgatása
Első körben a memóriablokkok másolásáról lesz szó.
Ezzel memóriablokkokat mozgathatunk. Szintaxis:
void *memcpy(void *ide, const void *innen, size_t ennyi_bajtot); void *memmove(void *ide, const void *innen, size_t ennyi_bajtot);
- ide
- A mutatott helyen kezdődik a terület, ahová másolunk.
- innen
- A mutatott helyen kezdődik a terület, ahonnét másolunk.
- ennyiBajtot
- Ennyi byte-ot másol.
Visszatérési értéke az ide
paraméter.
A memcpy
akkor használatos, hogy ha a forrás és a célterület nem fedi át egymást, különben használjunk memmove
-t.
Figyeljünk oda, hogy a célterületen legyen elég helyünk.
strcpy és strncpy – szöveges érték másolása
Ezekkel a függvényekkel stringeket másolhatunk. Szintaxisuk:
char *strcpy(char *ide, const char *ezt); char *strncpy(char *ide, const char *ezt, size_t max_ennyi_karaktert);
- ide
- A mutatott byte-nál kezdődik a terület, ahová másolunk.
- ezt
- A mutatott területen van a string, amit másolunk.
- max_ennyi_karaktert
- Legfeljebb ennyi karaktert másolunk.
Visszatérési értéke az ide
mutató.
Az strcpy addig másolja karaktereket, amíg a másolandó string végére nem ér (tehát eléri a nullás byte-ot). Túlcsordulás elkerülése érdekében gondoskodjunk róla, hogy elegendő helyünk van azon a területen, ahová másolunk.
Az strncpy esetén, ha a másolandó string rövidebb, mint a másolandó byte-ok száma, akkor a string végére érve már csak 0-ás byte-okat ír, amíg a kellő számú karaktert oda nem írta. Ha hosszabb vagy egyenlő, akkor lényegében ugyanúgy működik, mint a memcpy, nem fog 0-ás byte-ot írni, magunknak kell odaírni azt. Túlcsordulás elkerülése érdekében gondoskodjunk róla, hogy elegendő helyünk van azon a területen, ahová másolunk.
A függvények viselkedése nincs definiálva, ha a forrás a célterület átfedi egymást.
strcat és strncat – szöveg összefűzése
Most a string összefűző függvények következnek.
Stringhez való hozzáfűzést lehet velük csinálni. Szintaxisuk:
char *strcat(char *ehhez, const char *ezt); char *strncat(char *ehhez, char *ezt, size_t max_ennyi_karaktert);
- ehhez
- A string elejére mutat, amelyhez hozzáfűzünk.
- ezt
- A stringre mutat, amit hozzá akarunk fűzni az előbbihez
- max_ennyi_karaktert
- Legfeljebb ennyi karaktert fűz hozzá a stringhez.
A függvény az eredeti string végét jelző 0-ás byte-tól kezdve elkezdi hozzáírni a megadott stringet.
Az strcat
addig adja hozzá a byte-okat, ameddig hozzáadandó string végére nem ér.
Az strncat
, ha hamarabb eléri a maximális byte számot, akkor nem ad hozzá többet, és lezárja a stringet egy 0-ás byte-tal.
Gondoskodjunk arról, hogy elengedő helyünk legyen a módosítandó területen.
A függvények viselkedése nincs definiálva, ha a forrás és a célterület átfedi egymást.
memcmp – két memóriaterület összehasonlítása
Két memória blokkot hasonlít össze. Szintaxis:
int memcmp(const void *ezt, const void *ezzel, size_t hosszuk);
- ezt, ezzel
- Mutató az összehasonlítandó blokkok elejére
- hosszuk
- A blokkok hossza.
A függvény visszatérési értéke 0, hogyha a két blokk byte-jai megegyeznek, különben más érték. Ha pozitív, akkor az első különböző byte az első blokkban nagyobb, ha negatív, akkor a második blokkban nagyobb.
strcmp és strncmp – két string összehasonlítása
Két stringet hasonlít össze. Szintaxis:
int strcmp(const char *egyik, const char *masik); int strcmp(const char *egyik, const char *masik, size_t max_hossz);
Lényegében ugyanúgy működik, mint a memcmp
, csak az összehasonlítás megáll, amint valamelyik stringben
egy 0-ás byte-hoz érünk. Ha eddig a pontig megegyezett a két string, akkor a függvény visszatérési értéke 0, különben a memcmp
-nél
említett módon számolódik. Az strncmp esetén még van annyi plusz, hogy megadott számú karakter összehasonlítása után mindenképp megáll az összehasonlítás,
még akkor is, ha nem értünk el 0-ás byte-ot.
memchr, strchr és strrchr – karakter vagy byte keresése a stringben és memóriaterületen
Egy blokkban megkeresi az első előfordulását egy adott byte-nak. Szintaxisuk:
void *memchr(const void *blokk, int ezt, size_t blokk_meret); char *strchr(const char *string, int ezt); char *strrchr(const char *string, int ezt);
- blokk
- Mutató a blokk elejére, amiben keresünk
- ezt
- Ezt a byte-ot keressünk (unsigned char-rá lesz konvertálva).
- blokk_meret
- A blokk mérete
A memche
függvény visszatérési értéke egy mutató a megtalált byte-ra, ha nincs meg, akkor NULL.
Az strchr
nyilván a string végéig, azaz a 0-ás byte-ig keres, a memchr
pedig a megadott számú byte-ig.
Az strrchr
ugyanaz, mint az strchr
csak az a legutolsó karaktert keresi meg.
strcspn és strpbrk – több karakter keresése stringben
Stringben megkeresi az adott string karaktereit. Szintaxis:
size_t strcspn(const char *ebben, const char *ezeket); char *strpbrk(const char *ebben, const char *ezeket);
Az strcspn
függvény visszatér az első karakter sorszámával, amely benne van az ezeket
stringben.
Ha egyik karaktere sincs benne, akkor az ebben
string hosszával tér vissza.
Az strpbrk
függvény is hasonlóan működik, csak az egy mutatóval tér vissza a talált karakterre, ha nincs meg a karakter,
akkor NULL-lal.
strspn – illeszkedő karakterek számolása a string elején
Megszámolja, hogy egy string elején hány karakter van a másik karakterei közül. Szintaxis:
size_t strspn(const char *ennek_elejen, const char *ezek_a_karakterek);
A visszatérési érték az string elején lévő karakterek száma, melyek egyeznek a megadottakkal.
strstr – string keresése egy másik stringben
String keresése egy másik stringben.
char *strstr(const char *ebben, const char *ezt);
A függvény visszatér egy mutatóval arra pozíciója a string elejétől számolva, ahol megtalálta az ezt
stringet
az ebben
stringben. Ha nem található meg, akkor NULL-lal tér vissza.
strtok – string darabokra szedése
Darabokra bont szét egy stringet a megadott elválasztó karakterek mentén. Szintaxis:
char *strtok(char *string, const char *elvalaszto_karakterek);
- string
- A szétbontandó string vagy NULL. A függvény a folyamat közben lecseréli az elválasztó karaktereket 0-ás byte-okra a megadott stringben.
- elvalaszto_karakterek
- A string, melyben felsoroljuk az elválasztó karaktereket.
A függvény visszatér az aktuális stringdarabka elejével (a vége le van zárva 0-ás byte-tal), ha nincs több darabka, akkor NULL mutatóval.
Az első híváskor a string
paramétert megadjuk, hogy megkapjuk az első darabkánt, ezután NULL
mutatót
írunk a paraméter helyére, hogy megkapjuk a többi darabkát is.
Bizonyos rendszerekben létezik a függvénynek egy olyan változata, melynek 3 paramétere van:
char *strtok(char *string, const char *elvalaszto_karakterek, char **allapot);
Ez egy felhasználó által megadott mutatóban tárolja a szétbontás állapotát, így egyszerre több szétvagdosás is folyamatban lehet.
A memset függvény – memóriaterület nullázása
Egy memóriablokk byte-jait beállítja az adott értékre. Szintaxis:
void *memset(void *blokk, int ezt, size_t blokk_hossz);
- blokk
- Mutató a blokk elejére
- ezt
- Az érték, amivel inicializálni akarunk (unsigned char-rá lesz konvertálva).
- blokk_hossz
- A blokk hossza.
Visszatérési értéke a blokk
paraméter. Általában blokknullázásra szokták használni.
Az strerror függvény – rendszerhibák szöveges kiírása
Egy rendszer hibakódhoz tartozó hibaüzenetet adja vissza. Szintaxis:
char *strerror(int hibakod);
A függvény visszatérési értéke egy mutató a hibaüzenetre, mely rendszer és nyelvibeállítás-függő.
Az strlen függvény – szöveg hosszának lekérdezése
Visszatér a string hosszával. Szintaxis:
size_t strlen(const char *string);
Visszatér a megadott string hosszával (azaz, hogy hányadik karaktere a záró 0-ás byte).
Egyéb függvények
- int strcoll(const char *egyik, const char *masik)
- Két string összehasonlítása az aktuális nyelvi beállítás illesztési szabályai szerint, pl.: ha az 'A' betűről van szó, az lehet, hogy illeszkedik az 'Á'-ra vagy az 'Ä'-ra is. Mivel ez a függvény erősen operációs rendszer és nyelvi beállításfüggő nem javaslom használatát.
- size_t strxfrm(char *ide, const char *innen, size_t ennyit)
-
Lényegében egy
strncpy
jellegű dolog, csak az aktuális nyelvi beállításokat is figyelembe veszi másoláskor. Sose használtam még, és még a neten sem találtam a használatára jó példákat.
Az assert.h fejléc
Ebben a fejlécben ez az makró van csak:
assert(kifejezés);
Ha a kifejezés igaz, akkor semmi baj, ha hamis, akkor az abort
függvénnyel kilép a program.
Ez a makró, amint a nevében is benne van feltételezések kódba írására való.
Például ha írunk egy függvényt, amelynek az egyik paramétere mutató, és az a mutató nem lehet NULL (mert az az eset nincs értelmezve), akkor egy
assert
segítségével ellenőrizhetjük, hogy a hívó tényleg nem NULL-t adott-e meg. Tehát ezzel a dologgal programhibákat kerülhetünk
el, mielőtt nagyobb gondot okoznak a program más részén.
Ez a makró az érvényét veszti, hogy ha definiálva van az NDEBUG szimbólum. A legtöbb fejlesztői környezet általában definiál egy debug és a release módot a programnak, és release módban definiálja ezt az NDEBUG dolgot. Tehát az assertek szorgos berakosgatásával egyszerű programozói hibákra figyelmeztethetünk, és egyszerű teszteket is írhatunk.
Az errno.h fejléc
Hozzáférést biztosít a globális errno
változóhoz, melybe a legtöbb standard függvény írja a hibakódját. Ezen kívül nincs más benne.
A time.h fejléc
Dátum- és időkezelés függvényei találhatók benne.
Típusai
clock_t és time_t
Ezek egész szám típusok.
tm struktúra
struct tm { int tm_sec; // másodperc int tm_min; // perc int tm_hour; // óra int tm_mday; // nap int tm_mon; // hónap int tm_year; // év int tm_wday; // hét napja (előző vasárnaptól számolva) int tm_yday; // év napja (jan. 1-től számolva) int tm_isdst; // Nyári időszámítás van-e. };
Ez a struktúra az időt felbontva ábrázolja.
clock – elhasználnál processzoridő mérése
Vissza a program által felhasznált CPU idő mennyiségével. Szintaxis:
clock_t clock(void);
A clock_t
egy egész szám típus.
A visszatérési értéket CLOCKS_PER_SEC
-kel elosztva megkapjuk a programunk által elhasznált CPU idő mennyiségét másodpercben.
Működése platformfüggő, és pontos időmérésre nem alkalmas.
difftime – két időpont összehasonlítása
double difftime(time_t korabbi, time_t kesobbi);
Két időpont különbségét számolja ki, és visszatér a kettő különbségével másodpercben. Habár a visszatérési érték double
a törtrész
soha nem lesz használva, mert a time_t
egy egész szám.
mktime – tm
struktúra time_t
-vé alakítása
time_t mktime(struct tm *ido);
Egy kitöltött tm
struktúrából készít egy time_t
értéket. Ha a struktúra hibás, akkor -1 értékkel tér vissza.
time – aktuális idő lekérése
time_t time(time_t *idobelyeg);
Lekérdezi az időt, és visszatér vele, illetve letárolja az ido
paraméterben, ha nem NULL értéket adtunk meg neki.
asctime – idő szöveggé alakítása
char * asctime(const struct tm *ido);
A feltöltött tm
struktúrát szöveggé alakítja. A formátum. Www Mmm dd hh:mm:ss yyyy
A W hét napja, M a hónap, d a nap, h, m és s az idő, y az év. A visszatérési érték egy statikus tömbben van tárolva, amely
minden egyes hívás után megváltozik, így érdemes a visszatérési értéket azonnal lemásolni magunknak. A statikus tömbhöz való
hozzáférés miatt a függvény nem szálbiztos (nyilván az egyszálas időkben készült, mint a C nyelv maga).
ctime – idő szöveggé alakítása
char *ctime(const time_t *idobelyeg);
Ugyanazt csinálja, mint az előbb említett asctime
, csak ez time_t
-t vár.
gmtime – time_t -ből tm struktúra feltöltése
struct tm *gmtime(const time_t *idobelyeg);
Ez effektíve a mktime
fordítottja. Egy time_t
-ből csinál tm
struktúrát.
Ez egy statikus struktúra, szóval azonnal érdemes lemásolni. Nyilván abban az időben készült ez a függvény is, amikor
egyszálú számítógépek voltak, így ez a függvény nem szálbiztos.
localtime – time_t -ből tm struktúra feltöltése
struct tm *localtime(const time_t *idobelyeg);
Ez ugyanaz, mint a gmtime
csak ez az aktuális időzónát is figyelembe veszi. Tehát locale-függő,
így nem javaslom a használatát.
strftime – formázott kiírása az időnek
size_t strftime(char *ide, size_t max_ennyit, const char *formatum, const struct tm *ido);
- ide
- A mutató a puffer elejére, ahová a string íródik majd.
- max_ennyit
- A string maximális hossza.
- formatum
- Formátum string, lásd később
- ido
- Struktúra feltöltve.
A függvény lényegében úgy működik, mint a printf
, tehát bizonyos formátumjelölők be lesznek helyettesítve a nekik megfelelő stringgel.
A következő táblázat tartalmazza a lehetséges formátumjelölőket:
Formátumjelölő | Jelentés | Példa |
---|---|---|
%a | Rövidítve a hét napja. (nyelvibeállítás-függő) | Wed |
%A | A hét napja teljesen kiírva. (nyelvibeállítás-függő) | Wednesday |
%b | Rövidített hónapnév (nyelvibeállítás-függő) | Oct |
%B | Hónapnév kiírva (nyelvibeállítás-függő) | October |
%c | Dátum és idő kiírva (mint az asctime vagy ctime esetében, nyelvibeállítás-függő) |
Wed Oct 30 02:20:48 2024 |
%d | A nap a hónapon belül | 30 |
%H | Óra (24 órás formátum) | 02 |
%I | Óra (12 órás formátum) | 02 |
%j | A nap sorszáma jan. 1-től számolva. | 303 |
%m | Hónap sorszáma egész számként (01-12) | 10 |
%M | Perc (00-59) | 20 |
%p | AM és PM (délelőtt és délután jelölése) | AM |
%S | Másodpercek (00-61) (szökőmásodpercek miatt mehet 60 fölé) | 48 |
%U | A hét sorszáma (vasárnappal kezdődő hetek) (00-53) | 44 |
%w | A hét napja mint sorszám (0-6). A 0 a vasárnap, 6 a szombat. | 3 |
%U | A hét sorszáma (hétfővel kezdődő hetek) (00-53) | 44 |
%x | Dátum (nyelvibeállítás-függő) | 10/30/24 |
%X | Idő (nyelvibeállítás-függő) | 02:10:48 |
%y | Év (két számjegyű formátum) | 24 |
%Y | Év (Négy számjegyű formátum) | 2024 |
%Z | Időzóna rövidítés | UTC |
%% | Százalékjel | % |
A visszatérési értéke a kimeneti pufferbe írt karakterek száma lesz a lezáró nullás byte-tal együtt, különben és hiba esetén 0-ás érték.
(A táblázat példáit PHP-val generáltam, amely esetleg eltérhet attól, amit a C standard library visszaad.)
Egyéb fejléc fájlok
Itt sorolom fel azokat a fejléc fájlokat, amelyeket nem használunk túl sokat, de időnként jól jönnek. Csak pár mondatban leírom a funkcióikat, a függvényeik részletezésébe nem megyek bele.
A ctype.h
Ebben a fejlécben karakterkezelő függvények vannak. Mivel nagy részük locale alapján működik, ezért nem javaslom a használatukat többplatformos alkalmazások esetén.
A float.h
Lebegőpontos konstansok vannak definiálva benne (egyes lebegőpontos számtípusok határértékei és sok más).
Az iso646.h
Logikai és bitműveletek operátorainak a szöveges változatát definiálja, C++-ban a nyelv definiálja ezeket a kulcsszavakat, így ott nincs szükség erre. Meg amúgy se használjuk őket túl sokat.
A limits.h
Egész adattípusok értékhatárait definiálja.
A locale.h
Nyelvvel kapcsolatos dologkat lehet beállítani itt.
A setjmp.h
Olyan függvények vannak ebben, amellyel összevissza lehet ugrálni a forráskódban. A régebbi nyelvekben emiatt van olyan rossz hírneve a GOTO-nak.
A signal.h
Szignálokkal kapcsolatos függvényeket tartalmaz. Ez a szignálos dolog főleg az Unix alapú rendszerekben jellemző, Windows alatt más módja van ennek.
Az stddef.h
Ezt a fejlécet a többi standard fejléc szúrja be. Deklarál néhány típust.