Práce se soubory v jazyku C V kapitole je rozebrána práce se soubory v jazyku C. Je uvedeno dělení souborů, způsoby práce se soubory, funkce souborového systému a makra v hlavičkovém souboru stdio.h. Dále jsou rozebrány metody čtení a zápisu do souboru, testy a chyby při práci se soubory. Pozornost je věnovaná též práci s binárními soubory. Látka je doložena řadou praktických příkladů. Klíčové pojmy: Soubory textové, binární, otevření a zavření souboru, režimy přístupu k souborům.
Pojem soubor Soubor je posloupnost znaků (bytů) ukončená speciální kombinací, která již do souboru nepatří. (EOF = End Of File). Se soubory je možné v programu pracovat i s využitím přesměrování vstupu a výstupu programu, známého z příkazového řádku. Přesměrování výstupu programu do souboru Standardní V/V programu lze přesměrovat do souboru: Nazev_spustitelneho_programu > nazev_souboru Příklad Program ascii.exe zapíše ASCII tabulku do souboru: ascii > soubor
Připojení výstupu programu do souboru Nazev_spustitelneho_programu >> nazev_souboru Program ascii.exe připojí ASCII tabulku do souboru: ascii >> soubor Přesměrování vstupu programu ze souboru Program bude číst data za souboru program < soubor
2.11.11
Práce se soubory v jazyku C
1/25
Obsah souboru lze vypsat i pomocí systémové funkce type: system(”type data.dat”);
Abychom ji mohli použít, nutno vložit: #include <process.h>
nebo: #include <stdlib.h>
Dělení souborů Soubory dělíme na: Textové : řádky textu Binární : o hodnoty ve tvaru, jak jsou uloženy v paměti o nerozlišují se řádky
Způsoby práce se soubory
Čtení Zápis Připisování kombinované
Jaké hlavičkové soubory musíme připojit pro práci se soubory? Funkční prototypy pro práci se soubory jsou v stdio.h Základem pro přístup k souborům je datový typ FILE. Deklarace souborové proměnné FILE *ps; ps - Ukazatel na souborovou proměnnou Funkce souborového systému fopen, fclose, fgetc, fputc, fgets, fputs, fscanf, fprintf, fread, fwrite, fseek, ftell, remove, rename, rewind, fflush, ungetc
Otevření a zavření souboru Otevření souboru : spojení souborové proměnné s konkrétním souborem
2.11.11
Práce se soubory v jazyku C
2/25
určení režimu přístupu
ps = fopen("nazev souboru”,"režim přístupu"); Vhodné je testovat návratovou hodnotu: Test správného otevření souboru #include<stdio.h> #include
#include<stdlib.h> int main(){ FILE *ps; if((ps = fopen("data.dat","r"))==NULL){ printf("Chyba pri otevirani souboru\n"); exit(1);
// nebo vlastní osetreni chyby
} return 0; }
Volání funkce exit vyžaduje vložit hlavičkový soubor: #include <stdlib.h>
nebo: #include <process.h>
Počet současně otevřených souborů Počet souborů, které můžeme z programu současně otevřít je omezen operačním systémem – dá se určit pomocí makra FOPEN_MAX Toto makro je definované v stdio.h: #define FOPEN_MAX 20 Hodnotu FOPEN_MAX lze vypsat funkcí printf("%d", FOPEN_MAX); Další makra v stdio.h FILENAME_MAX EOF
maximální délka jména souboru je def. v stdio.h: #define FILENAME_MAX 260 makro indikující konec souboru Je def. v stdio.h: #define EOF (-1)
Režimy přístupu k souborům Přípustné hodnoty režimu přístupu : 2.11.11
Práce se soubory v jazyku C
3/25
"r" "w" "a" "rb" "wb" "ab" "r+" "w+" "a+" "r+b" "rb+" "w+b" "wb+" "a+b","ab+"
Otevře textový soubor pro čtení Vytvoří textový soubor pro zápis Otevře textový soubor pro připisování Otevře binární soubor pro čtení Vytvoří binární soubor pro zápis Otevře binární soubor pro připisování Otevře textový soubor pro čtení/zápis Vytvoří textový soubor pro čtení/zápis Otevře textový soubor pro čtení/připisování Otevře binární soubor pro čtení/zápis Otevře binární soubor pro čtení/zápis Vytvoří binární soubor pro čtení/zápis Vytvoří binární soubor pro čtení/zápis Vytvoří binární soubor pro čtení/připisování
Otevření souboru pro čtení i zápis ps = fopen("nazev souboru","režim přístupu");
režim přístupu: "r+" "w+" "r+b" "rb+" "w+b" "wb+"
Otevře textový soubor pro čtení/zápis Vytvoří textový soubor pro čtení/zápis Otevře binární soubor pro čtení/zápis Otevře binární soubor pro čtení/zápis Vytvoří binární soubor pro čtení/zápis Vytvoří binární soubor pro čtení/zápis
Otevření soubor pro připisování ps = fopen("nazev souboru”,"režim přístupu");
Režim přístupu: "a" "ab" "a+" "a+b","ab+"
Otevře textový soubor pro připisování Otevře binární soubor pro připisování Otevře textový soubor pro čtení/připisování Vytvoří binární soubor pro čtení/připisování
Zavření souboru fclose(ps);
2.11.11
Práce se soubory v jazyku C
4/25
Čtení ze souborů Čtení znaků ze souboru Čtení znaku do proměnné typu char: c=fgetc(fr);
Program, který vypíše sám sebe na obrazovku: char c; FILE *fr; fr=fopen("C_konzola.cpp","r"); while ((c=fgetc(fr))!=EOF){ putc(c,stdout); } getch(); fclose(fr);
Čtení řetězce ze souboru fgets(s,delka,fr); konec se testuje na NULL Čtení lze provádět i v hlavičce cyklu : char s[80]; while ((fgets(s,80,fr)) != NULL) Příklad: FILE *fr; int c; char s[80]; puts("Zadej jmeno souboru: "); gets(s); puts(s); fr = fopen(s, "r"); while ((fgets(s,80,fr)) != NULL) {printf("%s",s);Sleep(100);} fclose(fr);
Čtení čísel ze souboru Formátovaný V/V : fscanf(fr,"formátové specifikace", seznam adres proměnných); fprintf(fw,"formátové specifikace",seznam proměnných); Postup práce se souborem: deklarujeme souborovou proměnnou 2.11.11
Práce se soubory v jazyku C
5/25
otevřeme soubor čteme/zapisujeme (v cyklu) uzavřeme soubor
Příklad: Následující program přečte ze souboru znamky.dat nejprve jméno žáka, a potom 7 známek do pole z, z nichž vypočítá průměr. Čtení a výpočet součtu známek probíhá v cyklu for. Za cyklem se vypočítá průměr a načtené jméno a vypočítaný průměr se vypíší na obrazovku. FILE *fr; char jmeno[20]; int z[7],i; float prum=0; fr = fopen("znamky.dat", "r"); while (!feof(fr))
{
prum=0; fscanf(fr,"%s",&jmeno); for (i=0;i<7;i++){fscanf(fr,"%d",&z[i]);prum+=z[i];} prum/=7; printf("%s %7.2f\n\r",jmeno,prum); } fclose(fr);
Obsah souboru znamky.dat: Josef 1 2 3 4 5 4 3
Test konce souboru while ((c=fgetc(fr))!=EOF){….} while ((fgets(s,80,fr)!=NULL){….} while (!feof(fp))
ukazatel na soubor
Funkce vrací nenulovou hodnotu, jestliže soubor, spojený s fp dosáhl konce. Cyklus pro zpracování dat ze souboru : while(!feof(fp)){…}
2.11.11
Práce se soubory v jazyku C
6/25
Zápis do souborů Zápis znaků do souboru fputc(c,fw);putc(c,fw);
Následující program čte znaky, zadávané z klávesnice a zapisuje je do souboru znaky.txt. Čtení probíhá v cyklu while, dokud uživatel nezadá konec souboru Ctrl+Z, nebo F6. char c; FILE *fw; fw=fopen("znaky.txt","w"); while ((c=getc(stdin))!=EOF){ putc(c,fw); } fclose(fw);
Zápis řetězce do souboru fputs(s,fw);
Následující program čte v cyklu while řetězce z klávesnice. Každý načtený řetězec zapíše do souboru znaky.txt a odřádkuje. Čtení probíhá, dokud uživatel nezadá konec souboru Ctrl+Z, nebo F6. char s[80]; FILE *fw; fw=fopen("znaky.txt","w"); while (gets(s)!=NULL){ fputs(s,fw); fputs("\n",fw); } fclose(fw);
Zápis čísel do souboru? fprintf(fw,"formátové specifikace",seznam proměnných);
Následující program čte v cyklu while čísla z klávesnice. Každé načtené číslo zapíše do souboru cisla.txt . Čtení probíhá, dokud uživatel nezadá konec souboru Ctrl+Z, nebo F6. char c; FILE *fw; int cislo; fw=fopen("cisla.txt","w"); while ((scanf("%d",&cislo))!=EOF){ fprintf(fw,"%d ",cislo); }
2.11.11
Práce se soubory v jazyku C
7/25
fclose(fw);
Chyby při práci se soubory Chyby mohou nastat během těchto operací: Otevření souboru Uzavření souboru Čtení ze souboru Zápis do souboru Kontrola správného otevření souboru Vhodné je testovat návratovou hodnotu: FILE *ps; if((ps = fopen("data.dat","r"))==NULL){ printf("Chyba pri otevirani souboru\n"); exit(1);
// nebo vlastní osetreni chyby
Kontrola správného čtení ze souboru Funkce ferror() vrací nenulovou hodnotu, pokud došlo při práci se souborem, spojeným s fr k chybě, jinak vrací nulu. Následující program čte jednotlivé znaky ze souboru znaky.txt . Dojde-li k chybě, vypíše chybové hlášení a přeruší čtení. Jestliže nedojde k chybě, vypíše načtený znak na obrazovku. char c; FILE *fr; fr=fopen("znaky.txt","r"); while (!feof(fr)) { c = fgetc(fr); if(ferror(fr)) { printf("Chyba cteni ze souboru\n"); break; } else putc(c,stdout); } fclose(fr);
ferror() hlásí stav vzhledem k poslednímu přístupu k souboru. Pro úplnou kontrolu chyb by bylo vhodné ji volat po každé operaci se souborem.
2.11.11
Práce se soubory v jazyku C
8/25
V/V binárních dat Výhody použití binárních souborů
Menší velikost (při ukládání čísel) Lepší utajení dat
Čtení/zápis do binárních souborů fread(adresa,velikost,počet,fp); fwrite(adresa,velikost,počet,fp);
adresa – adresa místa v paměti, na které ukládáme přečtené hodnoty velikost - délka každého prvku v bytech počet - počet čtených prvků Pro použití fread() a fwrite() pro čtení a zápis binárních dat musí být soubory otevřeny pro binární operace. Určení velikosti proměnné Pomocí operátoru sizeof Příklad: int i = 100; fwrite(&i,4,1,fp); fwrite(&i,sizeof(int),1,fp); fwrite(&i,sizeof i,1,fp); fread(&i,sizeof(i),1,fp);
Následující program otevře dva soubory pro zápis: cis1.dat jako textový a cis2.dat jako binární. Do obou zapíše maximální celé číslo: 0x7fffffff. Do textového souboru zapisuje funkcí: fprintf(fw1,"%d",a) a do binárního funkcí: fwrite(&a,sizeof(int),1,fw2). FILE *fw1,*fw2; fw1 = fopen("cis1.dat","w"); fw2 = fopen("cis2.dat","wb"); int a=0x7fffffff; fprintf(fw1,"%d",a); fwrite(&a,sizeof(int),1,fw2); fclose(fw2); fclose(fw1);
Následuje zobrazení obsahu obou souborů v hexadecimálním tvaru: cis1.dat
2.11.11
Práce se soubory v jazyku C
9/25
cis2.dat:
Zápis celého pole do souboru jedním příkazem Funkce fwrite může do souboru najednou zapsat celé pole hodnot. Následující program definuje pole čísel a toto zapíše do souboru cis.dat nejprve v cyklu for po jednotlivých číslech, a potom jedním voláním funkce fwrite celé pole najednou. FILE *fw; int d[]={123,321,12,21,1,2}; fw = fopen("cis.dat","wb"); for(int i=0;i<sizeof(d)/sizeof(int);i++) fwrite(&d[i],sizeof(int),1,fw); fwrite(d,sizeof d, 1, fw); fclose(fw);
Zobrazení obsahu souboru cis.dat v hexadecimálním tvaru:
Čtení celého pole ze souboru jedním příkazem Funkce fread může do pole najednou načíst hodnoty ze souboru. Čtení 6 čísel: Následující program přečte ze souboru cis.dat 6 čísel, zapsaných do souboru předchozím programem. 2.11.11
Práce se soubory v jazyku C
10/25
Nejprve čte čísla jednotlivě v cyklu for , kde načtené číslo vždy vypíše a potom hodnotu proměnné vynuluje, potom přečte celé pole jedním příkazem fread(d,sizeof d, 1, fr) a následně obsah pole d vypíše cyklem for. FILE *fr; int d[6],i; fr = fopen("cis.dat","rb"); for(i=0;i<6;i++){ fread(&d[i],sizeof(float),1,fr); printf("%d ",d[i]); d[i]=0; } printf("\n"); fread(d,sizeof d, 1, fr); for(i=0;i<6;i++){ printf("%d ",d[i]); } fclose(fr);
Výpis na obrazovku:
Následující program spojuje zápis pole do souboru a jeho následné čtení. double d[10]={ 1.2 , 2.3 , 3.4 , 4.5 , 5.6 , 6.7 , 100.1 , 200.5 , 300.4 , 1000.8 }; FILE *fp; int i; fp=fopen("data.dat","wb"); //Zápis pole do souboru fwrite(d,sizeof d, 1, fp); fclose(fp); //Vymazání pole for(i=0;i<10;i++) d[i] = -1.0; //Čtení celého pole v jednom kroku fp=fopen("data.dat","rb"); fread(d,sizeof d, 1, fp); fclose(fp); //Výpis pole
2.11.11
Práce se soubory v jazyku C
11/25
for(i=0;i<10;i++) printf("%lf\n",d[i]);
Výpis na obrazovku:
Kontrola chyb při práci s binárními soubory Lze provést porovnáním počtu zapsaných nebo přečtených prvků s požadovaným počtem. Funkce fwrite vrací počet zapsaných hodnot a funkce fread vrací počet načtených hodnot. Následující příkazy kontrolují, zda byla zapsána a načtena jedna hodnota: if(fwrite(&i, sizeof(int),1,fp)!=1) { printf("Chyba pri zapisu.\n"); exit(1); } if(fread(&i, sizeof(int),1,fp)!=1) { printf("Chyba pri cteni.\n"); exit(1); }
Lze rovněž použít funkce feof() a ferror() jako u textových souborů.
Náhodný přístup k datům Přístup k libovolnému místu v souboru fseek(fp,posun,počátek);
Makra, definována v stdio.h určují počátek: Počátek SEEK_SET SEEK_CUR SEEK_END 2.11.11
Význam Začátek souboru Aktuální pozice v souboru Konec souboru Práce se soubory v jazyku C
12/25
Zjištění aktuální pozice v souboru loc=ftell(fp);
Doporučuje se používat náhodný přistup jen u binárních souborů U textových souborů je vhodné fseek používat jen pro nastavení pozice, která byla zjištěna pomocí funkce ftell()
Příklad: Následující program si vyžádá pozici, od které začíná číslo, uložené do souboru cis.dat. Protože celá čísla zabírají 4 byty, musí být zadaná hodnota dělitelná 4. Potom program nastaví ukazatel v souboru na zadanou pozici loc a přečte z této pozice celé číslo a uloží je do proměnné i. Nakonec vypíše pozici i načtenou hodnotu čísla. long loc; int i; FILE *fp; fp=fopen("cis.dat","rb"); printf("Zadejte pozici vyhledavaneho cisla:"); scanf("%ld",&loc); fseek(fp,loc,SEEK_SET); fread(&i, sizeof(int),1,fp); printf("Hodnota na pozici %ld je %d ",loc,i); fclose(fp);
Výpis programu:
Příklad: Kopírování obsahu jednoho textového souboru do jiného po znacích v opačném pořadí. long loc; FILE *in,*out; char ch; in=fopen("mesta.txt","rb"); out=fopen("pozpatku.txt","wb"); fseek(in,0L,SEEK_END); loc=ftell(in);loc--; while(loc>=0L){
2.11.11
Práce se soubory v jazyku C
13/25
fseek(in,loc,SEEK_SET); ch=fgetc(in); fputc(ch,out); loc--; } fclose(in); fclose(out);
Vstupní a výstupní soubor:
Další funkce pro práci se soubory Funkce rename Umožňuje přejmenovat soubor. rename("zdroj","cíl");
Příklad: rename("mesta.txt","MestaCR.txt");
Funkce remove Odstraní soubor. Příklad: remove("pozpatku.txt");
Funkce rewind Nastaví ukazatel na začátek souboru. Následující program vypíše obsah souboru MestaCR.txt, potom nastaví ukazatel na začátek souboru a vypíše ho znovu: FILE *fr; int c;
2.11.11
Práce se soubory v jazyku C
14/25
char s[80]; fr = fopen("MestaCR.txt", "r"); while ((fgets(s,80,fr)) != NULL) printf("%s",s); rewind(fr); printf("\n"); while ((fgets(s,80,fr)) != NULL) printf("%s",s); fclose(fr); getch();
Funkce fflush Vyprázdní obsah zásobníku do souboru, spojeného s ukazatelem fp FILE *fp; ..... fflush(fp);
Příklady práce se soubory. 1.
Čtení dvou čísel ze souboru a výpis jejich průměru na obrazovku
Program čte ze souboru cisla.dat dvojici čísel v jednom řádku a vypisuje jejich průměr na obrazovku. FILE *fr; fr=fopen("cisla.dat","r"); float a,b; while(!feof(fr)){ fscanf(fr,"%f %f",&a,&b); if(feof(fr))break; printf("%.2f\n",(a+b)/2.); } fclose(fr);
Vstupní a výstupní soubor
2.11.11
Práce se soubory v jazyku C
15/25
2. Čtení čísel ze souboru a zápis jejich součtu do jiného souboru Program čte dvě čísla v jednom řádku ze souboru, zapíše je a jejich součet do jiného souboru, původní soubor zruší a nový přejmenuje. Nakonec soubor vypíše. FILE *fr,*fw; fr=fopen("cisla.dat","r"); fw=fopen("cisla2.dat","w"); float a,b; while(!feof(fr)){ fscanf(fr,"%f %f",&a,&b); if(feof(fr))break; fprintf(fw,"%.2f + %.2f = %.2f\n",a,b,a+b); } fclose(fr); fclose(fw); remove("cisla.dat"); rename("cisla2.dat","cisla.dat"); system("type cisla.dat");
Výsledný obsah souboru cisla.dat: 1.00 + 2.00 = 3.00 2.00 + 6.00 = 8.00 2.00 + 3.00 = 5.00 8.00 + 2.00 = 10.00 2.00 + 5.00 = 7.00 3.00 + 3.00 = 6.00 8.00 + 2.00 = 10.00 77.00 + 88.00 = 165.00
3. Zápis zadaných řetězců do souboru funkcí fprintf Program zapisuje jména, zadaná z klávesnice do souboru data.dat – k zápisu je použitá funkce fprintf Čtení jmen z klávesnice probíhá, dokud uživatel nezadá konec souboru Ctrl+Z, nebo F6. FILE *fw; char jmeno[80]; fw=fopen("data.dat","w"); while(!feof(stdin)){ gets(jmeno); if(feof(stdin))break;
2.11.11
Práce se soubory v jazyku C
16/25
fprintf(fw,"%s\n",jmeno); } fclose(fw);
4. Zápis zadaných řetězců do souboru funkcí fputs Program zapisuje jména, zadaná z klávesnice do souboru data.dat – k zápisu je použita funkce fputs FILE *fw; char jmeno[80]; fw=fopen("data.dat","w"); while(!feof(stdin)){ gets(jmeno); if(feof(stdin))break; fputs(jmeno,fw); fputs("\n",fw); } fclose(fw);
5. Volba vypisovaného souboru Program vypíše uživateli nabídku, zda chce vypsat jména mužů, nebo žen. Podle volby uživatele nastaví ukazatel souboru na muzi.dat nebo zeny.dat . První cyklus while skončí jen tehdy, když uživatel zvolí jednu z nabízených možností, jinak se bude vypisovat: Spatna volba . #include <stdio.h> #include #include <windows.h> #include <stdlib.h> main(){ FILE *fr; int c,volba; while(volba>2 || volba<1){ system("cls"); printf("Co chces vypsat:\ \n1. muze\ \n2. zeny\n"); scanf("%d",&volba); fflush(stdin); switch(volba){ case 1:fr = fopen("muzi.dat", "r");break; case 2:fr = fopen("zeny.dat", "r");break; default:printf("Spatna volba");getch();
2.11.11
Práce se soubory v jazyku C
17/25
} } while ((c = fgetc(fr)) != EOF) { putc(c,stdout); Sleep(100);} fclose(fr); getch(); }
6.
Zápis odpovědí na dotazník do souboru
Následující program klade uživateli 3 otázky a po jejich zodpovězení se zeptá, zda chce opakovat (pro jiného respondenta). Všechny odpovědi se připisují do souboru: dotaznik.txt ve tvaru 1='A'/0='N'. FILE *fw; char jmeno[20],nk,pr,ld,op='A'; int i,j,k,c,b; char zn; fw = fopen("dotaznik.txt", "a+"); while(op=='A'){ system("cls"); printf("Jsi nekurak?"); nk=getche(); printf("\nJsi pravicak?"); pr=getche(); printf("\nJsi lidumil?"); ld=getche(); fprintf(fw,"%d %d %d\n",nk=='A',pr=='A',ld=='A'); printf("\nOpakovat ? (A/N)"); op=getche(); } fclose(fw);
Soubor dotaznik.txt:
2.11.11
Práce se soubory v jazyku C
18/25
7.
Vyhodnocení dotazníku
Následující program vyhodnotí data v souboru dotaznik.txt, který byl vytvořený předchozím programem. #include <stdio.h> #include #include <stdlib.h> main(){ FILE *fr; char jmeno[20]; int a,b,c; int nk=0,pr=0,ld=0,celk=0; system("cls"); fr = fopen("dotaznik.txt", "r"); while (!feof(fr)){ fscanf(fr,"%d %d %d",&a,&b,&c); if(feof(fr))break; celk++; if(a)nk++; if(b)pr++; if(c)ld++; } printf("Vyhodnoceni: nekuraku:
\n\
%d\n
\
pravicaku: %d\n
\
lidumilu:
\
%d\n
z celkoveho poctu: %d",nk,pr,ld,celk); fclose(fr); getch(); }
Výpis na obrazovku: Vyhodnoceni: nekuraku:
2
pravicaku: 2 lidumilu:
2
z celkoveho poctu: 4
8. Výpis pozice zadaného znaku – funkce ftell Následující program si vyžádá zadání znaku a vypíše všechny pozice, na kterých se tento znak vyskytuje. Zadávání znaku je zacykleno cyklem do-while , který trvá, dokud uživatel namísto znaku nestiskne klávesu Escape (s kódem 27).
2.11.11
Práce se soubory v jazyku C
19/25
Do cyklu do-while je vnořený cyklus while , v němž je prohledávaný celý soubor a pokud hledaný znak nalezne, vypíše jeho pozici. Aby hledání dalšího zadaného znaku probíhalo od začátku souboru, je třeba převinout soubor na začátek funkcí rewind. long loc; int c,d; FILE *fr; fr=fopen("muzi.dat","r"); do{ printf("\nZadejte znak (ukonci Escape):"); c=getche(); if(c==27)break; fflush(stdin); while(!feof(fr)){ d=fgetc(fr); if(c==d)printf("\n%ld",ftell(fr)); } rewind(fr); // previnutí souboru }while(c!=27); fclose(fr);
9. Výpis znaku na zadané pozici – funkce fseek Následující program je doplňkový k předchozímu v tom smyslu, že zadáme pozici a program vypíše znak na zadané pozici. Počet bytů souboru je stanoveno tak, že se nejprve soubor nastaví na konec funkcí: fseek(fp,0L,SEEK_END) a potom se určí pozice tohoto posledního bytu funkcí: ftell(fp)-1. Dále se v cyklu while opakovaně čte pozice a vypisuje se znak na této pozici. Cyklus se opakuje, dokud jako požadovanou pozici nezadáme záporné číslo. long loc,N; FILE *fp; char c; fp=fopen("zeny.dat","r"); fseek(fp,0L,SEEK_END); loc=ftell(fp); loc--; N=loc; while(1){ printf(" Zadej c. vyhledavaneho bytu (cislovani je od 0 do %ld)\n \ ukonci zapornym cislem:",loc); scanf("%ld",&loc);
2.11.11
Práce se soubory v jazyku C
20/25
fflush(stdin); if(loc<0)break; if(loc>N)printf("Soubor nema tolik bytu\n"); fseek(fp,loc,SEEK_SET); printf("\nHodnota na pozici %ld je %c \n",loc,(char)getc(fp)); rewind(fp); } fclose(fp);
10. Výpis souboru od konce Jde o kopírování obsahu jednoho textového souboru do jiného po znacích v opačném pořadí. Zde nedochází ke kopírování do jiného textového souboru, ale k jeho výpisu do konzolového okna pozpátku po jednotlivých znacích. Volání funkce fputc(ch,out) , kde out je ukazatel na výstupní soubor je nahrazeno voláním: putc(ch,stdout). long loc; FILE *in; char ch; in=fopen("mesta.txt","rb"); fseek(in,0L,SEEK_END); loc=ftell(in);loc--; while(loc>=0L){ fseek(in,loc,SEEK_SET); ch=fgetc(in); putc(ch,stdout); loc--; } getch(); fclose(in);
11. Kontrola, zda se zadané jméno vyskytuje v souboru Následující program si od uživatele vyžádá zadat jméno a hledá toto jméno v souboru: jmena.txt . Pokud jméno v souboru najde, vypíše text: Jmeno nalezeno , v opačném případě vypíše: Jmeno nenalezeno . FILE *fr; int c,ok=0,i,j,n; char jm[10],jmeno[10]; system("cls"); fr = fopen("jmena.txt", "r");
2.11.11
Práce se soubory v jazyku C
21/25
printf("Zadej jmeno: "); scanf("%s",jm); while(!feof(fr)){ fscanf(fr,"%s\n",jmeno); if((!strcmp(jm,jmeno))){ok=1;break;} } fclose(fr); if(!ok)printf("Jmeno nenalezeno"); else printf("Jmeno nalezeno");
12. Kontrola přístupových práv Jestliže se zadané jméno a heslo vyskytuje v souboru jmen a hesel, vypíše se: Pristup povolen, jestliže ne, vypíše se: Pristup zamitnut. FILE *fr; int c,ok=0,i,j,n; char jm[10],hes[10],jmeno[10],heslo[10]; system("cls"); fr = fopen("hesla.txt", "r"); printf("Zadej jmeno: "); scanf("%s",jm); printf("Zadej heslo: "); i=0; do{ hes[i]=getch(); if(hes[i]==13)break; putc('*',stdout); i++; }while(true); hes[i]='\0'; while(!feof(fr)){ fscanf(fr,"%s %s",jmeno,heslo); if((!strcmp(jm,jmeno)) && (!strcmp(hes, heslo))) {ok=1;break;} else ok=0; } fclose(fr); if(!ok)printf("\nPristup zamitnut"); else printf("\nPristup povolen");
Soubor hesla.txt: Josef Josef Petr Petr
2.11.11
Práce se soubory v jazyku C
22/25
Pavel Pavel Imrich Imrich Karel Karel Jana Jana Marie Marie
13. Program pro výuku slovíček. Pro zadané české slovíčko vypíše anglický ekvivalent. Jestliže zadané slovo ve slovníku neexistuje, vypíše: Neni ve slovniku. char slov[40]; char ces[80]; FILE *fr; char op='a'; fr=fopen("slovicka.txt","r"); while(op=='a' || op=='A'){ rewind(fr); printf("\nZadej ceske slovo: "); gets(ces); // Vyhledani slova while(!feof(fr)){ fscanf(fr,"%s",slov); if(!strcmp(ces,slov)){ fscanf(fr,"%s",slov); printf("Anglicky preklad je: %s",slov); break; } } if(feof(fr))printf("Neni ve slovniku\n"); printf("\nChces zadat dalsi slovo (a/n)?"); op=getche(); }
Soubor slovicka.txt: ano yes ne no matka mother otec father syn son dcera daughter dite child pocitac computer
2.11.11
Práce se soubory v jazyku C
23/25
14. Postupné zkoušení ze všech slovíček v souboru Program zkouší uživatele z překladu českých slovíček do angličtiny. Slovíčka, které uživatel neumí, jsou zapsána do souboru slovneum.txt . FILE *fr,*fw; int c; char ang[20],ces[20],odp[20]; fr = fopen("slovicka.txt", "r"); fw = fopen("slovneum.txt", "w"); printf("Chces-li ukoncit, zadej quit\n\n"); while (!feof(fr)) { fscanf(fr,"%s %s",ces,ang); if(feof(fr))break; printf("%s ",ces); scanf("%s",&odp); if(!strcmp("quit",odp))break; if (!strcmp(ang,odp)) printf("dobre \n") ; else {printf("spatne \n"); fprintf(fw,"%s %s\n",ces,ang);} } printf("\nKonec"); fclose(fr); fclose(fw);
Soubor slovicka.txt je stejný jako v předešlém příkladě. 15. Zkoušení ze slovíček v souboru – program slovíčka vybírá náhodně Následující program je vylepšení předchozí verze – program vybírá slovíčka ze souboru náhodně. Nejprve v cyklu while zjistí počet slovíček v souboru, potom v cyklu do- while generuje náhodné číslo v tomto rozsahu, provede příslušný počet „prázdných čtení ze souboru“ a přečte dvojici: české a anglické slovíčko. Anglické slovíčko vypíše a načte české slovíčko jako uživatelovu odpověď. To porovná s hodnotou slovníku a vypíše odpovídající text: dobře, nebo spatne. Špatně zodpovězená slovíčka uloží do souboru: slovneum.txt . #include <stdio.h> #include #include <string.h> #include <stdlib.h> #include
2.11.11
Práce se soubory v jazyku C
24/25
main() { int N=0,i,j; FILE *fr,*fw; int c; char ang[80],ces[20],odp[20]; fr = fopen("slovicka.txt", "r"); fw = fopen("slovneum.txt", "w"); srand( (unsigned)time( NULL ) ); while (!feof(fr)) { fgets(ang,80,fr); N++; } do{ i=rand()%N; rewind(fr); for(j=0;j
fprintf(fw,"%s %s\n",ces,ang);}
}while(1); fclose(fr); fclose(fw); }
Shrnutí: V kapitole je probrána práce s textovými i binárními soubory jazyku C. Jsou rozebrány metody čtení a zápisu do souboru, různé režimy přístupu k souborům, testy a chyby při práci se soubory. U každé části jsou uvedeny příklady programů.
2.11.11
Práce se soubory v jazyku C
25/25