XXVII. Diel C++ - Hlavičkové súbory IV. – stdio.h II.

Michal Kyžňanský  /  12. 05. 2006, 00:00

Pokračujeme v predstavovaní funkcii hlavičkového súboru stdio.h. Dokončíme skupinu funkcii, ktoré sa starajú o načítavanie a ukážeme si používanie bufferu. Buffer je vynikajúca vec a jeho použitie je veľmi dobré pri práci so súborom, ak nevieme či zmeny urobené hodláme ukladať. Povieme si aj o variantoch výpisu do súboru.

V minulom dieli sme skončili pri kapitole načítavanie. Povedali sme si o načítavaní po jednom znaku – fgetc( ) / getc( ) a o načítavaní formátovaného reťazca – fscanf( ). Tento diel odštartuje funkcia načítania celého riadku.

Načítavanie celého riadka – fgets( )

Možnosť načítavať po rôzne veľkých blokoch dát nám dáva do rúk mocné nástroje. Ak je nutné načítať iba jeden riadok, alebo jednoducho načítavať text po riadkoch odpoveďou je funkcia fgets( ). Táto funkcia ukladá počet alokovaných znakov -1 v riadku. Načítava až pokým sa nedostane k znaku EOF alebo EOL – End Of Line. Funkcia vyzerá nasledovne:
fgets(názov_alokovaného_poľa, počet znakov, premenná_FILE)  

Ukážeme si teda na príklade ako to funguje. Vytvoríme si najprv textový dokument test.txt a zapíšeme do neho 3 vety a každá bude v novom riadku. Program načíta iba celý prvý riadok.

Príklad
FILE * f; 
char riadok [100];

f = fopen ("C:test.txt" , "r");
fgets (riadok , 100 , f);
ShowMessage(riadok);
fclose (f);



Zisťovanie pozície v súbore


Na princípe pointera, ktorý ukazuje, kde v súbore sa nachádzame pracujú všetky funkcie načítavania a výpisu. Tento pointer je akoby “kurzor“, ktorý ukazuje, kde sa nachádzame v súbore a podľa neho sa orientujú ostatné funkcie. Máme však funkcie – predstavme si ich ako myšku, ktorými môžeme meniť polohu tohto kurzora. Predstavíme si tieto funkcie.

Zistenie aktuálnej pozície – ftell( ) a fgetpos( )

Tieto dve funkcie zistia aktuálnu pozíciu “kurzora” v súbore s ktorým pracujeme. Ak je zistenie úspešné, je vrátená hodnota – číslo, ktoré reprezentuje vzdialenosť od začiatku súboru, od prvého znaku, ktorý ma číslo 0. Teda, ak je súbor prázdny, tak je vrátená hodnota 0. Ak sú v ňom zapísané 4 znaky, je vrátená hodnota 4, pričom hodnota 4 ukazuje na miesto za posledným znakom. Počítanie začína od nuly a teda prvý znak je na pozícii 0. Ak zistenie nie je úspešné a nastane nejaká chyba je vrátená hodnota -1L.

Príklad1 – ftell( )
FILE * f; 
double pos;

f = fopen ("C:test2.txt","w+"); //w+ znamená čítanie aj zapisovanie
fprintf(f,"ahoj"); //zapíšeme 4 znaky - ahoj
pos = ftell(f); //po výpise do súboru zisťujeme pozíciu
fclose (f); //zatvorenie súboru

ShowMessage(pos); //výpis pozície


Príklad2 – fgetpos( )
....... 
fgetpos(f,&pos); //priradenie pozície premennej pos
.......


Presunutie na začiatok – rewind( )

Tento príkaz jednoducho presunie pozíciu “kurzora“ na začiatok súboru. Za všetko hovorí nasledovný príklad. Pre demonštráciu si vyskúšajte tento program s použitím riadku s funkciou rewind( ) a bez neho.

Príklad:
char ret[20]; 
FILE * f;

f = fopen ("test.txt","w+");
fprintf(f,"výpis");
rewind (f); //po výpise vraciame pozíciu na začiatok
fscanf(f,"%s", &ret);
fclose (f);
ShowMessage(ret); //vypíše načítaný reťazec - výpis


Presúvanie pozície kurzoru funkciou fseek( )

Táto funkcia umožňuje posúvať pozíciu “kurzora” o ľubovoľný počet miest, a od troch rôznych pozícii. Posúvanie sa týka začiatku súboru, konca súboru a aktuálnej pozície v súbore.
fileseek(pointer FILE, počet_miest, koeficient);

