Још у првом разреду учили сте да улаз, односно извор података, може бити неки улазни уређај (нпр. тастатура) или датотеке ускладиштене на уређајима за складиштење (нпр. датотека на хард диску). Такође, излаз, односно одредиште података може бити неки излазни уређај (нпр. монитор) или датотеке ускладиштене на уређајима за складиштење.
Зашто су нам онда потребне датотеке, ако имамо тастатуре и мониторе?
- када програм престане са извршавањем подаци се губе – чување података у датотекама значи да ће подаци бити сачувани и након прекида извршавања програма,
- унос великог броја података током извршавања програма захтева много времена – ако су подаци већ уписани у датотеку, може им се приступити брзо помоћу неколико наредби,
- сачувани подаци могу се лако премештати са једног рачунара у други заједно са извршним програмом, итд.
У програмском језику C, улазни и излазни уређаји могу да се посматрају као датотеке неограничене дужине. Код улаза крај датотеке означавамо специјалним карактером којег уносимо путем тастатуре (CTRL+D за UNIX/LINUX оперативне системе, односно CTRL+Z за Microsoft оперативне системе).
Према начину чувања података у датотекама, датотеке делимо на:
- текстуалне датотеке и
- бинарне датотеке.
Текстуалне датотеке садрже низове карактера који су подељени у редове помоћу карактера за прелазак у нови ред (‘\n‘). Сви карактери у текстуалној датотеци могу или да се исписују на екран или имају специјалну функцију. Бројеви, представљени у меморији у бинарном облику, у току преноса из меморије у текстуалну датотеку конвертују се у низ цифара (односно, из низа цифара у бинарни облик када се из датотеке преносе у меморију). Садржај тексуалних датотека можемо исписати на екран помоћу наредбе cat у UNIX/LINUX командном интерфејсу, односно наредбе type у командним интерфејсима Microsoft оперативних система.
Бинарне датотеке садрже низова бајтова слично начину представљања података у меморији. Због тога, у току преноса из меморије, односно у меморију, не извршава се никаква конверзија, већ се врши пренос бајт по бајт. Овакве датотеке има смисла чувати само на уређајима за складиштење података – њихов приказ на монитор рачунара без адекватне конверзије бесмислен је, јер је њихов садржај неразумљив човеку. Треба напоменути и да је запис података у бинарним датотекама компактнији него у текстуалним – нпр. за запис десетоцифреног броја у бинарној датотеци потребно је 4 бајта, а у тестуалној 10 бајтова.
Датотеке можемо поделити и по организацији на:
- секвенцијалне,
- релативне и
- индексне.
Код секвенцијалних датотека приступ записима у датотеци могућ је само по редоследу по којем су записи унешени у датотеку (секвенцијални приступ).
Код релативних датотека могуће је приступити записима по произвољном редоследу на основу редног броја записа у датотеци (директни приступ).
Код индексних датотека могуће је приступити записима по произвољном редоследу на основу садржаја дела записа за идентификацију који се назива кључ (приступ помоћу кључа).
У програмском језику C користе се само секвенцијалне датотеке које су по структури низ бајтова, па се због тога називају “ток”. Код текстуалних датотека функције за улаз не реагују на карактер “\n“, а ни функције за излаз не уписују аутоматски карактер “\n” на крај реда, па су и текстуалне датотеке у ствари само низови карактера (бајтова). Оно што програмски језик C нуди је могућност позиционирања на одређени бајт у датотеци, па се читање/писање може вршити секвенцијално од тог бајта.
Било каква сложенија организација података у датотеци могућа је искључиво ако је програмер сам осмисли и имплементира, па након тога све време води рачуна о тој организацији.
Оно са чиме ћемо се ми сусрести у овој лекцији приликом рада са датотекама је:
- отварање датотеке,
- приступ датотеци,
- испитивање стања датотеке и
- затварање датотеке.
Отварање датотеке
Служи за успостављање везе програма са датотеком на основу њеног имена, приликом чега се у меморији ствара структура података која омогућава ефикасан рад са датотеком и садржи податке о њеном стању. За сваку датотеку која се користи у програму треба да постоји показивач на податак типа FILE. Показивач на податак типа FILE је структурирани тип података дефинисан наредбом typedef у stdio.h заглављу, што значи да има статус идентификатора типа података, па би показивач датотеке pFajl дефинисали на следећи начин:
FILE *pF;
Отварање датотеке врши се функцијом fopen() чији је општи облик:
FILE * fopen ( const char * imefajla, const char * rezim );
imefajla је стринг који представља назив датотеке, а ако се датотека не налази у истом директоријуму у којем се налази и извршни програм, imefajla може да садржи и ознаку уређаја и називе директоријума (путању) у којем се датотека налази.
rezim је стринг којим се дефинише начин на који ће се датотека користити.
Режим | Значење | Ако (не)постоји |
---|---|---|
r |
Отварање за читање | Ако не постоји, fopen() враћа NULL |
rb |
Отварање за читање у бинарном режиму | Ако не постоји, fopen() враћа NULL |
w |
Отварање за писање | Ако постоји њен садржај ће бити преписан, а ако не постоји биће креирана |
wb |
Отварање за писање у бинарном режиму | Ако постоји њен садржај ће бити преписан, а ако не постоји биће креирана |
a |
Отварање за измене – подаци који се додају биће уписани на крај | Ако не постоји биће креирана. |
ab |
Отварање за измене у бинарном режиму – подаци који се додају биће уписани на крај | Ако не постоји биће креирана. |
r+ |
Отварање за читање и писање | Ако не постоји, fopen() враћа NULL |
rb+ |
Отварање за читање и писање у бинарном режиму | Ако не постоји, fopen() враћа NULL |
w+ |
Отварање за читање и писање | Ако постоји њен садржај ће бити преписан, а ако не постоји биће креирана |
wb+ |
Отварање за читање и писање у бинарном режиму | Ако постоји њен садржај ће бити преписан, а ако не постоји биће креирана |
a+ |
Отварање за читање и измене | Ако не постоји биће креирана. |
ab+ |
Отварање за читање и измене у бинарном режиму | Ако не постоји биће креирана. |
Затварање датотеке
Служи за раскид веза програма и датотеке, којом се поништавају и структуре података створене приликом отварања датотеке. Врши се функцијом fclose() чији је општи облик:
int fclose ( FILE * pF );
pFajl је показивач датотеке који је придружен датотеци која се затвара. Ако се датотека успешно затвори, функција враћа вредност нула, а у случају грешке враћа EOF.
ЗАДАТАК 1. Напишите једноставан програм који отвара текстуалну датотеку mojfajl.txt у режиму за читање и измене a+, па је потом затвара.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pF; pF = fopen("mojfajl.txt", "a+"); fclose(pF); return 0; }
Писање података у датотеку
Текст се у датотеку може уписати тако што у датотеку упишемо или појединачни карактер или стринг. Синтаксе функције којима се ово имплементира су:
int fputc ( int karakter, FILE * pF ); int fputs ( const char * string, FILE * pF ); int fprintf ( FILE * pF, const char * format, ... );
fputc()
Уписује карактер у ток pF чиме се помера индикатор положаја за један. На пример:
fputc('A', pF);
fputs()
Уписује стринг у ток pF све док не достигне завршни NULL знак који се не уписује у ток. На пример:
fputs("Dobar dan", pF);
fprintf()
Уписује форматиране податке у ток pF. Формат података (и спецификатора конверзије уколико постоје) идентичан је као код команде printf()
. На пример:
double pi = 3.14159265359; fprintf(pF, "Broj pi = %.2lf", pi);
ЗАДАТАК 2. Напишите једноставан програм који отвара текстуалну датотеку mojfajl.txt у режиму за читање и писање w+, у њу уписује стринг “Dobar dan”, па је потом затвара.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pF; pF = fopen("mojfajl.txt", "w+"); fputs("Dobar dan", pF); fclose(pF); return 0; }
ЗАДАТАК 3. Преправите претходни програм тако да се приликом отварања датотеке проверава успешност отварања и о томе обавештава корисник.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pF; pF = fopen("mojfajl.txt", "w+"); if (pF != NULL) { printf("Fajl je uspesno otvoren. Vrsim upis...\n"); fputs("Dobar dan", pF); fclose(pF); } else { printf("Fajl nije uspesno otvoren!\n"); } return 0; }
Читање података из датотеке
Синтаксе функције којима се имплементира читање података из датотеке су:
int fgetc ( FILE * pF ); char * fgets ( char * string, int broj, FILE * pF ); int fscanf ( FILE * pF, const char * format, ... );
fgetc()
Враћа карактер на који тренутно показује индикатором положаја датотеке тока pF.
fgets()
Чита карактере из тока pF и смешта их као стринг у string све док се не прочита broj-1 карактера или док се не стигне до краја реда или датотеке.
fscanf()
Чита податке из тока pF и чува их према формату параметaра на локацији означене додатним аргументима.
ЗАДАТАК 4. Отворити датотеку mojfajl.txt у r режиму и пребројати колико је пута карактер $ уписан у датотеку користећи функцију fgetc().
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pFile; char c; int n = 0; pFile = fopen("mojfajl.txt", "r"); if (pFile == NULL) printf("Greska prilikom otvaranja..."); else { do { c = fgetc(pFile); if (c == '$') n++; } while (c != EOF); fclose(pFile); printf("Ovaj fajl sadrzi %d $ karaktera,\n", n); } return 0; }
ЗАДАТАК 5. Отворити датотеку mojfajl.txt у r режиму, прочитати и исписати на екран прву линију текста, односно првих 100 карактера из отворене датотеке помоћу функције fgets().
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pFile; char tekst[100]; pFile = fopen("mojfajl.txt", "r"); if (pFile == NULL) printf("Greska prilikom otvaranja..."); else { if (fgets(tekst, 100, pFile) != NULL) puts(tekst); fclose(pFile); } return 0; }
ЗАДАТАК 6. Упишите у mojfajl.txt реалан број 3.1416 и стринг “PI” (нпт. користећи Notepad). Отворите датотеку mojfajl.txt у r режиму и помоћу функције fscanf() прочитати прво податак типа float, а затим податак типа char[] и исписати их на екран.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) { FILE* pFile; char tekst[80]; float broj; pFile = fopen("mojfajl.txt", "r"); fscanf(pFile, "%f", &broj); fscanf(pFile, "%s", tekst); fclose(pFile); printf("Upisano je: %f i %s \n", broj, tekst); return 0; }
You must be logged in to post a comment.