{{indexmenu_n>4}}
====== 4 - Řídicí struktury, funkce a ladění programu ======
* pro vyučující: [[courses:b3b36prg:internal:tutorialinstruction:04|]]
===== Ú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, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
static int first_day_in_march = 1; // 1. 3. 2022 is Tuesday
static int first_day_in_year = 5; // 1. 1. 2022 is Saturday
==== 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é