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.