PB161 Jazyk C++ - 4. cvičení
Nejčastější křestní jméno (použití kontejneru)
Jestliže nevidíte správně česká písmena, zvolte potřebné kódování češtiny manuálně.
Zadání:
Vytvořte program, který bude číst osobní data ve tvaru jméno
příjmení rodné_číslo a vyhodnotí, které mužské a které ženské křestní
jméno se v souboru vyskytovalo nejčastěji (a kolikrát to bylo). Pokud má maximální
četnost shodně více jmen, vypíše je program všechna.
Požadavky:
- Program nazvěte
krestni.
C
a po odladění uložte (pouze zdrojový tvar)
do adresáře /export/e1/pb161/
váš_login/cvic4
.
Odlaďte jej na počítači aisa.
- I v případě, že ve vstupním souboru budou pouze osoby téhož pohlaví, se musí
program chovat rozumně.
- Program provede závěrečné výpisy a skončí po dočtení vstupního souboru do konce (v Unixu při čtení z
klávesnice tento stav způsobíte klávesovou kombinací Ctrl D).
- Předpokládejte, že vstupní soubor může být velmi rozsáhlý. Akce,
které lze provádět až po dočtení souboru, proto nedělejte hned při
čtení záznamů, ale až na závěr nad tabulkou nalezených jmen (různých
jmen bude mnohem méně než osob na vstupu).
Poznámky:
- Vhodným nástrojem ke sledování četnosti jednotlivých jmen je kontejner
map<string,int>
. Jako klíč použijete křestní jméno, jako asociovanou
hodnotu počet výskytů. S výhodou tak využijete vlastnosti tohoto typu kontejneru, že
neexistující položka má asociovanou hodnotu 0.
- Je těžké algoritmizovat rozhodnutí, které jméno je mužské. Proto pro rozlišení
použijte rodné číslo, jehož 3. číslice je u mužů 0 nebo 1, u žen 5 nebo 6.
- Vřele doporučuji považovat rodné číslo za textový řetězec, a ne za celé
číslo - jinak nerozlišíte například RČ 0201024567 (nar. 2. ledna 2002 - č. 4567) a
201024567 (nar. 24. října 1920 - č. 567).
- Jaký index má 3. znak řetězce?
- Příjmení v programu vůbec nepoužijete, ale předpokládejte, že ve vstupním
souboru figuruje.
- Jako vstupní data můžete použít soubor
/home/jkucera/pb161/cvic4/krestni.data
,
na nějž přesměrujete standardní vstup.
- Pro konstrukci cyklu, v němž budete číst data, můžete s výhodou využít
následujícího faktu: vstupní operátor
>>
vrací
opět vstupní proud (levý operand) a ten se při použití na místě logického
výrazu (např. v podmínce) transformuje na true
. Při
pokusu o čtení více dat, než soubor obsahuje, však >>
vrátí
hodnotu, jež se transformuje na false
.
- Nutnost vyhodnocovat zvlášť mužská a zvlášť ženská jména představuje
určitou komplikaci. Nabízí se několik způsobů řešení:
- Vést separátně dva kontejnery - jeden pro mužská, jeden pro ženská jména.
- Ukládat vše do jednoho kontejneru a pohlaví jednotlivých jmen rozlišovat znaménkem
u četnosti, např. u mužů uvádět četnost jako kladné číslo, u žen jako
záporné. Tento přístup není použitelný, pokud určité křestní jméno mohou mít
muži i ženy, v češtině tato komplikace (doufám) nehrozí.
- Jako asociovanou hodnotu nepoužívat celé číslo, ale strukturu složenou z celého
čísla (četnost) a logické hodnoty (pohlaví).
Osobně považuji za nejjednodušší druhou variantu; ta je použita ve
vzorovém řešení.
- Pro závěrečné vyhledávání nejfrekventovanějších jmen doporučuji zkonstruovat
cyklus podle následujícího vzoru:
map<string,int>::const_iterator i;
for(i=tab.begin();i!=tab.end();i++)
{ ... }
Kontejner map
zajišťuje, že v těle cyklu je hodnota klíče
(aktuální jméno)
dostupná pod názvem i->first
a asociovaná hodnota (četnost) pod názvem
i->second
.
- Jako inspiraci si můžete spustit na aise vzorové řešení příkazem:
/home/jkucera/pb161/cvic4/krestni </home/jkucera/pb161/cvic4/krestni.data
Jeho zdrojový tvar má 39 řádků (1056 znaků), není
Vám však k dispozici.
- Autorem této úlohy je Ing. Jan Kučera