koeficient:

SEEK_SET – pozícia kurzoru s hodnotou začiatku súboru
SEEK_CUR - aktuálna pozícia kurzoru v súbore
SEEK_END - pozícia kurzoru v súbore s hodnotou konca súboru

Príklad
FILE * f; 

f= fopen ("C:test3.txt","w");
fputs ("Musel som vyrobiť.",f); //zapíše sa do súboru
fseek (f,10,SEEK_SET); //pozícia kurzora od začiatku + 10
fputs ("za",f); //prepíše písmená “vy“ v súbore na za
fclose (f);


Výpis tejto funkcie teda bude vyzerať Musel som zarobiť. Funkcia fputs( ) zapisuje pole znakov na aktuálnu adresu kurzora v súbore.

Presúvanie pozície kurzoru funkciou fsetpos( )

Funkcia fsetpos( ) nastaví pozíciu „kurzora” v súbore na zadanú adresu. Parameter pozície „kurzora” musí byť v tvare long. Príklad
FILE *f; 
f = fopen ("C:test3.txt","w");
long pos = 20;
fsetpos (f, &pos);


Zapisovanie do súboru


Na zapisovanie do súboru je možné použiť niekoľko funkcii. Od zapisovanie po jednom znaku až po zapisovanie bloku dát.

Zapisovanie do súboru po jednom znaku – fputc( ), po jednom čísle – putw( )

K tejto funkcii netreba žiadny komentár, pretože je tak jednoduchá ako len funkcia môže byť. Preto prejdeme priamo k príkladu.

Príklad - fputc
FILE *f; 
f = fopen("C:test.txt","w");
fputc ("A",f); //zapísanie znaku A do súboru


Príklad - putw
FILE *f; 
f = fopen("C:test.txt","w");
putw (45,f); //zapísanie čísla 45 do súboru


Zapisovanie do súboru po jednom znaku – fputs( )

Táto funkcia vyzerá úplne rovnako ako predchádzajúca spomínaná. Jediný rozdiel je, že dokáže zapísať do súboru reťazec.

Príklad
FILE *f; 
f = fopen("C:test.txt","w");
fputs ("Ahoj svet",f); //zapísanie reťazca do súboru
fclose(f);


Vrátenie znaku do súboru – ungetc( )

Táto funkcia by nebola opodstatnená, keby sme pri niekedy pri načítavaní neoverovali koniec súboru metódou
char c; 
c = fgetc(f);
ungetc(f);
if(c != EOF){
..........
}

Pretože metóda fgetc( ) nám načíta znak a chceli by sme napríklad začať načítavať po reťazcoch, tak v prvom reťazci by nám chýbalo prvé písmenko. Práve toto ošetruje funkcia ungetc( ) – vráti znak, ktorý sme načítavali do súboru, resp. posunie “kurzor” tak, akoby sa načítavanie nezačalo.

Zápis formátovaných dát do súboru – fprintf( )

Táto funkcia umožňuje zapisovať do súboru konkrétne formátované dáta. Práve druhý parameter tejto funkcie určuje či pôjde o číslo, znak , reťazec alebo niečo íné. Tieto koeficienty sú zhodné s funkciou fscanf( ).

Príklad
FILE *f; 
f = fopen("C:test.txt","w");
fprintf(f,"%s","ahoj"); //symbol s označuje, že ide o reťazec
fclose(f);


Zapisovanie bloku dát do súboru – fwrite( )

Funkcia fwrite( ) obsahuje už viac parametrov, ale jej základná idea – vypisovať blok dát akejkoľvek veľkosti do súboru je veľmi prostá. Prototyp funkcie vyzerá takto:

fwrite (blok_dát , veľkosť_prvku ,počet_prvkov , pointer FILE);

blok_dát – označuje buď text napísaný v úvodzovkách , alebo je to premenná obsahujúca zdroj, ktorý chceme zapísať do súboru.
veľkosť_prvku – je to veľkosť každého prvku v bajtoch, ktorý sa má zapisovať. Normálne je to hodnota 1, pretože znak má takúto veľkosť počet_prvkov – táto hodnota označuje počet prvkov, ktoré zapíšeme. Teda, ak vypisujeme pole znakov, tak toto číslo musí byť také veľké, koľko prvkov naše pole obsahuje.

Príklad
FILE *f; 
char buffer[34];

