BPC1E – počítačové cvičení 9
Struktury a dynamické proměnné Cílem cvičení je sestavit aplikaci, která bude používat vhodnou strukturu popisující daný objekt požadovanými parametry. Navazujícím cílem je deklarovat tuto strukturu jako dynamickou proměnnou a procvičit si práci s dynamickými proměnnými v jazyku C. Úloha A. Cílem tohoto příkladu je sestavit projekt pro jednoduchou správu autobazaru. Projekt k příkladu A se skládá ze zdrojového souboru BPC1E_C09A.c, kde se nachází funkce main(): #include <stdio.h> #include
int main(void) { T_car *bazar[200]; int cnt=0; int lprice, hprice; char cmd;
// ptrs. to cars // number of recorded cars
cnt = ini_bazar(bazar, cnt); printf("\n\nInsert command: 'q' = quit … "); scanf("%c", &cmd); fflush(stdin); while(cmd!='q') // if not quit { switch (cmd) { case 'p': print_bazar(bazar, cnt); break; //case 'a': call function for adding a new car case 's': { printf("\nSelect low limit of price:"); scanf("%d", &lprice); fflush(stdin); printf("\nSelect high limit of price:"); scanf("%d", &hprice); fflush(stdin); } } printf("\n\nInsert command: 'q' = quit, … "); scanf("%c", &cmd); fflush(stdin); }; // call function for deleting of all recods return 0; }
a knihovny pro funkce spojené se správou autobazaru s hlavičkovým souborem bazar.h: typedef { char char char
struct car
// car record
type[20]; // type of car color[10]; // color of car mot; // kind of the motor B = benzin, D = diesel
int vol; int year; int price; }T_car;
// motor volume in cubic cm // year of production // price
int ini_bazar(T_car **rec, int num); // bazar initialization void print_record(T_car *prcar); // printing car parameters void print_bazar(T_car **rec, int num); // printing all cars // insert function header for deleting of all records (cars) // insert function header for printing of bazar content with // defined range of price // insert function header for adding of new car
a zdrojovým souborem bazar.c: #include int ini_bazar(T_car **rec, int num) { T_car *new_car; new_car=(T_car*)malloc(sizeof(T_car)); strcpy(new_car->type, "Skoda_Felicia"); strcpy(new_car->color, "Blue"); new_car->mot='D'; new_car->vol=1400; new_car->year=2003; new_car->price=75000; rec[num++] = new_car; // and other cars return num; } void print_record(T_car *prcar) { printf("\n%s\t %s", prcar->type, prcar->color); if(prcar->mot=='D') printf("\t diesel"); else if(prcar->mot=='B') printf("\t beznin"); printf("\t %4d ccm\t year %d\t price %6d CZK", prcar->vol, prcar->year, prcar->price); } void print_bazar(T_car **rec, int num) { int n; for(n=0; n
Vložte předpřipravené kódy do vašeho projektu. V hlavičkovém souboru je uvedena kompletní definice vlastního typu struktury T_car, položky jsou popsány v poznámkách. Ve vlastní knihovně „bazar“ máte rovněž připraveny kompletní a plně funkční funkce pro
inicializaci databáze autobazaru ini_bazar(…), která naplní pole záznamů několika vozy tak, abyste nemuseli při každém spuštění plnit databázi ručně. Dále pak obsahuje funkci pro tisk položek jednoho záznamu do jednoho řádku print_record(…), vstupním parametrem je ukazatel na záznam, který má být tisknut. Poslední připravenou funkcí je print_bazar(…) pro tisk všech záznamů (aut) v autobazaru. Ve funkci main() je inicializováno pole ukazatelů na záznam *bazar[200], tedy na 200 záznamů. Do tohoto pole se vkládají ukazatele (adresy) na jednotlivé záznamy, způsob je zřejmý z funkce ini_bazar(…). Důležitá je rovněž proměnná cnt, ve které je uložen počet naplněných záznamů. Všimněte si, že například ve funkci print_bazar(…) je parametrem ukazatel na ukazatel, protože potřebuji znát ukazatel na pole, musím to provést tímto způsobem. Vašim úkolem je doplnit program o funkce pro přidání nového záznamu auta, výpis aut v bazaru pro zadaný rozsah cen a funkci, která před ukončením programu vymaže všechny dynamický vytvořené záznamy. Ve funkci main() je již vytvořeno jednoduché ovládací prostředí pomocí zadávání příkazů z klávesnice. Ukázka činnosti programu je na obrázku 9.1.
Obr. 9.1. Příklad zobrazení výsledků příkladu A) v konzolovém okně. Hodnocení: 3 body.
Bonusová úloha Vytvořte program, který v konzolovém okně umožní hodnocení dvoukolového mezinárodního závodu ve skocích na lyžích. Vytvořte vlastní datový typ struktury (nebo využijte přiložený zdrojový kód), který bude obsahovat jméno závodníka, třímístný kód země, celkové dosažené body a aktuální pořadí a dvě vnitřní struktury s hodnocením jednotlivých skoků v prvním a druhém kole (délka skoku + bodové hodnocení 5 rozhodčích). Bodování je zřejmé z následujících pravidel: Hodnocení se vytváří na základě součtu dvou údajů: bodů za délku skoku a za stylové provedení: a) body za délku skoku: každý závodník obdrží automaticky 60 bodů (výjimkou jsou mamutí můstky - K170 a více, u nichž se uděluje 120 bodů). V závislosti na dosažení tzv. konstrukčního bodu můstku (např. 120 metrů u můstků K120) získává (nebo ztrácí) další body. Za každý metr navíc/méně získá/ztrácí určité množství bodů závislé na typu můstku: K60 - K69: K70 - K79: K80 - K99: K100 - K169: K170 a více:
2,4 bodu za metr 2,2 bodu za metr 2,0 bodu za metr 1,8 bodu za metr 1,2 bodu za metr
(velikost můstku je proměnná zadaná na začátku po spuštění programu) b) body za stylové hodnocení: Každý z pěti porotců udělí skokanovi známku do 20 bodů s rozlišením po 0,5 bodech. Nejvyšší a nejnižší hodnota ze všech pěti známek se škrtá. Platné jsou tedy pouze tři známky a maximální zisk je 60 bodů. Stylové chyby skokana musí porotce promítnout do svého hodnocení. Jednotlivé záznamy budou generovány jako dynamické proměnné, na které bude nastaven ukazatel v poli ukazatelů na jednotlivé záznamy s počtem maximálně 30. Počet záznamů udržujte ve vhodné globální proměnné. Sestavte funkce pro vložení závodníka a dále funkce pro hodnocení skoku a výpis výsledků. Pro jednoduchost v prvním i druhém kole startují závodníci podle pořadí, ve kterém byly jejich záznamy dynamicky přidány. Po každém skoku bude vypsáno aktuální pořadí a na žádost i tabulka výsledků (pořadí od nejlepšího k nejhoršímu). Na závěr každého kola bude tabulka výsledků vypsána automaticky. V maximální míře využívejte funkce. Příklad výpisů konzolového okna je uveden na obrázku 9.2. Kritickou částí je generování aktuálního pořadí. Doporučuji vytvořit funkci, kterou zavoláte po každém skoku a v níž se vyhodnotí pořadí podle bodů. Tak stačí porovnat jen aktuální záznam s předešlými výsledky a vhodným způsobem jej zařadit. Příklad řešení struktury je v přiloženém zdrojovém kódu BPC1E_C09BON.c.
Obr. 9.2. Příklad výstupů v konzolovém okně pro bonusový úkol včetně finálního vyhodnocení. typedef struct jump { float length; float points[5]; } t_jump;
// structure for jump and evaluation
typedef struct competitor { char name[20]; char country[4];
// structure for competitor
// length of jump in meters // evaluation by refs
// name // three-letter code of country
float points; int order; t_jump round_1; t_jump round_2; }t_competitor; t_competitor int cnt=0;
*comp[30];
// sum of points // order // jump and eval. in the 1st round // jump and eval. in the 2nd round
// global array of pointers to comp. records // global number of records
Kontrolní otázky 9.1)
Jak velký prostor bude v paměti vyhrazený v případě deklarace proměnné typu T_car z příkladu A?
9.2)
Co deklaruje následující konstrukce: int **x?
9.3)
Jak se projeví při tisku znak \t v řetězci funkce printf()?
Literatura [9.1]
KERNIGHAN, B. W., RITCHIE, D. M. Programovací jazyk C. Brno: Computer Press, 2004.
[9.2]
HEROUT, P. Učebnice jazyka C. 1. díl. České Budějovice: KOOP nakladatelství, 2009.
[9.3]
HEROUT, P. Učebnice jazyka C. 2. díl. České Budějovice: KOOP nakladatelství, 2008.