PB071: Úvod do jazyka C - 7

Vstup a výstup

Soubory

#include <stdio.h>
FILE *
fp;
fp=fopen(název_souboru,režim); /* otevře soubor, při chybě vrátí NULL */
fclose(
fp); /* zavře soubor, při chybě vrátí EOF */
fp=tmpfile(); /* vytvoří pracovní soubor v režimu wb+;
                po skončení bude vymazán */

režim:
r otevřít pro čtení (read)
w otevřít pro zápis (write)
a otevřít pro zápis na konec existujícího souboru (append)

Za toto písmeno lze přidat b, se souborem se pak bude pracovat jako s binárním, tj. na disku budou mít záznamy přesně stejný tvar jako v paměti. Jinak se soubor považuje za textový a při převodu může docházet k modifikaci podle konvencí příslušného operačního systému (např. pod MS DOS-Windows končí řádek na disku dvojicí znaků \n\r, avšak znak \r je v textovém režimu pro program neviditelný; chová se, jako by v souboru byl pouze znak \n. V jiných OS mohou být jednotlivé řádky dokonce ohraničeny jinak než speciálním znakem.)

Na konec režimu lze rovněž přidat znak + označující, že se soubor otevírá pro aktualizaci (čtení i zápis). Mezi čtením a zápisem se musí provést příkaz pro nastavení pozice v souboru (např. fseek nebo rewind).

Automaticky jsou otevřeny "soubory" stdin (standardní vstup), stdout (standardní výstup) a stderr (standardní chybový výstup).

Příklad:

FILE *in, *out;
in=fopen("/home/ja/moje_data.dat","r");
out=fopen(argv[2],"w");
...
fclose(in);fclose(out);

Pozor na znak \

Pod operačními systémy Microsoft je třeba dávat pozor při zápisu názvu adresářů.

Místo fopen("c:\normy\tisk.prn","w") nutno psát fopen("c:\\normy\\tisk.prn","w")
(Jinak by se \n považovalo za nový řádek a \t za tabulátor.)

Funkce z rodiny printf, scanf

Standardní V/V

printf(formát,výrazy); /* vrací počet vypsaných znaků */
scanf(
formát,ukazatele); /* vrací počet přečtených položek nebo EOF */

Souborový V/V

fprintf(fp,formát,výrazy);
fscanf(
fp,formát,ukazatele);

Paměťový V/V

Zdrojem či cílem dat není vnější zařízení, ale řetězec v paměti, dovoluje však běžné formátování.

(V ANSI C v hlavičkovém souboru string.h, v C99 v stdio.h)

sprintf(řetěz,formát,výrazy);
sscanf(
řetěz,formát,ukazatele);

Formátovací řetězce

Pro výstup se ve formátovacím řetězci zapisuje vypisovaný text a formátovací příkazy ve tvaru %písmeno

Písmeno Typ Způsob výpisu Poznámka
d int dekadicky Pro long int se před formátovací písmeno přidá l, pro short int se přidá h, v C99 se pro long long int přidá ll, pro char se přidá hh, pro size_t potom z
o oktalově
x hexadecimálně
u unsigned int dekadicky Pro unsigned long int se před formátovací písmeno u přidá l, pro unsigned short int se přidá h
f float nebo double (C99 i long double) běžný tvar Pro double se před formátovací písmeno přidá l (jen pro scanf nebo v C99 i pro printf), v C99 se pro long double přidá L,
e mantisa e exponent
g podle hodnoty jako f nebo jako e
a nebo A (C99) hexadecimálně_mantisa P dvojkový_exponent
c char jako znak výpis ve tvaru čísla lze provést pomocí %d (v C99 %hhd)
s char * (tj. textový řetězec) proměnný počet znaků podle délky řetězce  

Mezi znak % a formátovací písmeno lze ještě vložit číslo udávající počet míst, resp. číslo.číslo, kde číslo za tečkou udává počet desetinných míst.

Analogicky se tvoří formátovací řetězce pro vstup, nemohou však obsahovat vložený text. Mezera mezi položkami označuje, že bílé znaky na tomto místě budou ignorovány.

