Práce se soubory (2017)
Zadání:
Vytiskněte statistiku výskytu bajtů (znaků) v souboru. Název zpracovávaného souboru je dán na příkazové řádce při spuštění programu. Tisk statistiky proveďte na konzolu ve formátu: první řádek obsahuje celkový počet bajtů/znaků (délka souboru); další řádky obsahují: hodnota bajtu/znaku dekadicky; hodnota bajtu/znaku hexa; vlastní znak (je-li „tištitelný“ - funce isxxx (isalpha, isnumber, is...)) jinak mezera, počet výskytů bajtu s touto hodnotou v souboru; procentní zastoupení v souboru. Ošetřete případ, kdy je soubor prázdný.
Tisk statistiky proveďte v pořadí podle hodnoty znaku a následně seřazený sestupně podle četnosti znaku. Pro setřídění použijte metodu, kdy se nebude třídit původní pole, ale (druhé) pole obsahující indexy (odkazy na původní pole).
Výstup programu by měl být v tomto tvaru:
14561
0;
0x0; ; 134; 1.2%
1; 0x1; ; 268; 2.4%
Pozn.: Ve cvičeních se snažte vyřešit co nejvíce, zbytek dodělejte za DU (příště budete potřebovat).
Doporučené řešení:
Vytvořte nový projekt – prázdnou konzolovou aplikaci
Vytvořte soubory projektu – main01.c (ve kterém bude
funkce main), funkce01.c (ve kterém budou funkce zpracovávající
soubor a provádějící tisk), funkce01.h (ošetřený hlavičkový soubor
umožňující volání funkcí ze souboru funkce.c)
Do pracovního
adresáře nakopírujte soubor pro vyhodnocení statistiky (v případě
spouštění z MSVC je to adresář kde jsou .c a .h soubory. V případě
spouštění .exe souboru je to adresář, ve kterém se vyskytuje tento
.exe soubor).
Předpřipravené testovací soubory.
Napište funkci main, vytiskněte parametry argc a zadané (naplněné, smysluplné) parametry argv (nezapomeňte načíst/includovat hlavičkový soubor pro funkci tisku printf)
V prostředí MSVC nastavte parametr argument na název načítaného souboru
Ve funkci main proveďte test přítomnosti parametru názvu souboru na příkazové řádce (tj. musí být přítomny dva parametry) – není-li druhý parametr přítomen, vytiskněte hlášení s popisem chybového stavu a program ukončete s návratovou hodnotou 1. Pro ukončení bez chyby použijte návratovou hodnotu 0.
Otevřete soubor, ošetřete chybové stavy
Pokuste se otevřít
soubor – pokud se soubor nepodaří otevřít (pro čtení, v
binárním módu), vypište chybový text a ukončete program s návratovou
hodnotu 2. Uvědomte si, že otevřené soubory je nutné zavřít v
případě, že už je nepotřebujeme. Na konci funkce main tedy soubor
zavřete. V případě, že se to nepodaří, vytiskněte popis chyby a
vraťte návratovou hodnotu 3.
V souboru funkce.c napište hlavičky/prototypu pro tři funkce
(tj. funkce se zatím prázdným tělem):
- statistika:
funkce bude mít jako parametr otevřený soubor a vrátí kód chyby
(pokud k chybě nedošlo vrátí hodnotu 0). Tato funkce vytvoří
statistiku souboru, vytiskne ji (pomocí funkce tisk), následně
zavolá funkci setrid, která setřídí prvky statistiky podle velikosti
(pole statistiky zůstane nezměněné, setřídí se jen pole indexů).
Následně funkce statistika tyto prvky opět vytiskne (pomocí stejné
stejné funkce tisk).
- tisk: funkce
bude mít jako parametr pole statistiky znaků (jakého datového typu
mohou být prvky tohoto pole bude-li obsahovat počty znaků?), a pole
s indexy, které budou určovat pořadí setříděných znaků (pro
neseřazené pole tedy bude pole indexů obsahovat 0,1,2...255; pro
setříděné například 45, 12, … což znamená, že se nejdříve
vytiskne znak s indexem 45, potom s indexem 12 …).
-
funkce setrid, která
dostane dva parametry. První bude pole statistiky, druhé bude pole
indexů. Tato funkce setřídí indexy tak, aby první index byl indexem
prvku s největší četností ve statistice, druhý prvek obsahoval index
druhého nejčastějšího (nebo stejně častého) prvku v souboru ...
K souboru funkce.c vytvořte hlavičkový soubor (funkce.h) – ošetřete ho proti vícenásobnému načtení. Pomocí tohoto souboru zveřejněte funkci statistika ze souboru funkce.c.
Z funkce main zavolejte funkci statistika, vyhodnoťte návratovou hodnotu – došlo-li k chybě vypište text chyby a vraťte návratovou hodnotu 4 (nezapomeňte, že máte pravděpodobně stále otevřený soubor!).
Jako vstup použijte textový soubor, ve funkci statistika načítejte znaky souboru a v rámci ověření správnosti načítání hodnoty, kopírujte na konzolu (monitor). Pro test konce souboru použijte funkce feof.
Při načítání znaků aktualizujte hodnoty v poli statistiky s názvem cetnost.
Napište funkci tisk pro tisk pole statistiky.
Napište funkci sestrid, která naplní pole indexů tak, aby indexy ukazovaly postupně na prvky od nejčetnějšího.
„Zrušte“ tisk/kopii znaků při načítání a vyzkoušejte správnou funkci programu i pro binární soubor. (například jiný .exe).
Uložte výsledky namísto tisku na konzolu do souboru. Název souboru bude dán jako další parametr na příkazovém řádku. V případě, že nebude přítomen, tiskněte výsledky na konzolu (uvědomte si, že konzola je také stream („otevřený soubor“) jako soubor – s názvem stdout, takže v tomto případě stačí předat místo otevřeného souboru parametr stdout). Nezapomeňte ošetřit chybové stavy spojené s otevřením a manipulací s dálším souboru. (Uvědomte si, že máte otevřeny dva soubory a že stdout se nezavírá).
Je možné zkusit formátovaný tisk pomocí streamů jazyka C++.
Vlastní streamy jsou definovány v knihovně <iostream>. Rozšiřující možnosti nastavení tisku jsou v knihovně <iomanip>.
Pro tisk na výstupní konzolu (monitor) se použije objekt cout v
následujícím tvaru:
cout << hodnota1 << hodnota2 <<
manipulátor1 << manipulátor 2 << hodnota 3 << …...
<< endl;
Jelikož je cout v prostoru std nebude předchozí fungovat. Je nutné
buď říci, že je v prostoru std a to :
std::cout při každém použití
std. Nebo je možné ho jedenkrát „vytáhnout“ z prostoru
std pomocí using std::cout;
Pro odřádkování a vynucení tisku je možné použít manipulátor endl, který se používá většinou jako poslední položka tisku. Opět se vyskytuje v prostoru std, takže je nutné ho zpřístupnit jednou z metod uvedených u std.
Pro formátovaný tisk je možné použít << std::setw(3) <<
pro nastavení šířky pole pro tisk. Následující tištěná proměnná bude
mít šířku minimálně tři znaky (a bude zarovnána napravo tohoto
pole).
Je možné stanovit i formát tisku. Hexadecimální tisk se
nastaví pomocí << std::hex <<. Dekadický tisk pomocí <<
std::dec <<. Pro čísla typu float je možné nastavit počet
platných míst a typ (například mantisa =fixed) <<
std::setprecision(2)<< std::fixed.
Některé modifikátory platí pouze pro následující tisk (např.
setw). Jiné jsou platné do dalšího přepnutí (dec, hex).
Pro variantní tisk je možné použít ternární operátor << (isxxxx(i) ? (char)i : ' ') << .
Poslední úpravy 2017-09-18