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í
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:
- vytvořit objekt třídy proudu ;
- asociovat objekt třídy se souborem, do kterého se má zapisovat;
- zapsat řádek do souboru;
- 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
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++.
- vytvořit objekt třídy ifstream a přiřadit jej k souboru, ze kterého se má číst;
- číst soubor;
- zavřete soubor.
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
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:
- počet bajtů přidělených pro datový typ
- 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
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.
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
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
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:
- adresa oblasti paměti, ze které jsou data zapisována nebo čtena,
- velikost jedné dané libovolného typu,
- množství čtených dat o zadané velikosti,
- 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
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
- 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.
- 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
Následující příklad prochází čtením řádků ze souboru test.txt a jejich zobrazením na konzole.
#zahrnout
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
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
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.