• Jak provést vstup ze souboru c. Práce s textovými soubory

    Většina počítačových programů pracuje se soubory, a proto je potřeba soubory vytvářet, mazat, zapisovat, číst, otevírat. Co je soubor? Soubor je pojmenovaná kolekce bajtů, která může být uložena na nějakém úložném zařízení. No, teď je jasné, že soubor je nějaká posloupnost bajtů, která má svůj vlastní jedinečný název, například soubor .txt. Soubory se stejným názvem nemohou být ve stejném adresáři. Název souboru je chápán nejen jako jeho název, ale také jako přípona, například: soubor.txt a soubor.dat různé soubory, i když mají stejný název. Existuje něco jako úplný název souborů - jedná se o úplnou adresu do adresáře souboru s názvem souboru, například: D:\docs\file.txt . Je důležité porozumět těmto základním pojmům, jinak bude obtížné pracovat se soubory.

    Chcete-li pracovat se soubory, musíte zahrnout soubor záhlaví . V několik definovaných tříd a hlavičkových souborů vstup do souboru a výstup souboru.

    File I/O je podobný standardnímu I/O, jediný rozdíl je v tom, že I/O se neprovádí na obrazovku, ale do souboru. Pokud je vstup/výstup na standardní zařízení prováděn pomocí objektů cin a cout, pak pro organizaci souborových I/O stačí vytvořit vlastní objekty, které lze použít podobně jako operátory cin a cout.

    Například je potřeba vytvořit textový soubor a do něj napsat řádek Práce se soubory v C++. Chcete-li to provést, musíte provést následující kroky:

    1. vytvořit objekt třídy proudu ;
    2. asociovat objekt třídy se souborem, do kterého se má zapisovat;
    3. zapsat řádek do souboru;
    4. zavřete soubor.

    Proč je nutné vytvořit objekt třídy ofstream a ne třídy ifstream? Protože potřebujete zapisovat do souboru a pokud byste potřebovali číst data ze souboru, pak by se vytvořil objekt třídy ifstream.

    // vytvořte objekt pro zápis do souboru ofstream /*jméno objektu*/; // objekt třídy proudu

    Nazvěme objekt - fout , Zde je to, co se stane:

    Ofstream fout;

    Proč potřebujeme předmět? Objekt musí být schopen zapisovat do souboru. Objekt již byl vytvořen, ale není přidružen k souboru, do kterého má být řetězec zapsán.

    fout.open("cppstudio.txt"); // asociovat objekt se souborem

    Prostřednictvím operace tečka získáme přístup k metodě třídy open(), v jejíž závorce uvedeme název souboru. Zadaný soubor bude vytvořen v aktuálním adresáři s programem. Pokud existuje soubor se stejným názvem, stávající soubor bude nahrazen novým. Soubor je tedy otevřený, zbývá do něj napsat požadovaný řádek. Dělá se to takto:

    Fout<< "Работа с файлами в С++"; // запись строки в файл

    Pomocí operace cast to stream ve spojení s objektem fout je řetězec File Handling v C++ zapsán do souboru. Protože již není nutné měnit obsah souboru, musí být uzavřen, to znamená, že objekt by měl být oddělen od souboru.

    fout.close(); // zavřete soubor

    V důsledku toho byl vytvořen soubor s řádkem Práce se soubory v C++.

    Kroky 1 a 2 lze kombinovat, to znamená v jednom řádku vytvořit objekt a přiřadit jej k souboru. Dělá se to takto:

    Ofstream fout("cppstudio.txt"); // vytvoří objekt třídy ofstream a přiřadí jej k souboru cppstudio.txt

    Zkombinujme celý kód a získáme následující program.

    // soubor.cpp: definuje vstupní bod pro konzolovou aplikaci. #include "stdafx.h" #include pomocí jmenného prostoru std; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // vytvořte objekt třídy ofstream pro zápis a přidružte jej k souboru cppstudio.txt fout<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

    Zbývá zkontrolovat správnou činnost programu, a proto soubor otevřeme cppstudio.txt a podívejte se na jeho obsah, mělo by to být - Práce se soubory v C++.

    1. vytvořit objekt třídy ifstream a přiřadit jej k souboru, ze kterého se má číst;
    2. číst soubor;
    3. zavřete soubor.
    // file_read.cpp: definuje vstupní bod pro konzolovou aplikaci. #include "stdafx.h" #include #zahrnout pomocí jmenného prostoru std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // správné zobrazení azbuky char buff; // mezipaměť pro ukládání textu načteného ze souboru ifstream fin("cppstudio.txt"); // otevření souboru pro čtení fin >><< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

    Program ukazuje dva způsoby čtení ze souboru, prvním je použití operace přenosu do streamu, druhým je použití funkce getline() . V prvním případě se přečte pouze první slovo a ve druhém případě se přečte řetězec 50 znaků. Ale protože v souboru zbývá méně než 50 znaků, znaky se přečtou až do posledního včetně. Všimněte si, že čtení podruhé (řádek 17) pokračoval po prvním slově, a ne od začátku, protože první slovo bylo přečtenořádek 14. Výsledek programu je na obrázku 1.

    Práce se soubory v C++ Pokračujte stisknutím libovolné klávesy. . .

    Obrázek 1 - Práce se soubory v C++

    Program fungoval správně, ale není tomu tak vždy, i když je vše v pořádku s kódem. Programu byl například předán název neexistujícího souboru nebo došlo k chybě v názvu. Co pak? V tomto případě se nestane vůbec nic. Soubor nebude nalezen, což znamená, že jej nelze přečíst. Proto bude kompilátor ignorovat řádky, kde je soubor zpracováván. V důsledku toho se program správně ukončí, ale na obrazovce se nic nezobrazí. Zdálo by se, že jde o zcela normální reakci na takovou situaci. Prostý uživatel však nepochopí, o co jde a proč se na obrazovce neobjevil řádek ze souboru. Aby bylo vše velmi jasné, C++ poskytuje takovou funkci - is_open() , která vrací celočíselné hodnoty: 1 - pokud byl soubor úspěšně otevřen, 0 - pokud soubor nebyl otevřen. Dokončíme program otevřením souboru tak, že pokud se soubor neotevře, zobrazí se odpovídající zpráva.

    // file_read.cpp: definuje vstupní bod pro konzolovou aplikaci. #include "stdafx.h" #include #zahrnout pomocí jmenného prostoru std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // správné zobrazení cyrilice char buff; // vyrovnávací paměť pro přechodné uložení textu načteného ze souboru ifstream fin("cppstudio.doc"); // (ZADÁN NESPRÁVNÝ NÁZEV SOUBORU) pokud (!fin.is_open())) // pokud soubor není otevřen<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> buff; // přečtení prvního slova ze souboru cout<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

    Výsledek programu je na obrázku 2.

    Soubor nelze otevřít! Pokračujte stiskem libovolné klávesy. . .

    Obrázek 2 - Práce se soubory v C++

    Jak můžete vidět na obrázku 2, program hlásil, že soubor nelze otevřít. Pokud tedy program pracuje se soubory, doporučuje se použít tuto funkci is_open() , i když jste si jisti, že soubor existuje.

    Režimy otevírání souborů

    Režimy otevírání souborů určují způsob použití souborů. Pro nastavení režimu poskytuje třída ios_base konstanty, které určují režim otevírání souboru (viz Tabulka 1).

    Režimy otevírání souborů lze nastavit přímo při vytváření objektu nebo při volání funkce open(). .

    Ofstream fout("cppstudio.txt", ios_base::app); // otevření souboru pro přidání informací na konec souboru fout. open("cppstudio.txt", ios_base::app); // otevřete soubor pro přidání informací na konec souboru

    Režimy otevření souboru lze kombinovat pomocí bitové booleovské operace nebo| , například: ios_base::out | ios_base::trunc - otevřete soubor pro zápis po jeho vymazání.

    Objekty třídy ofstream , jsou-li spojeny se soubory, standardně obsahují režimy otevírání souborů ios_base::out | ios_base::trunc . To znamená, že soubor bude vytvořen, pokud neexistuje. Pokud soubor existuje, jeho obsah bude smazán a samotný soubor bude připraven k nahrávání. Objekty třídy ifstream, jsou-li spojeny se souborem, mají ve výchozím nastavení režim otevírání souboru ios_base::in - soubor je otevřen pouze pro čtení. Režimu otevírání souborů se také říká příznak, kvůli čitelnosti budeme tento termín v budoucnu používat. Tabulka 1 neuvádí všechny příznaky, ale pro začátek by vám měly stačit.

    Vezměte prosím na vědomí, že příznaky ate a app jsou velmi podobné v popisu, oba přesouvají ukazatel na konec souboru, ale příznak aplikace umožňuje zápis pouze na konec souboru a příznak ate jednoduše přeuspořádá příznak na konec souboru a neomezuje prostor pro nahrávání.

    Pojďme vyvinout program, který pomocí operace sizeof() vypočítá charakteristiky hlavních datových typů v C++ a zapíše je do souboru. Vlastnosti:

    1. počet bajtů přidělených pro datový typ
    2. maximální hodnota, kterou může konkrétní datový typ uložit.

    Zápis do souboru musí být v následujícím formátu:

    /* datový typ byte max. hodnota bool = 1 255,00 char = 1 255,00 short int = 2 32767,00 unsigned short int = 2 65535,00 int = 4 2147483647,00 unsigned int = 4 670629,00 unsigned int = 4 670629,00 7,00 unsigned long int = 4 4294967295,00 float = 4 2147483647,00 long float = 8 9223372036854775800,00 double = 8 922337203685470758

    Takový program již byl vyvinut dříve v této části, ale tam byly všechny informace o datových typech vyvedeny na standardní výstupní zařízení a my musíme program předělat tak, aby se informace zapisovaly do souboru. Chcete-li to provést, musíte soubor otevřít v režimu zápisu s předběžným zkrácením informací o aktuálním souboru ( řádek 14). Jakmile je soubor vytvořen a úspěšně otevřen (řádky 16 - 20), místo příkazu cout v řádek 22 použijte objekt fout. tedy místo obrazovky budou informace o datových typech zapsány do souboru.

    // write_file.cpp: definuje vstupní bod pro konzolovou aplikaci. #include "stdafx.h" #include #zahrnout // práce se soubory #include // I/O manipulátory používající jmenný prostor std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // propojí objekt se souborem při otevírání souboru v režimu zápisu, přičemž nejprve z něj odstraní všechna data ofstream fout("data_types.txt", ios_base::out | ios_base::trunc); if (!fout.is_open the file has has not been open (!fout.is_open the file has has not been open)<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // záhlaví sloupců <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout << "Данные успешно записаны в файл data_types.txt\n"; system("pause"); return 0; }

    Není možné si nevšimnout, že změny v programu jsou minimální a to vše díky tomu, že standardní vstup/výstup a souborový vstup/výstup jsou využívány naprosto stejně. Na konci programuřádek 45soubor jsme výslovně uzavřeli, ačkoli to není vyžadováno, považuje se to za dobrou programátorskou praxi. Stojí za zmínku, že všechny funkce a manipulátory používané pro formátování standardního vstupu/výstupu jsou relevantní i pro vstup/výstup souboru. Při obsluze tedy nedošlo k žádným chybám cout byl nahrazen předmětem fout.

    Funkce fopen() otevře proud pro použití, přidruží soubor k danému proudu a poté vrátí ukazatel FILE na daný proud. Více často než ne, soubor je považován za soubor na disku. Funkce fopen() má následující prototyp:

    FILE *fopen(const char *název souboru, const char *režim);

    Kde režim ukazuje na řetězec obsahující požadovaný režim otevírání souboru. Platné hodnoty pro režim v Borland C++ jsou uvedeny v tabulce. název_souboru musí být znakový řetězec, který poskytuje platný název souboru pro operační systém a může obsahovat cestu.

    Funkce fopen() vrací ukazatel na základní typ FILE. Tento ukazatel identifikuje soubor a používá ho většina funkcí systému souborů. Nikdy by se to nemělo měnit sami. Pokud soubor nelze otevřít, funkce vrátí nulový ukazatel.

    Jak ukazuje tabulka, soubor lze otevřít v textovém nebo binárním režimu. V textovém režimu se při psaní sekvence návratu vozíku a posunu řádku převede na znak nového řádku. Ve výstupu je opak pravdou: znak nového řádku se převede na návrat vozíku a posun řádku. V binárních souborech takový překlad neexistuje. Pokud v argumentu mode není zadáno ani t ani b, je textový/binární stav souboru určen hodnotou globální proměnné _fmode definované v Borland C++. Ve výchozím nastavení je fmode nastaven na O_TEXT, to znamená, že je nastaven textový režim. Nastavení _fmode na O_BINARY otevře soubory v binárním režimu. (Tato makra jsou definována v fcntl.h.) Použití explicitního t nebo b přirozeně eliminuje účinky proměnné _fmode. Kromě toho je _fmode specifický pouze pro produkty Borland. V I/O systému ANSI C není definován.

    Pokud potřebujete otevřít soubor s názvem test pro zápis, měli byste napsat:

    Fp = fopen("test", "w") ;

    Kde fp je proměnná typu FILE *. Obvykle však uvidíte následující:

    If((fp = fopen("test", "w"))==NULL) (
    puts("Nelze otevřít soubor.");
    exit(1);
    }

    Tato metoda umožňuje odhalit chyby při otevírání souboru, například přítomnost ochrany proti zápisu nebo nedostatek volného místa na disku.

    Pokud se k otevření souboru pro zápis použije fopen(), bude odstraněn jakýkoli již existující soubor se zadaným názvem. Pokud soubor se zadaným názvem neexistuje, bude vytvořen.

    Pokud potřebujete přidat informace na konec souboru, měli byste použít režim a (přidat). Pokud soubor neexistuje, bude vytvořen.

    Otevření souboru pro čtení vyžaduje přítomnost souboru. Pokud soubor neexistuje, bude vrácena chyba. Pokud je soubor otevřen pro operaci čtení/zápisu, není odstraněn, pokud existuje, a pokud soubor neexistuje, je vytvořen.

    Tabulka: Hodnoty povoleného režimu

    Význam

    Otevře soubor ke čtení. (Ve výchozím nastavení se otevře jako textový soubor.)

    Vytvoří soubor pro zápis. (Ve výchozím nastavení se otevře jako textový soubor.)

    Připojí se k souboru. (Ve výchozím nastavení se otevře jako textový soubor.)

    Otevře binární soubor pro čtení.

    Otevře binární soubor pro zápis.

    Připojí se k binárnímu souboru.

    Otevře soubor pro čtení/zápis. (Ve výchozím nastavení se otevře jako textový soubor.)

    Vytvoří soubor pro čtení/zápis. (Ve výchozím nastavení se otevře jako textový soubor.)

    Připojí nebo vytvoří soubor pro čtení/zápis. (Ve výchozím nastavení se otevře jako textový soubor.)

    Otevře binární soubor pro čtení/zápis.

    Vytvoří binární soubor pro čtení/zápis.

    Připojí nebo vytvoří binární soubor pro čtení/zápis.

    Vytvoří textový soubor pro zápis.

    Připojí se k textovému souboru.

    Otevře textový soubor ke čtení.

    Vytvoří textový soubor pro čtení/zápis.

    Otevře nebo vytvoří textový soubor pro čtení/zápis.

    - srovnání k identifikaci rovnosti nebo nerovnosti.

    Praktickým účelem výčtu je definovat sadu odlišných symbolických konstant celočíselného typu.

    Příklad použití výčtových proměnných:

    mo=1, tu, my, čt, fr, sa, ne ) dny;

    puts(“ Zadejte den v týdnu (1 až 7) : “); scanf("%d", &t_den);

    w_day=su; start = mo;

    konec = w_day -t_day;

    printf(“\n pondělí je %d-tý den v týdnu, \ nyní je %d-tý den. \n\

    Do konce týdne %d dní (dnů). ”, začátek, t_den, konec);

    Výsledek programu: Zadejte den v týdnu (od 1 do 7): 2

    Pondělí je 1. den v týdnu, nyní 2. den. Do konce týdne 5 dní (dnů).

    18. Soubory v jazyce C

    Soubor je soubor dat umístěných na externím médiu a při zpracování je považován za celek. Soubory obsahují data určená k dlouhodobému uložení.

    Existují dva typy souborů: textové a binární. Textové soubory jsou posloupností znaků ASCII a lze je prohlížet a upravovat pomocí libovolného textového editoru.

    Binární (binární) soubory jsou sekvence dat, jejichž struktura je určena softwarem.

    Jazyk C má velkou sadu funkcí pro práci se soubory, z nichž většinu najdeme v knihovnách stdio.h a io.h.

    18.1. Otevření souboru

    Každému souboru je přiřazen interní logický název, který se použije později, když se na něj odkazuje. Logický název (ID souboru) je

    ukazatel souboru, tj. do oblasti paměti, která obsahuje všechny potřebné informace o souboru. Formát pro deklaraci ukazatele souboru je následující:

    FILE * ukazatel na soubor;

    FILE je identifikátor strukturálního typu, popsaný ve standardní knihovně

    stdio.h a obsahující následující informace:

    zadejte struct(

    – počet nepřečtených bytů zbývajících ve vyrovnávací paměti;

    obvyklá velikost vyrovnávací paměti je 512 bajtů; jakmile úroveň=0,

    další blok dat je načten do vyrovnávací paměti ze souboru;

    – příznak stavu souboru – čtení, zápis, přidávání;

    – deskriptor souboru, tzn. číslo, které jej definuje

    nepodepsané char hold;

    – nepřenesený charakter, tzn. ungetc-symbol;

    – velikost vnitřní mezilehlé vyrovnávací paměti;

    unsigned char buffer;

    je hodnota ukazatele, ke kterému se má přistupovat uvnitř vyrovnávací paměti, tzn.

    určuje začátek vyrovnávací paměti, začátek řádku nebo aktuální hodnotu

    hodnota ukazatele uvnitř vyrovnávací paměti v závislosti na režimu

    ma vyrovnávací paměť;

    unsigned char *curp;

    je aktuální hodnota ukazatele pro přístup do vyrovnávací paměti

    fera, tzn. nastavuje aktuální pozici ve vyrovnávací paměti

    pokračovat s programem;

    nepodepsaný istemp;

    – příznak dočasného souboru;

    – příznak při práci se souborem;

    ) SOUBOR;

    Než začnete se souborem pracovat, tzn. aby bylo možné číst nebo zapisovat informace do souboru, musí být otevřen pro přístup. To se obvykle provádí pomocí funkce

    SOUBOR* fopen(znak* název souboru, režim znak*);

    vezme si externí reprezentaci – fyzický název souboru na médiu (disketa, pevný disk) a přiřadí mu logické jméno.

    Fyzické jméno, tzn. jméno souboru a cesta k němu je dána prvním parametrem

    – řetězec, například „a:Mas_dat.dat“ je soubor s názvem Mas_dat.dat umístěný na disketě, „d:\\work\\Sved.txt“ je soubor s názvem Sved.txt umístěný na pevném disku v pracovním adresáři.

    Pozornost! Zpětné lomítko (\) jako speciální znak se zapisuje do řetězce dvakrát.

    Po úspěšném otevření funkce fopen vrací ukazatel na soubor (dále jen ukazatel na soubor). Při chybě je vrácena hodnota NULL. K této situaci obvykle dochází, když je nesprávně zadána cesta k otevíranému souboru. Pokud například zadáte cestu ve třídě zobrazení naší univerzity, kterou je zakázáno zapisovat (obvykle je povoleno d:\work\).

    Druhý parametr je řetězec, který určuje režim přístupu k souboru:

    w - soubor je otevřen pro zápis; pokud neexistuje žádný soubor s daným názvem, bude vytvořen; pokud takový soubor existuje, jsou předchozí informace před otevřením zničeny;

    r - soubor je otevřen pouze pro čtení; pokud takový soubor neexistuje, dojde k chybě;

    a - soubor je otevřen pro přidání nových informací na konec;

    r+ - soubor je otevřen pro editaci dat - je možný zápis i čtení informací;

    w+ je stejné jako pro r+;

    a+ - stejné jako u a, kdekoli v souboru lze provádět pouze zápis; k dispozici je také čtení souborů;

    t - soubor je otevřen v textovém režimu, b - soubor je otevřen v binárním režimu.

    Textový režim se od binárního liší tím, že při otevření souboru jako textové dvojice znaků "line feed" je "carriage return" nahrazen jedním znakem: "line feed" pro všechny funkce zápisu dat do souboru a pro všechny výstupní funkce je nyní znak "line feed" nahrazen dvěma znaky: "line feed", "carriage return".

    Ve výchozím nastavení se soubor otevře v textovém režimu. Příklad: FILE *f; – je deklarován ukazatel na soubor f;

    f = fopen("d:\\práce\\Dat_sp.cpp", "w"); – otevře se pro zápis souboru s logickým názvem f, který má fyzické jméno Dat_sp.cpp, umístěný na disku d, v adresáři work; nebo stručněji

    SOUBOR *f = fopen("d:\\práce\\Dat_sp.cpp", "w");

    18.2. Zavření souboru

    Po práci se souborem musí být přístup k němu uzavřen. To se provádí funkcí int fclose (ukazatel na soubor). Například z předchozího příkladu je soubor uzavřen takto: fclose (f);

    Pro uzavření více souborů byla zavedena funkce deklarovaná následovně: void fcloseall(void );

    Pokud chcete změnit režim přístupu k souboru, musíte soubor nejprve zavřít a poté znovu otevřít, ale s jinými přístupovými právy. Chcete-li to provést, použijte standardní funkci:

    FILE* freeopen (char*název souboru , char *režim , FILE *ukazatel souboru );

    Tato funkce nejprve zavře deklarovaný soubor ukazatel souboru(jako funkce fopen) a poté otevře soubor s oprávněními k souboru a "režimu".

    Jazyk C má schopnost pracovat s dočasnými soubory, které jsou potřeba pouze během činnosti programu. V tomto případě se použije funkce

    FILE*tmpfile(void);

    který vytvoří na disku dočasný soubor s oprávněním „w+b“, po ukončení programu nebo po zavření dočasného souboru se automaticky smaže.

    18.3. Psaní – čtení informací

    Všechny akce pro čtení a zápis dat do souboru lze rozdělit do tří skupin: vstupně-výstupní operace znak po znaku; operace linkového vstupu/výstupu; blokovat I/O operace.

    Zvažte hlavní funkce používané v každé z těchto tří skupin operací.

    Znakový vstup/výstup

    Znakové I/O funkce přijímají jeden znak ze souboru nebo přenášejí jeden znak do souboru:

    Řádek I/O

    Linkové I/O funkce se přenášejí ze souboru nebo do

    Blokovat I/O

    Blokové I/O funkce fungují na celých blocích

    informace:

    int fread (void*p, intsize,

    - přečte n bloků velikosti bajtů každého ze souborů

    int n, SOUBOR *f)

    la f do oblasti paměti pomocí ukazatele p (potřeba

    int fwrite(void*p, intsize,

    předem alokovat paměť pro čtený blok);

    – zapíše n bloků velikosti bajtů každého z

    int n, SOUBOR *f)

    paměťové místo s ukazatelem p na soubor f.

    Formátovaný I/O je vytvářen funkcemi.

    Předtím jsme při zadávání a výstupu dat pracovali se standardními streamy – klávesnicí a monitorem. Nyní se podívejme, jak jazyk C implementuje získávání dat ze souborů a jejich zápis tam. Před provedením těchto operací musí být soubor otevřen a zpřístupněn.

    V programovacím jazyce C je ukazatel na soubor typu FILE a jeho deklarace vypadá takto:
    SOUBOR *mujsoubor;

    Na druhou stranu funkce fopen() otevře soubor na adrese zadané jako první argument v režimu čtení ("r"), zápisu ("w") nebo připojení ("a") a vrátí programu ukazatel na něj. Proto proces otevření souboru a jeho připojení k programu vypadá asi takto:
    myfile = fopen("ahoj.txt", "r");

    Při čtení nebo zápisu dat do souboru se k nim přistupuje pomocí ukazatele na soubor (v tomto případě myfile).

    Pokud z nějakého důvodu (na zadané adrese není žádný soubor, přístup k němu je odepřen) funkce fopen() nemůže soubor otevřít, vrátí hodnotu NULL. Ve skutečných programech je chyba při otevření souboru téměř vždy řešena ve větvi if, ale to dále vynecháme.

    Deklarace funkce fopen() je obsažena v hlavičkovém souboru stdio.h, takže je vyžadováno její zahrnutí. Typ struktury FILE je také deklarován v stdio.h.

    Po ukončení práce se souborem je zvykem jej zavřít, aby se uvolnil buffer od dat a z jiných důvodů. To je důležité zejména v případě, že program běží i po práci se souborem. Přerušení spojení mezi externím souborem a ukazatelem na něj z programu se provádí pomocí funkce fclose(). Jako parametr bere ukazatel souboru:
    fclose(myfile);

    V programu lze otevřít více než jeden soubor. V takovém případě musí být každý soubor spojen s vlastním ukazatelem souboru. Pokud však program nejprve pracuje s jedním souborem a poté jej zavře, lze ukazatel použít k otevření druhého souboru.

    Čtení a zápis do textového souboru

    fscanf()

    Funkce fscanf() je svým významem podobná funkci scanf(), ale na rozdíl od ní přebírá formátovaný vstup ze souboru spíše než standardní vstup. Funkce fscanf() přebírá parametry: ukazatel souboru, formátovací řetězec, adresy oblastí paměti pro zápis dat:
    fscanf(myfile, "%s%d", str, &a);

    Vrátí počet úspěšně přečtených dat neboli EOF. Mezery, znaky nového řádku se berou v úvahu jako oddělovače dat.

    Řekněme, že máme soubor obsahující následující popis objektů:

    Jablka 10 23,4 banány 5 25,0 chleba 1 10,3

    #zahrnout main () ( FILE * soubor; struct food ( char name[ 20 ] ; unsigned qty; float price; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ("fscanf.txt" , "r" ) ; while (fscanf (file, &q, "%s shop[i%].] name) , & (obchod[ i] .cena) ) != EOF) ( printf ("%s %u %.2f \n", obchod[ i] .název , obchod[ i] .množství , obchod[ i] .cena ); i++; ))

    V tomto případě je deklarována struktura a pole struktur. Každý řádek ze souboru odpovídá jednomu prvku pole; prvek pole je struktura obsahující řetězec a dvě číselná pole. Cyklus čte jeden řádek na iteraci. Když je zjištěn konec souboru, fscanf() vrátí EOF a smyčka se ukončí.

    fgets()

    Funkce fgets() je podobná funkci gets() a provádí vstup ze souboru řádek po řádku. Jedno volání funkce fgets() přečte jeden řádek. V tomto případě nemůžete přečíst celý řádek, ale pouze jeho část od začátku. Možnosti fgets() vypadají takto:
    fgets (array_of_characters, number_of_characters_to_read, pointer_to_file)

    Například:
    fgets(str, 50, můjsoubor)

    Takové volání funkce přečte ze souboru spojeného s ukazatelem myfile celý jeden řádek textu, pokud je jeho délka menší než 50 znaků, včetně znaku "\n", který funkce také uloží do pole. Posledním (50.) prvkem pole str bude znak "\0" přidaný funkcí fgets() . Pokud je řetězec delší, funkce přečte 49 znaků a na konci zapíše "\0". V tomto případě nebude "\n" obsaženo v čteném řádku.

    #zahrnout #define N 80 main () ( FILE * soubor; char arr[ N] ; soubor = fopen ("fscanf.txt" , "r" ) ; while (fgets (arr, N, soubor) != NULL) printf ("%s" , arr) ; printf (" \n"); fclose(soubor); )

    V tomto programu se na rozdíl od předchozího načítají data řádek po řádku do pole arr. Když je přečten další řádek, předchozí je ztracen. Funkce fgets() vrátí NULL, pokud nemůže přečíst další řádek.

    getc() nebo fgetc()

    Funkce getc() nebo fgetc() (obě fungují) vám umožňuje získat další znak ze souboru.

    while ((arr[ i] = fgetc (soubor) ) != EOF) ( if (arr[ i] == " \n") ( arr[i] = " \0 " ; printf("%s \n", arr); i = 0 ) jinak i++; ) arr[i] = " \0 " ; printf("%s \n", arr);

    Kód uvedený jako příklad vytiskne data ze souboru na obrazovku.

    Zápis do textového souboru

    Stejně jako vstup může být výstup do souboru jiný.

    • Formátovaný výstup. Funkce fprintf (ukazatel_souboru, řetězec_formátu, proměnné) .
    • Výstup příspěvku. Funkce fputs(řetězec, filepointer) .
    • Symbolický výstup. fputc() nebo putc(znak, filepointer) .

    Níže jsou uvedeny příklady kódu, které používají tři způsoby výstupu dat do souboru.

    Zápis do každého řádku souboru pole jedné struktury:

    soubor = fopen("fprintf.txt" , "w" ) ; while (scanf ("%s%u%f" , shop[ i] .name , & (shop[ i] .qty ) , & (shop[ i] .price ) ) != EOF) ( fprintf (soubor, "%s %u %.2f \n", obchod[ i] .název , obchod[ i] .množství , obchod[ i] .cena ); i++; )

    Řádek po řádku výstup do souboru (fputs() , na rozdíl od samotného puts() nevkládá "\n" na konec řádku):

    while (získá (arr) != NULL) ( fputs (arr, soubor) ; fputs (" \n",soubor); )

    Příklad výstupu znak po znaku:

    while ((i = getchar () ) != EOF) putc (i, soubor) ;

    Čtení a zápis do binárního souboru

    Se souborem můžete pracovat nikoli jako s posloupností znaků, ale jako s posloupností bajtů. V zásadě není možné pracovat s netextovými soubory jiným způsobem. Tímto způsobem však můžete také číst a zapisovat do textových souborů. Výhoda tohoto způsobu přístupu k souboru spočívá v rychlosti čtení a zápisu: při jednom přístupu lze přečíst/zapsat významný blok informací.

    Při otevírání souboru pro binární přístup je druhým argumentem pro fopen() řetězec "rb" nebo "wb".

    Téma práce s binárními soubory je poměrně složité, vyžaduje si samostatnou lekci. Zde budou uvedeny pouze vlastnosti funkcí čtení a zápisu do souboru, který je považován za proud bajtů.

    Funkce fread() a fwrite() berou jako parametry:

    1. adresa oblasti paměti, ze které jsou data zapisována nebo čtena,
    2. velikost jedné dané libovolného typu,
    3. množství čtených dat o zadané velikosti,
    4. ukazatel souboru.

    Tyto funkce vracejí počet úspěšně přečtených nebo zapsaných dat. Tito. můžete si "objednat" čtení 50 datových prvků a dostanete pouze 10. Nedojde k žádné chybě.

    Příklad použití funkcí fread() a fwrite():

    #zahrnout #zahrnout main () ( FILE * soubor; char police1[ 50 ] , police2[ 100 ] ; int n, m; soubor = fopen ("shelf1.txt" , "rb" ) ; n= fread (police1, sizeof (char ) , 50 , soubor) ; fclose (filerblf.txt)";) soubor (filerblf.txt";)" fread (police2, sizeof (char) , 50 , soubor) ; fclose (soubor) ; police1[ n] = " \0 " ; police2[m] = " \n"; police2[ m+ 1 ] = " \0 " ; soubor = fopen("obchod.txt" , "wb" ) ; fwrite (strcat (police2, police1) , sizeof (char ) , n+ m, soubor) ; fclose(soubor); )

    Zde je proveden pokus o načtení 50 znaků z prvního souboru. n ukládá počet skutečně přečtených znaků. Hodnota n může být 50 nebo menší. Data jsou umístěna v řetězci. Totéž se stane s druhým souborem. Dále je první řádek připojen k druhému a data jsou uložena do třetího souboru.

    Řešení problému

    1. Napište program, který vyzve uživatele k zadání názvu (adresy) textového souboru, poté jej otevře a spočítá počet znaků a řádků v něm.
    2. Napište program, který zapíše do souboru data přijatá z jiného souboru a před zápisem upravená tak či onak. Každý řádek dat přijatých ze souboru musí být umístěn ve struktuře.

    Mechanismus I/O vyvinutý společností , neodpovídá dnes obecně přijímanému stylu objektově orientovaného programování, navíc aktivně využívá ukazatelové operace, které jsou v moderních prostředích spouštění zabezpečeného kódu považovány za potenciálně nebezpečné. Alternativou pro vývoj aplikací je standardní mechanismus I/O tříd poskytovaný standardem jazyka C++.

    Otevírání souborů

    Nejčastěji používané třídy jsou ifstream pro čtení, ofstream pro zápis a fstream pro úpravu souborů.

    Všechny třídy I/O s vlákny jsou nepřímo odvozeny od společného předka ios a plně zdědí jeho funkčnost. Například výčtový datový člen open_mode určuje režim otevření souboru, který je definován následovně:

    Enum open_mode ( app, binary, in, out, trunc, ate );

    Níže jsou uvedeny možné hodnoty příznaků a jejich účel.

    Chcete-li například otevřít soubor s názvem test.txt pro čtení binárních dat, napište:

    ifstream soubor; file.open("test.txt", ios::in | ios::binary);

    Logický operátor OR (|) vám umožňuje sestavit režim s libovolnou kombinací příznaků. Abyste při otevírání souboru zápisem omylem nepřepsali existující soubor se stejným názvem, musíte použít následující formulář:

    offstream soubor; file.open("test.txt", ios::out | ios::app);

    Předpokládá se, že k projektu je připojen příslušný hlavičkový soubor:

    #zahrnout

    Chcete-li zkontrolovat, zda byl soubor úspěšně otevřen, můžete použít konstrukci

    If (!file) ( // Zpracování chyby při otevření souboru )

    Operátoři inkluze a těžby

    Přepsáno ve třídách zpracování souborů zahrnovat operátora (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

    soubor<< "Это строка текста";

    Textový řetězec můžete také napsat po částech:

    soubor<< "Это " << "строка " << "текста";

    Příkaz endl ukončí vstup řádku návratem vozíku:

    soubor<< "Это строка текста" << endl;

    Pomocí operátoru include je snadné zapsat hodnoty proměnných nebo prvků pole do souboru:

    Ofstream soubor("Temp.txt"); char buff = "Textové pole obsahuje proměnné"; int vx = 100; plovák pi = 3,14159; soubor<< buff << endl << vx << endl << pi << endl;

    V důsledku spuštění kódu se vygenerují tři řádky textového souboru Temp.txt:

    Textové pole obsahuje proměnné 100 3,14159

    Všimněte si, že číselné hodnoty se do souboru zapisují jako textové řetězce, nikoli binární hodnoty.

    operátor extraktu(>>) dělá opak. Zdá se, že k extrahování znaků ze souboru Temp.txt napsaného dříve, musíte napsat kód jako následující:

    ifstream soubor("Temp.txt"); char buff; intvx; floatpi; soubor >> buff >> vx >> pi;

    Operátor extrakce se však zastaví u prvního oddělovače (mezera, tabulátor nebo nový řádek), na který narazí. Při analýze věty „Textové pole obsahuje proměnné“ se tedy do pole buff zapíše pouze slovo „Text“, mezera se ignoruje a slovo „pole“ se stane hodnotou celočíselné proměnné vx a spuštění kódu se „zničí“ s nevyhnutelným porušením datové struktury. Dále si při probírání třídy ifstream ukážeme, jak správně organizovat čtení souboru z předchozího příkladu.

    ifstream třída: čtení souborů

    Jak název napovídá, třída ifstream je navržena pro vstup datového proudu souboru. Hlavní metody třídy jsou uvedeny níže. Většina z nich je zděděna z třídy istream a přetížena rodičovskou funkcí. Například funkce get je v závislosti na parametru volání schopna číst nejen jeden znak, ale i blok znaků.

    Nyní je jasné, jak je třeba upravit předchozí příklad, aby použití operátoru extrakce dat poskytlo očekávaný výsledek:

    ifstream soubor("Temp.txt"); char buff; intvx; floatpi; file.getline(buff, sizeof(buff)); soubor >> vx >> pi:

    Metoda getline přečte první řádek souboru až do konce a operátor >> přiřadí hodnoty proměnným.

    Následující příklad ukazuje přidání dat do textového souboru a následné čtení celého souboru. Smyčka while (1) se používá místo while(!file2.eof()) z důvodů uvedených v .

    #zahrnout #zahrnout pomocí jmenného prostoru std; int main() ( soubor ofstream; file.open("test.txt",ios::out|ios::app); if (!soubor) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >>a; if (file2.eof()) break; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

    Následující příklad prochází čtením řádků ze souboru test.txt a jejich zobrazením na konzole.

    #zahrnout #zahrnout pomocí jmenného prostoru std; int main() ( soubor ifstream; // vytvoření souboru objektu streamu file.open("test.txt"); // otevření souboru pro čtení if (!soubor) return 1; // návrat při chybě otevření char str; // vyrovnávací paměť statického řádku // Čtení a zobrazování řádků ve smyčce až do eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

    Tento kód pod OS Windows také závisí na přítomnosti znaku nového řádku v posledním řádku souboru, bylo by spolehlivější to udělat:

    While (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

    Explicitní volání metod open a close jsou volitelné. Volání konstruktoru s argumentem vám skutečně umožní otevřít soubor okamžitě, v okamžiku vytvoření objektu streamu souboru:

    ifstream soubor("test.txt");

    Místo metody close můžete použít operátor delete, který automaticky zavolá destruktor objektu souboru a zavře soubor. Kód smyčky while poskytuje správnou kontrolu konce souboru.

    ofstream class: zápis souborů

    Třída ofstream je navržena pro výstup dat z datového proudu souborů. Hlavní metody této třídy jsou uvedeny níže.

    Operátor include popsaný výše je vhodný pro organizaci zápisu do textového souboru:

    Ofstream soubor("temp.txt"); if (!soubor) return; pro (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

    Binární soubory

    V zásadě se binární data obsluhují jako textová data. Rozdíl je v tom, že pokud jsou binární data zapsána v určité logické struktuře, musí být načtena ze souboru do proměnné stejného typu struktury.

    První parametr metod zápisu a čtení (adresa bloku zápisu/čtení) musí být typu znakového ukazatele char * , je tedy nutné explicitně převést typ adresy struktury void *. Druhý parametr určuje, že binární bloky souboru mají konstantní velikost bajtů bez ohledu na skutečnou délku záznamu. Následující příloha uvádí příklad, jak vytvořit a zobrazit data v jednoduchém poznámkovém bloku. Záznamy souboru jsou pak postupně čteny a zobrazeny na konzole.

    #zahrnout #zahrnout #zahrnout pomocí jmenného prostoru std; struct Poznámky ( // datová struktura zápisníku char Name; // celé jméno char Phone; // phone int Age; // age ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1= ( "Ioann Vasilievich Hrozný", "nenainstalováno", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233 ", 30 ); Notes Note3= ( "32Romanov",3,211 Petr); "02111 Petr ofstream ofile("Not ebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof(Notes)); // 1. blok ofile.write((char*)&Note2, sizeof(Notes)); // 2. blok zapsaný ofile.write((char*)&Note3, ifte/ifte. book.dat", ios: :binary); Notes Note; // strukturovaná proměnná char str; // vyrovnávací paměť statického řetězce // Čtení a zobrazování řádků ve smyčce až do eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tBody: %s\tNotePho: %s\tAgeNage: %s\tAge; cout,.Age); cout,.<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

    V důsledku provedení tohoto kódu se vytvoří binární soubor Notebook.dat ze tří bloků po 80 bajtech (za předpokladu, že znaky jsou jednobajtové). Samozřejmě můžete použít jiné metody streamování a provádět libovolné operace na polích konkrétní datové struktury.

    třída fstream: náhodný přístup k souboru

    Předpokládejme, že náš zápisník nashromáždil 100 záznamů a my chceme počítat 50. Samozřejmě můžete uspořádat smyčku a přečíst všechny záznamy od prvního po daný. Je zřejmé, že cílenějším řešením je nastavit ukazatel polohy souboru pos přímo na položku 50 a přečíst ji:

    ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Notes); ifile hledat (pos); // hledání 50. položky Poznámky Poznámka; //Poznámky - struktura "záznam" popsaná výše ifile.read((char*)&Note, sizeof(Notes));

    Takové vyhledávací operace jsou účinné, pokud soubor obsahuje záznamy o známé a konstantní velikosti. Chcete-li nahradit obsah libovolné položky, musíte otevřít výstupní proud v režimu úprav:

    Ofstream ofile("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile seekp(pos); // hledání 50. noty Notes Note50 = ("Jelcin Boris Nikolajevič", "095-222-3322", 64); ofile.write((char*)&Poznámka, velikost(Poznámky)); // výměna, nahrazení

    Pokud nezadáte příznak ios::ate (nebo ios::app), pak při otevření binárního souboru Notebook.dat bude jeho předchozí obsah vymazán!

    Konečně je možné otevřít soubor současně pro čtení/zápis pomocí metod zděděných streamovací třídou fstream od svých předchůdců. Vzhledem k tomu, že třída fstream je odvozena od istream a ostream (rodiče ifstream a ofstream), jsou pro aplikaci dostupné všechny výše uvedené metody.

    Následující příklad zamění první a třetí položku v souboru Notebook.dat.

    #zahrnout #zahrnout #zahrnout pomocí jmenného prostoru std; struct Poznámky ( char Jméno; char Telefon; int Věk; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Otevřít soubor pro současné čtení/zápis fstream file("Notebook.dat", ios::binary | ios::in | ios::out); file.seekg(2 * sizeof(Notes)); // najít a přečíst Note3*) velikost souboru., viz. read Note 1 file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Note1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

    Příznaky ios::in a ios::out musí být specifikovány v konstruktoru objektu souboru, aby bylo možné provádět souběžné operace čtení a zápisu. V důsledku provedení tohoto kódu dojde k záměně prvního a třetího záznamu binárního souboru Notebook.dat.

    K tématu jsou další příklady.