{{indexmenu_n>3}} ====== 3 - Řídicí struktury, funkce a ladění programu ====== * pro vyučující: [[courses:b3b36prg:internal:tutorialinstruction:03|]] ===== Úkoly ===== ==== Kalendář ==== * Naprogramujte zjednodušenou verzi programu ''cal''. * Nejdříve zkuste vypsat: Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 * Pak zkuste kalendář pro mesíc září: September Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 * nebo rovnou kalendář pro tři po sobě jdoucí měsíce: September Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 October Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 November Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 * Parametrizujte kód, pokud tak již nemáte a zkuste vypsat kalendář pro různý rozsah měsícu. * Následující vám může pomoci: static char *day_of_week[] = {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su" }; static char *name_of_month[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; static int days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static int first_day_in_september = 3; // 1. 9. 2016 is Thursday static int first_day_in_year = 4; // 1. 1. 2016 is Friday ==== Ladění programu - Debug ==== * Všechny programy v této sekci kompilujte s přepínačem ''-g''. * Spusťte následující program. Porovnejte výstup s ostatními ve třídě a vysvětlete, co se v programu děje. #include int main(int argc, char *argv[]) { int arr[5] = { 1, 2, 3, 4, 5 }; for (int i = 0; i < 30; ++i){ printf("%d: %d\n", i, arr[i]); } return 0; } * Zkuste zvýšit počet cyklů na 10000. Co se děje nyní. Jaký je návratový kód programu? (''echo $?'') * Nyní zkuste spustit valgrind ./prog 2>log a podívejte se do souboru ''log''. Zkuste sami rozluštit co valgrind vypisuje. * Podobně si vyzkoušejte ''gdb'' s prikazy ''run'' a ''bt'': gdb ./prog (gdb) run (gdb) bt * Podobně zanalyzujte následující kód #include static int arr[5] = { 1, 2, 3, 4, 5 }; static void endless(int size) { for (int i = 0; i < size; ++i) printf(" %d", arr[i]); printf("\n"); endless(size * 10); } int main(int argc, char *argv[]) { endless(1); return 0; } * Zjistěte, co dělá funkce ''a()''. Nejdříve si prohlídněte kód a zkuste rozluštit, co se v něm děje. Potom si rozmyslete, jak funkci otestovat a otestujte ji. #include static int a(int i); static int b(int i); static int c(int i); static int d(int i); static int a(int i) { int shift = sizeof(int) * 8 - 1; if ((i & (0x1 << shift)) == INT_MIN){ return i + a(0); }else if (i % 2 == 0){ return a(i + 1) - 1; }else{ return i + b(i) / 2; } } static int b(int i) { if ((i & 0x1) == 0){ return d(i); }else{ return c(i - 1); } } static int c(int i) { int j = i / 2; if (i == 0){ return 2; }else{ return b(j); } } static int d(int i) { int ip = i + 1; int im = i - 1; if (i == 1) return ip; return b(im); } int main(int argc, char *argv[]) { ... } * Zkuste teď svůj testovací program spustit pomocí ''gdb'' nebo ''cgdb''. Vyzkoušejte si následující příkazy. run -- spustí běh break [název funkce nebo číslo řádku] -- nastaví breakpoint tbreak [název funkce nebo číslo řádku] -- nastaví jednorázový breakpoint clear [název funkce nebo číslo řádku] -- smaže breakpoint info break -- zobrazí seznam breakpointů step -- provede jeden krok program (zkratka s) step [počet kroků] -- provede uvedený počet kroků programu display [výraz] -- nastaví výraz, který se vypíše při každém zastavení backtrace -- vypíšte backtrace frame -- zobrazí rámec up [počet rámců] -- posune program o počet rámců zpět down [počet rámců] -- posune program o počet rámců dopředu info locals -- zobrazí lokální proměnné info args -- zobrazí argumenty rámce info variables -- zobrazí všechny statické a globální proměnné