f = fopen("C:test.txt","w");
fwrite (buffer , 1 , 34 , f);
fclose(f);


Používanie bufferu


Buffer je označenie pre dočasnú pamäť, kde sa ukladajú údaje určené k ďalšiemu spracovaniu. Buffer sa preto dá veľmi dobre využiť v rôznych programoch. Jeho základnou úlohou je strážiť čo sa skutočne má zapísať a čo nie. Teda či sa majú zmeny, ktoré s dátami robíme zapísať aj fyzicky do súboru, ktorý napríklad upravujeme alebo nie. Predstavíme si dvojicu funkcii - fflush() a setbuf( ), ktoré majú na starosti prácu s bufferom.

Vytvorenie bufferu ako poľa – setbuf( )

Táto funkcia pracuje s bufferom, ktorý si samy vytvoríme. Teda jeho veľkosť nie je obmedzená priamo nejakým číslom. Buffer je v tomto prípade pole, najlepšie pole znakov. Po priradený bufferu pointeru typu FILE, bude každý výpis do súboru, ktorý reprezentuje pointer typu FILE vykonaný najskôr do bufferu, teda do pamäte. To znamená, že fyzicky sa dáta do súboru nezapíšu. Fyzicky sa do súboru dáta zapíšú z bufferu až po použití funkcii fclose( ), fflush( ) alebo po ukončení aplikácie. Funkcia fflush( ) vyvolá zapísanie bufferu do súboru. Rozdiel v našom prípade nebude prakticky vidno, ale je dôležité si uvedomiť, že zapisovanie neprebieha v prvom prípade (f1) okamžite fyzicky, ale sa zapisuje do pamäte – buffera a až po vykonaní funkcie fflush( ) sa zapíšu dáta do súboru.

Príklad
char buffer[BUFSIZ];		//BUFZIZ – konštanta s hodnotou 51
FILE *f1,*f2;

f1 = fopen ("C:test1.txt","w");
f2 = fopen ("C:test2.txt","w");
setbuf (f1,buffer); //nastavenie bufferu pre pointer FILE
fputs ("Ahoj svet",f1); //tento zápis ide IBA do bufferu zatiaľ
fflush (f1); //až teraz sa zapíšu dáta do súboru

setbuf (f2,NULL); //buffer s hodnotou NULL, teda žiadny
fputs ("dobrý deň",f2);

fclose (f1);
fclose (f2);


O buffer sa stará aj príbuzná funkcia setvbuf( ).

Vytvorenie dočastného súboru – tmpfile( ) a dočasného mena – tmpnam( )

Spoločne s bufferom ako dočasné úložisko dát môžeme použiť dočasný súbor. Ten sa vytvorí v momente zavolania funkcie, v adresári projektu a vymaže sa automaticky po zatvorení tohto súboru, alebo po ukončení programu. Takže ho môžeme používať podobne ako buffer, na úpravu dát “na nečisto“. Dočasný súbor má unikátne meno, takže nie je možná kolízia s existujúcimi súbormi. Tento súbor sa vytvorí v móde zapisovania a čítania. Typické použitie je napríklad pri otvorení súboru sa jeho obsah načíta do bufferu a vypíše sa do dočasného súboru, s ktorým budeme pracovať v programe. Ak budeme chcieť zmeny uložiť, tak sa jednoducho obsah dočasného súboru skopíruje do nášho súboru trvalého.

Príklad - tmpfile
FILE *f;		 
char str[20];
f = tmpfile (); //vytvorenie dočasného súboru
fputs("cauko",f); //zapísanie reťazca do neho
rewind(f); //presunutie “kurzoru” na začiatok súboru
fgets(str,20,f); //načítanie riadku v dočasnom súbore

ShowMessage(str); //výpis
fclose (f); //zatvorenie súboru + jeho vymazanie


Avšak časť funkcie tmpfile( ) je nám k dispozícii ako funkcia tmpnam( ). Táto funkcia obsahuje čisto len proces vytvorenia špeciálneho/unikátneho mena pre súbor.

Príklad – tmpnam( )
FILE *f; 
char meno[40];
tmpnam(meno); //priradenie vytvoreného mena
f = fopen(meno,"w"); //otvorenie súboru fclose(f);


Budúci diel bude venovaný postupom a iba konkrétnym príkladom na použitie príkazov, ktoré sme si ukazovali len zbežne. Bude to diel plný ukážkových programov na rôzne veci.

 

Súvisiace články:

Prehľad všetkých dielov

Neprehliadnite: