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 <bazar.h> int main(void) T_car *bazar[200]; // ptrs. to cars int cnt=0; // number of recorded cars int lprice, hprice; char cmd; 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 struct car // car record char type[20]; // type of car char color[10]; // color of car char mot; // kind of the motor B = benzin, D = diesel
int vol; // motor volume in cubic cm int year; // year of production int price; // price T_car; 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 <bazar.h> 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<num; n++) print_record(rec[n]); // insert function for deleting of all cars // insert function for printing of all cars from given price range // insert function for adding a new car 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: 2,4 bodu za metr K70 - K79: 2,2 bodu za metr K80 - K99: 2,0 bodu za metr K100 - K169: 1,8 bodu za metr K170 a více: 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; // sum of points int order; // order t_jump round_1; // jump and eval. in the 1st round t_jump round_2; // jump and eval. in the 2nd round t_competitor; t_competitor *comp[30]; int cnt=0; // 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.