7 - Dynamická alokace a struktury

Cíle cvičení

  1. Použití struktury.
  2. Pointer na funkce.

Úkoly

Výpis načtených řádků v opačném pořadí

  • Implementujte program, který načte vstupní textový soubor, který následně vypíše v opačném pořadí načtených řádků.
  • Nejdříve implementujeme načtení řádků s dynamickou alokací. Předpokládáme, že vstup má řádky zakončeny znakem '\n'.
    • V případně chybějícího znaku \n načteme pouze jeden řádek, nebo reportujeme chybu vstupu.
  • Program vhodně dekomponujeme a uvažujte tři chybové stavy.
    • 100 - Chyba načtení.
    • 101 - Chyba alokace dynamické paměti.
    • 102 - Chyba výstupu. Uvažujte, že tisk na standardní výstup může selhat.
  • V lab06 jsme datovou strukturu uvažovali jako dynamicky alokované pole ukazatelů na textové řetězce reprezentující postupně načtené řádky.
  • Program z předchozího cvičení rozšíříme o použítí složeného typu struct, kterým nahradíme více argumentů, jedním argumentem.
    • Budeme uvažovat možnou dynamickou alokaci proměnné složeného typu. Proto budeme předávat proměnnou typu ukazatel na naší datovou strukturu řádků.

Výchozí (předpokládané) řešení ze 6. cvičení

  • Předpokládáme, že máme implementované funkce pro načtení jednoho řádku, případně více řádků a jejich tisk dle rozhraní .
Ve funkci free_lines nastavujeme hodnotu ukazatele alokované paměti na prokazatelně neplatnou adresu NULL, proto předáváme ukazatel na datový typ proměnné, který je v našem případě ukazatel na ukazatel na char, proto tři hvězdičky.

Příklad implementace free_lines()

Definice složeného typu struct

Proměnnou s počtem řádků a polem s řádky

nahradíme

složeným typem struct

Složený typ alokujeme ve funkci read_lines(), nicméně z důvodu dynamické alokace lines→lines implementujeme alokaci složeného typu v samostatné funkce allocate_lines()

např.

Funkci použijeme

např

Kromě funkce read_lines(), ve které alokujeme proměnnou složeného typu struct linies modifikujeme

  • print_lines() na int print_lines(struct lines *lines);

např. na

  • a free_lines() na
    void free_lines(struct lines **lines);

např. jako

Příklad možných změn vůči řešení lab06

Vytvoření náhodné permutace

  • Program rozšiřte o výpis řádků v náhodném pořadí.
  • Nejdříve si vyzkoušejte implementaci vytvoření permutace posloupnosti čísel 0 až n, viz man 3 rand.
  • Vytvoření permutace následně integrujte do programu.
  • Můžete dále přidat argument programu (parametr z příkazové řádky), který bude modifikovat chování.

Náhodná permutace

  1. Implementujte tři funkce init, print, permute,

např.

  1. Funkce použijte v např. v jednoúčelovém programu pro inicializaci pole celých čísel, jeho vytištění, permutování a znovu vytištění na stdout.

Implementace init() a print() je relativně

přímočará

Ve funkci permute() můžeme inicializovat generátor pseudonáhodných čísel pevných číslem, nebo aktuálním časem time().

např.

Příklad hlavní funkce main

Příklad výstupu s definováním délky sekvence při kompilaci

Použití náhodné permutace

Vytvoření náhodné permutace využijeme k výpisu řádků v náhodném pořadí. Z důvodu použití typu size_t zaměníme předchozí typ unsigned int právě za size_t.

Použití size_t

Například ve funkci print_lines_rand()

Alternativně můžeme pole náhodných čísel alokovat dynamicky

Ve funkci perm() používáme volání rand(), které vrací celé číslo v rozsahu int. Fakticky pracujeme s polem a6 do velikosti size_t. Striktně vzato tak progam nebude fungovat správně pokud bude řádků více než je rozsahu typu int. Což můžeme detekovat, např. dle hodnoty INT_MAX.

Přepínání chování výstupu programu

  • Program můžeme dále rozšířit o 2. argument, který v případně hodnoty “rand” výpíše načtené řádky v náhodném pořadí.
  • Protože funkce print_lines() a print_lines_rand() mají stejnou návratovou hodnotu a argumenty, můžeme použít proměnnou ukazatel na funkci.

Příklad ukazatele na funkci

Hodnotu ukazatele na funkci nastavíme na print_lines_rand, pokud je zadán druhý argument a jeho hodnota je “rand”, což ověříme funkcí strcmp() z knihovny <string.h>.

Ověření hodnoty druhého argumentu programu

Volání funkce zajistíme přes ukazatel

Program můžeme dále rozšířit o výpis chyby v případně, že druhý argument nemá hodnotu “rand”.

Další úlohy k procvičení

  • 2D pole a příprava na násobení matic nebo ukazatelová (pointerová) aritmetika.
  1. Napište funkci, která formátovaně vypíše obecné pole reálných čísel.
  2. Napište funkci, která vypočte směrodatnou odchylku z prvků zadaného pole.
  3. Napište funkci, která zajistí načtení n prvků z klávesnice do pole a toto pole předá do volající funkce. Počet prvků bude zadán jako parametr funkce.
  4. Společně s cvičícím si předveďte použití Valgrindu pro diagnostiku přístupů do paměti a správné alokace.
  5. Aplikujte funkce pro výpis a výpočet směrodatné odchylky na pole získané načítací funkcí. Nezapomeňte na dealokaci pole při ukončení programu!
  6. Upravte předchozí funkci tak, aby byla schopna načíst libovolnou posloupnost reálných čísel do pole ukončenou vhodnou zarážkou nebo lépe pomocí EOF, umí-li to vaše konzole.
  7. Upravte předchozí kód tak, aby bylo možné načíst od uživatele více datových řad a pro každou zvlášť spočítat směrodatnou odchylku. Jednoduše to zařídíte tak, že vytvoříte dvourozměrné pole, které ale může mít různé délky řádků. Nezapomeňte zajistit i dealoakaci celého pole!
  8. Vždy kontrolujte program na přístup do paměti a alokaci nástrojem valgrind.
courses/b0b36prp/labs/lab07.txt · Last modified: 2024/09/22 16:34 by szadkrud