Bližší podrobnosti (s mnoha dalšími formátovacími možnostmi): man 3s printf a man scanf

Rodina printf/scanf obsahuje ještě další málo používané funkce. Patří sem funkce, které mají na začátku přídáno písmeno v (např. vprintf, vfscanf apod.); fungují stejně, ale seznam čtených nebo tištěným položek je shrnut do jednoho parametru a z něj se "vytahují" makry va_... popsanými v 6. přednášce (odstavec "Funkce s proměnným počtem parametrů".

C99 má navíc i další funkce, zejména funkce pro čtení/zápis řetězců se "širokými" znaky (viz dále) a funkci snprintf (varianta sprintf s omezením rozsahu výstupu na max. zadaný počet znaků).

Znakový V/V - rodina get/put

Příkaz: Význam:
ch = getc(fp); Přečte 1 znak ze souboru; vrací int, ne char (aby mohl místo znaku vrátit EOF)
ch = getchar(); Přečte 1 znak ze standardního vstupu (klávesnice); také vrací int
ungetc(ch, fp); Vrátí znak ch do vstupního bufferu, takže následující vstupní funkce jej přečte znovu
putc(ch, fp); Zapíše 1 znak do souboru
putchar(ch); Zapíše 1 znak na standardní výstup (monitor)
gets(tx); Přečte ze standardního vstupu (klávesnice) řetězec až do konce řádku (včetně znaku \n)
fgets(tx, n, fp); Přečte ze souboru řetězec až do konce řádku (včetně znaku \n, nejvýše však n-1 znaků)
puts(tx); Zapíše řetězec do standardního výstupu (monitor) a přidá za něj znak "nový řádek"
fputs(tx, fp); Zapíše řetězec do souboru; znak "nový řádek" nepřidává (!)

Na rozdíl od použití formátového specifikátoru %s může čtený řetězec u těchto funkcí obsahovat i mezery a jiné bílé znaky.

Pozn.: getc a putc jsou makra, existují i jako funkce fgetc a fputc

Práce se "širokými znaky" (C99)

Sada podobných funkcí v <wchar.h>, do jejich názvu je přidáno w, např. fwprintf, fgetwc, putwchar.

Přímý vstup a výstup

Přesuny bloků paměti:

fread(kam, velikost_položky, počet_položek, fp)
fwrite(odkud, velikost_položky, počet_položek, fp)

Vrací počet přenesených položek. Přenáší se bez jakéhokoli formátování, tj. binárně.

Pomocné funkce

ferror(fp) vrací nenulu, došlo-li k chybě
feof(fp) vrací nenulu, když jsme se pokusili číst za konec souboru (rozdíl proti analogické funkci v Pascalu, která hlásí už dočtení souboru za poslední položku bez pokusu o čtení neexistujícího pokračování)
fflush(fp) provede výstup nashromážděný v bufferu. POZOR! použití fflush při vstupu pro přeskočení zbytku řádku sice některé překladače dovolují, ale norma  ANSI ani C99 nikoli

Bližší identifikace chyby se získá funkcí perror nebo jako extern int errno z <errno.h>

Další funkce: clearerr (výmaz příznaku chyby), ftell (zapamatování pozice v souboru), fseek (nastavení pozice v souboru), rewind (nastavení na začátek souboru)

Funkce pracující s pozicí v souboru nelze použít pro stdin, stdout, stderr, speciální soubory představující hardwarová zařízení (v Unixu v adresáří /dev) a pro soubory otevřené funkcí popen (bude popsána v jiné přednášce) 

V/V nad rámec normy

Není v žádné normě, ale většina překladačů umožňuje funkce nižší úrovně open creat close read write lseek (hlavičkové soubory <io.h>, <fcntl.h>). Nepoužívá strukturu FILE, ale "manipulační číslo souboru" (handle). Při zpracování velkých množství dat může být výrazně rychlejší.

Na PC bývá k dispozici <conio.h> pro práci s "konzolou" (terminálem). V Unixu podobnou funkci plní <curses.h> (viz jinou přednášku)


Předchozí Předchozí přednáška Další Další přednáška Hlavní stránka Hlavní stránka