{{indexmenu_n>5}} ====== 5 - Pole variabilní délky a textové řetězce ====== * [[courses:b0b36prp:internal:tutorialinstruction:05|pro vyučující]] ===== Cíle cvičení ===== - 1D pole variabilní délky. - Ukazatel, reference ''&'' a dereference ''*''. - Pointerová aritmetika. - Textové řetězce. ==== Materiály ==== * [[https://en.wikipedia.org/wiki/ASCII|ASCII tabulka]] * Délka textového řetězce: [[https://en.cppreference.com/w/cpp/string/byte/strlen|strlen]] * Porovnání řetězců: [[https://en.cppreference.com/w/c/string/byte/strcmp|strcmp]], [[https://en.cppreference.com/w/c/string/byte/strncmp|strncmp]] ===== Pole Variabilní Délky ===== - Napište program, který provede inicializaci 1D pole. Velikost pole zadá uživatel ze standardního vstupu. Protože se jedná o inicializaci za běhu programu, je třeba zkompilovat program s podporou standardu C99. - Pole naplňte celými čísly ze standardního vstupu. - Doplňte program tak, aby prošel pole pomocí cyklu a vypsal jednotlivé prvky pole. Zkuste napsat cyklus tak, aby program vypsal pole ve více sloupcích. - Napište funkci, která vypíše prvky pole, které je jejím argumentem. Funkci implementujte v přechozím programu. /* PV: Zkraceno protoze je malo casu - Napište funkci, která naplní pole zadané velikosti náhodnými celými čísly v zadaném rozsahu. Vytvořené pole je návratovou hodnotou funkce. - Naplňte pole pomocí funkce z předchozího bodu. Napište funkci, která určí četnost čísel v tomto poli (histogram). ==== Další úkoly ==== - Napište funkci, která setřídí pole metodou counting-sort. Nesetříděné pole je argumentem funkce, návratovou hodnotou funkce je pole setříděné. */ ===== Pointery a jejich aritmetika ===== ==== Reference, Dereference a Paměť ==== Odhadněte výstupy následujících výpisů a ověřte odhady v spuštěním programu. int x = 10; int *px = &x; printf("px = %ld\n", px); printf("*px = %d\n", *px); ++++ Otázky k diskuzi | * Proč se hodnota ''px'' mění při každém spuštění? ++++ char c = 10; int x = 10; int* px = &x; char* pc = &c; printf("sizeof(c) = %ld\n", sizeof(c)); printf("sizeof(x) = %ld\n", sizeof(x)); printf("sizeof(px) = %ld\n", sizeof(px)); printf("sizeof(pc) = %ld\n", sizeof(pc)); printf("(pc - px) = %ld\n", (pc - (char*)px)); ++++ Otázky k diskuzi | ''int'' zabere víc místa v paměti než ''char''. * Ale adresy na ''int'' a ''char'' zaberou stejné množství místa, jak to? * Jak kompilátor ví, kolik paměti má očekávat (při čtení či zápisu) při derefernci ''*px''? * Proč se poslední výpis nemění? ++++ int x; char *pcx = &x; pcx[0] = 'a'; pcx[1] = 'b'; pcx[2] = 'c'; pcx[3] = '\0'; printf("x = %d\n", x); printf("&x = %ld\n", &x); printf("&x = %s\n", &x); ++++ Otázky k diskuzi | * Co je hodnotou proměnné ''x''? Číslo nebo pole znaků? ++++ ==== Pointerová aritmetika ==== - Určete výsledek a ověřte programem: int array[] = {5, -6, 0, 8, -9, 3, 1, -4}; int *up = array; int **uup = &up; printf("array[1] = %d \n", array[1]); printf("array[1] + 4 = %d \n", array[1] + 4); printf("(array + 1)[2] = %d \n", (array + 1)[2]); printf("*up = %d \n", *up); printf("*up + 4 = %d \n", *up + 4); printf("*(up + 1) = %d \n", *(up + 1)); printf("**uup = %2d \n", **uup); printf("*(*uup + 2) = %2d \n", *(*uup + 2)); printf("**uup + 4 = %2d \n", **uup + 4); ===== Textové řetězce ===== * Definujte textový řetězec "Everybody likes PRP" a vypište ho. Následně vypište z tohoto řetězce pouze "likes PRP" a nakonec řetězec změňte na "Tom likes PRP" a vypište ho. Přemýšlejte, jak to provést nejúsporněji. * Naprogramujte funkce strlen, strcmp a strncmp. === cat === * Naprogramujte zjednodušenou verzi programu ''cat''. Načtěte vstup ze stdin a zase ho vypište na výstup (stdout). echo "Hello world" | cat Hello world * Upravte program tak, aby vypsal vstup až za první mezerou: echo "Hello world" | cat2 world * Vypište každe slovo ze vstupu na samostatný řádek (za oddělovače slov považujte mezeru, konec řádku ''\n'' a tabulátor ''\t''). echo "Hello world and hello again " | words Hello world and hello again * Nyní zkuste totéž, ale za každé slovo vypište i jeho délku a slova 'and' a 'or' nejak označte. echo "Hello world and hello again " | words-len Hello 5 world 5 and 3 <-- hello 5 again 5 === tr === * Načtěte vstup a vypište ho s malými písmeny přepsanými na velké a naopak echo "Hello world" | cap ===== hELLO WORLD * Nyní zkuste zjednodušenou verzi programu ''tr''. Program bude mít zadány dva argumenty na příkazové řádce, které budou sloužit jako předpis pro překlad znaků viz. následující příklad: echo "Hello world" | tr 'Hl' 'Xk' Xekko workd echo "Hello world" | tr 'dweji' '01234' H2llo 1orl0 * Zkuste si pospojovat dnešní programy. Např.: echo "Hello world and hello again " | words | cap hELLO WORLD AND HELLO AGAIN === Feedback === Pro cvičení Jakuba Dupáka: [[https://jakubdupak.com/prp-feedback/]]