21. cvičení

Probrané příklady

Aplikace spojového seznamu – ze souboru načteme jednoduchou databázi lidí a jejich atributů (jméno, příjmení, věk, …). Doplníme některé operace, např. hledání podle jména nebo příjmení, nejmladší a nejstarší osoby, atd.

Celý program ze cvičení: seznam_lidi.c

Testovací databáze (seznam.txt):

# jmeno prijmeni vek pohlavi narodnost znamka deti vyska vaha bydliste
Jan Novak      42   M Ceska 1   2   180 80  Praha
Jana Novakova  41   Z Ceska 5   2   170 70  Brno
Jana Novak     43   Z Ceska 3   2   190 90  Praha

22. cvičení

Dokončení příkladu z předchozího cvičení.

Výpis všech lidí se zadaným jménem

Při hledání ve spojovém seznamu může dojít k nejednoznačnosti – může existovat např. více lidí se stejným jménem. Pro hledání proto místo původní funkce najdi použijeme novou funkci najdi_dalsi, která nehledá od začátku spojového seznamu, ale od zadaného prvku – to bude nejprve začátek seznamu, poté následník prvního nalezeného prvku, následník druhého nalezeného prvku, atd.

uzel* najdi_dalsi(uzel* aktualni, char* jmeno)
{
    while (aktualni->naslednik != NULL) {
        if (strcmp(aktualni->data->jmeno, jmeno) == 0)
            return aktualni;
        aktualni = aktualni->naslednik;
    }
    return NULL;
}

Pro nalezení všech lidí se zadaným jménem musíme tuto funkci použit v cyklu:

uzel* u = najdi_dalsi(s.zacatek, "Jana");
if (u == NULL) {
    printf("nenalezeno\n");
}
while (u != NULL) {
    printf("nalezeno: ");
    vypis_data(u->data);
    u = najdi_dalsi(u->naslednik, "Jana");
}

Vyhledávání podle jména bez ohledu na velikost písmen

Abychom mohli porovnat dva textové řetězce bez ohledu na velikost písmen, musíme vytvořit pomocné řetězce, do nich zkopírovat původní řetězce se všemi znaky převedenými např. na malá písmena a potom porovnat pomocné řetězce. Funkci najdi_dalsi můžeme modifikovat např. takto:

uzel* najdi_dalsi(uzel* aktualni, char* jmeno)
{
    // pomocny retezec pro zadane jmeno
    char jmeno_male[15];
    for (int i = 0; i < strlen(jmeno) + 1; i++)
        jmeno_male[i] = tolower(jmeno[i]);

    while (aktualni->naslednik != NULL) {
        // pomocny retezec pro atualni jmeno
        char aktualni_male[15];
        for (int i = 0; i < strlen(aktualni->data->jmeno) + 1; i++)
            aktualni_male[i] = tolower(aktualni->data->jmeno[i]);

        // porovnani pomocnych retezcu
        if (strcmp(aktualni_male, jmeno_male) == 0)
            return aktualni;
        aktualni = aktualni->naslednik;
    }

    return NULL;
}

Poznámka: Při kopírování textových řetězců je potřeba zkopírovat o jeden znak více, aby byly nové řetězce správně ukončeny nulovým znakem.