Podklady přednášek pro aktuální akademický rok 2017/2018. Podklady se skládají z promítaných slidů, které jsou také k dispozici ve zkrácených verzích šetrnějších k případnému tisku, bez přechodů mezi snímky a ve formátu čtyř a devíti snímků na stránku.
Podklady tvoří podpůrný materiál a jejich učelem není nahradit vlastní zápisky z přednášky, které slouží také jako prostředek osvojení si studované problematiky.
Tématicky je náplň přednášek pokryta v knize Stephen G. Kochan: Programming in C (3rd Edition), Sams Publishing, 2005, případně též Pavel Herout, Učebnice Jazyka C - 1. díl, Kopp, 2016. Před přednáškou je doporučeno pročíst si odkazované kapitoly.
V přednáškách uvedené zdrojové kódy jsou přiloženy v příslušném .zip
archivu. Kromě vyzkoušení programů je též vřele doporučeno si složitější úlohy samostatně naprogramovat a přednáškové příklady využít pro inspiraci.
#VTýden | Týden | Téma | Středa 16:15 (Místnost T2:D3-309) |
---|---|---|---|
01 | 40. | Přednáška 01 - Informace o předmětu, Úvod do programování S. G. Kochan: kapitoly 2 a 3 | 04.10. - lec01 |
02 | 41. | Přednáška 02 - Základy programování v C S. G. Kochan: kapitoly 2 a 3 | 11.10. - lec02 |
03 | 42. | Přednáška 03 - Zápis programu v C a základní řídicí struktury S. G. Kochan: kapitoly 3, 4, 5 a část 6 | 18.10. - lec03 |
04 | 43. | Přednáška 04 - Řídicí struktury, výrazy a funkce S. G. Kochan: kapitoly 4, 5, 6 a 12 | 25.10. - lec04 |
05 | 44. | Přednáška 05 - Pole, ukazatel, textový řetězec S. G. Kochan: kapitoly 7, 10 a 11 | 01.11. - lec05 |
06 | 45. | Přednáška 06 - Ukazatele, paměťové třídy a volání funkcí S. G. Kochan: kapitoly 8 a 11 | 08.11. - lec06 |
07 | 46. | Přednáška 07 - Struktury a uniony, přesnost výpočtů a vnitřní reprezentace číselných typů S. G. Kochan: kapitoly 9, 14, 17 a Appendix B | 15.11. - lec07 |
08 | 47. | Přednáška 08 - Standardní knihovny C. Rekurze. S. G. Kochan: kapitola 16 a Appendix B | 22.11. - lec08 |
09 | 48. | Přednáška 09 - Spojové struktury | 29.11. - lec09 |
10 | 49. | Přednáška 10 - Stromy | 06.12. - lec10 |
11 | 50. | Přednáška 11 - Abstraktní datový typ (ADT) - zásobník, fronta, prioritní fronta | 13.12. - lec11 |
12 | 51. | Přednáška 12 - Prioritní fronta, halda. Příklad použití při hledání nejkratší cesty v grafu | 20.12. - lec12 |
– | 52. | Zimní prázdniny | |
13 | 01. | Přednáška 13 - Rezerva Dokončení přednášky Přednáška 10 - Stromy Přehled zdrojových souborů k implementační zkoušce. Dotazy a upřesnění náročnějších pasáží předchozích přednášek a domácích úkolů | 03.01. - lec13 |
14 | 02. | Přednáška 14 - | 10.01. - lec14 |
— Jan Faigl 2017/10/04 15:39
— Jan Faigl 2017/10/11 14:36
Dotazy z přednášky
Q: Jaká je vnitřní reprezentace typu _Bool?
Norma standardu C uvádí, že dostatečná pro uložení hodnot 0 a 1. Prakticky je to char
, tj. jeden byte, viz příklad lec02/bool.c
.
Q: Jak vytisknu znak '%' nebo '\' ve funkci printf()
?
Jako dvojici znaků, tj.
printf("%% a \\ a následně například nový řádek \n");
— Jan Faigl 2017/10/20 08:21 Aktualizace: Oprava překlepů, doplnění informace o unárním operátoru přetypování.
— Jan Faigl 2017/08/17 00:10
— Jan Faigl 2017/10/26 09:42 Aktualizace: Oprava překlepů a diagramu pro do..while()
Doplnění načítání vstupu
Při načítání vstupu funkcí scanf() lze rozlišit tři případy - úspěšné načtení požadované hodnoty, detekce ukončení vstupu a vstup neodpovídající načítané hodnotě, více viz man scanf
.
#include <stdio.h> int main(void) { int v; int r; int c = 0; while ((r = scanf("%d", &v)) > 0) { c += 1; } if (r == EOF) { printf("End of file detected, no. of parsed values %i\n", c); } else { printf("Error occur during parsing value no. %i\n", c + 1); } return 0; }
— Jan Faigl 2017/08/17 00:10
— Jan Faigl 2017/10/26 09:42 Aktualizace: Doplnění kódů pro příklady nedefinovaného chování
Dotazy z přednášky
Q: Je možné umístit návěští pro příkaz goto
před cyklus?
V zásadě ano, jediným omezením je použití pouze v rámci jedné funkce a dále pak otvírá rozsah platnosti (scope) proměnných konkretního bloku. To souvisí s paměťovou třídou lokálních proměnných (viz přednáška 6). V podstatě nelze příkazem goto
skočit na místo, kde ještě není proměnná deklarována (v rámci jednoho bloku).
Návěští před začátkem cyklu | Návěští před začátkem cyklu, ale před deklarací proměnné (nelze) |
---|---|
int a; // začátek platnosti a outer: for (int i = 0; i < 3; ++i) { goto outer; } | outer: // proměnná a (bloku) není deklarována, návěští nelze uvést int a; for (int i = 0; i < 3; ++i) { goto outer; } |
Další podstatnou nevýhodou umístění návěští před cyklus je horší čitelnost a tím také vyšší náchylnost k chybě a zacyklení.
— Jan Faigl 2017/08/17 00:10
Dotazy z přednášky
Q: Proč uvedený příklad načítání skončil v nekonečné smyčce?
Načítání hodnot celých čísel funkcí scanf()
ve smyčce while
:
#include <stdio.h> int main(void) { int v; int i = 0; while (scanf("%d", &v) > 0) { printf("%d %d\n", ++i, v); } printf("No. of read values %d\n", i); return 0; }
Skončil v nekonečné smyčce, neboť původní podmínka cyklu
while (scanf("%d", &v)) { ... }je vyhodnocena jako logická pravda i v případě neúspěšného načtení nové celočíselné hodnoty. V proměnné zůstane původní hodnota. Při opravě jsem, jak někdo na přednášce zmínil, zapomněl soubor uložit.
— Jan Faigl 2017/08/17 00:10
— Jan Faigl 2017/11/09 21:56 Aktualizace: Oprava překlepů a přidání snímku 26 s příkladem na extern
Dotazy z přednášky
Q: Snažím se načíst celé číslo do typu unsigned int
funkcí scanf()
a když dám na vstup celé záporné číslo, např. -10, nejen, že se hodnota načte, ale hodnota je veliká. Jak je to možné?
Minimální kód programu read_unsigned.c
může být například:
#include <stdio.h> int main(void) { unsigned int i; int r = scanf("%+u", &i); printf("Return value %i read value %u\n", r, i); return 0; }
Výstup pak například
clang read_unsigned.c && echo "-10" | ./a.out Return value 1 read value 4294967286Hodnota 4294967286 odpovídající maximálním hodnotě typu
unsigned int
bez 10 vyplývá z použití doplňkového kódu. Program nemá zřejmé očekávané chování. Při bližším pohledu na chování funkce scanf()
, např. man scanf
NAME scanf, fscanf, sscanf, vscanf, vsscanf, vfscanf — input format conversion LIBRARY Standard C Library (libc, -lc) ... u Matches an optionally signed decimal integer; the next pointer must be a pointer to unsigned int. ...se dočteme, že konverze přes
“%u”
načítá znamenkový integer
. Funkce se tak chová dle dokumentace. V případě, že bychom se chtěli vyhnout takovému chování můžeme buď použití větší datový typ, např. unsigned long
, a kontroloval rozsah pro unsigned int
nebo si napsat vlastní načítání pouze kladných hodnot a při výskytu znaku '-
' na vstupu indikovat špatný vstup.
— Jan Faigl 2017/11/15 16:05
Dotazy z přednášky
Q: Je nutné nebo vhodné explicitně typovat ukazatel návratové hodnoty z volání funkce malloc
()?
Vyloženě nutné to v současných verzích Cčka není, přestože pro některé kompilátory (zvláště pak před standarem) to nutné bylo. V současné době je typ void*
chápan jako generický ukazatel, jehož přetypování na konktrétní typ ukazatel na proměnné příslušné typu je zřejmé dle typu proměnné a není tak nutné explicitní přetypování uvádět. Jestli je vhodné explicitně přetypovat, tak na to se názory různí. Například v knize S.G.Kochan: Programming in C (3rd Edition), Sams Publishing, 2005 je uváděn malloc
vždy s explicitním přetypováním:
int *a = (int*)malloc(10 * sizeof(int));
Naproti tomu v knize K.N. King: C Programming A Modern Approach, Second Edition. W. W. Norton & Company, Inc., 2008 je preferována varianta bez přetypování:
int *b = malloc(10 * sizeof(int));
Obě varianty jsou přípustné, argumenty proti explicitnímu přetypování jsou uváděny například: přehlednější kód a je to zbytečné, neboť dochází k přetypování automaticky. Na druhé straně relativně silné argumenty pro explicitní přetypování uvedené v diskusi http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc jsou například:
You do cast, because:
Je to tak spíše věc osobního vkusu, preferencí, případně používaného kódovacího stylu.
Q: Jak funguje ukazatelová aritmetika v případě void*
Přičítá se hodnota jednoho bajtu, například pro hodnotu ukazatele void *a = 0x100;
bude je hodnota (a+1)
rovna 0x101.
— Jan Faigl 2017/11/22 12:29
— Jan Faigl 2017/11/29 15:22
— Jan Faigl 2017/08/17 00:10
— Jan Faigl 2017/08/17 00:10
— Jan Faigl 2017/12/20 08:45
— Jan Faigl 2017/12/23 08:09 Aktualizace: Zjednoušení návratové hodnoty funkce dijkstra_solve()
a zpřehlednění podmínky v pq_down()
.
— Jan Faigl 2018/01/08 08:48 Aktualizace: tdijkstra verze 2.3.6. - fix segfault při pokusu testovat řešení většího grafu než je vstupní graf
Zkouškový test
Např. systémy pro správu verzí
* prezentace: b0b36prp-lec14-slides.pdf
* zkrácená verze: b0b36prp-lec14-handout.pdf
* zkrácená verze 2×2: b0b36prp-lec14-handout-2x2.pdf
* zkrácená verze 3×3: b0b36prp-lec14-handout-3x3.pdf
— Jan Faigl 2017/12/20 14:15