Hlavní strana -> Programování v C -> 11. Pole, práce s řetězci

11. Pole, práce s řetězci

Malý úvod. Zdravím pravidelné návštěvníky (zatím žádní nejsou) těchto stránek o programování v C-čku. Těm nepravidelným i těm pravidelným co nejsou :-) na úvod říkám, že dnes to bude, jak nadpis napovídá, o polích a o práci s řetězci.

Takže o řetězcích jsem vykládal minule, ale moc toho nebylo. Vpodstatě teď umíme řetězec pouze načíst pomocí jedné funkce a pomocí druhé jej vypsat. S řetězci se dá různě manipulovat a standardně nám k tomu překladače nabízí některé základní funkce. Přitom všechny tyto funkce vyžadují, aby na začátku programu byl přidán hlavičkový soubor string.h. Například:

strlen(retezec)

Tato funkce vrací délku řetězce zadaného do závorek. Je možno zadat jako argument funkci také jméno proměnné, ve které je uložen řetězec (tedy jméno pole obsahujícího řetězec).

strlen("Delka retezce");
/* vrátí číslo 13, ukončovací nula se nepočítá */

char string[15] = "Delka retezce";
strlen(string);
/* tady strlen() vrátí také číslo 13 */

Další funkcí je:

strcpy(cil, zdroj)

Tuto funkci použijeme v případě, že potřebujeme zkopírovat obsah jednoho řetězce (zdroj) do druhého (cil). Předchozí řetězec bychom mohli přepsat tímto příkazem:

strcpy(string, "Prepsany");

Po provedení tohoto příkazu by se původní obsah pole string přepsal řetězcem "Prepsany". Tady je třeba opět dávat pozor na to, aby nebyly překročeny hranice pole a nedošlo k chybě. Následující použití strcpy() pro pole string delky 15 by bylo chybné.

strcpy(string, "Tohle je spatne pouziti");

Další funkce:

strcat(prvni, druhy)

Provádí zřetězení dvou řetězců v jeden a to tak, že přidá k prvnímu obsah druhého. Přitom: ukončovací nula prvního řetězce je nahrazena prvním znakem druhého řetězce a na konec výsledného řetězce je přidána ukončovací nula. Funkce výsledek ukládá na pozici prvni a vrátí ukazatel (ukazatele jsou dále). Příklad:

char prvni[50], druhy[50];

gets(prvni);
gets(druhy);
strcat(prvni, druhy);
printf(prvni);

Teď vysvětlení. Program si vyždá zadání dvou řetězců, potom je zřetězí tak, že k prvnímu přidá druhý. Pokud byste takovému programu zadali dva řetězce "ahoj" a "lidi", pak by program vypsal "ahojlidi". Opět je třeba dávat pozor na rozsah pole a cílové (první) pole by mělo být dostatečně veliké na to, aby se do něj vešly oba dva spojované řetězce.

Další funkce:

strcmp(prvni, druhy)

Tato nám porovnává zadané řetězce lexikograficky, tedy slovníkově. Potom "ahoj" je menší než "autobus". Řetězce nejsou porovnávány podle délky. Na to byste museli použít dvě funkce strlen() a porovnat jejich návratové hodnoty. Funkce vrací číslo podle toho, jak se liší oba řetězce. Vrací číslo menší než nula, pokud je prvni řetězec menší než druhy. Nulu pokud jsou oba řetězce shodé a číslo větší než nula, pokud je druhý řetězec větší než první. Příklady budou později v příkladech :-)

No to by zatím k řetězcům mohlo stačit. Tohle jsou 4 asi nejvíce používané, ale ve skutečnosti jich je více. Zatím to stačí. Proto přejdeme k polím (array). Nejsou to taková pole, do kterých byste běžně mohli sázet brambory nebo řepu :-) Pole už jste používali při práci s řetězci. Řekli jsme si, že řetězec může být uložen do pole znaků. Neexistují však jen pole znaků, ale také pole celočíselných hodnot, hodnot s pohyblivou řádovou čárkou nebo klidně i vlastních datových typů. Asi jsem vás zmátl těmi vlastními datovými typy. Ono totiž C-čko dovoluje si vytvářet tak trochu vlastní typy, ale o tom taky až někdy jindy. Jen vám řeknu že se jedná o příkaz typedef nebo struct a uninon. Obecně lze vytvořit jednorozmědné pole takto:

typ jméno-pole[velikost pole];

Tady typ je datový typ platný v jazyce C, jméno pole si můžeme vymyslet jako jméno proměnné a velikost pole dána do hranatých závorek zadává jeho velikost. (nečekané že?) Pole jsou jedním ze základních prvků programů v C a jen těžko a mnohdy vůbec bychom bez nich vytvářeli určité situace. Pole použijeme, když chceme vytvořit velké množství proměnných stejného typu a když spolu jejich hodnoty budou nějak souviset. Jedna proměnná z tohoto pole se pak nazývá prvek.

Fajn. Takže už víme, jak vytvořit pole. Teď ještě k použití. Můžeme si třeba vytvořit pole, do kterého si budeme zapisovat, kolik dní v měsíci bylo slunečno. Pole bude mít velikost 12, protože 12 měsíců a typ použijeme int.

int mesic[12];

Když máme pole vytvořené, tak do něj potřebujeme nějak hodnoty zapsat. Budeme tedy přistupovat k jednotlivým prvkům pole. To se dělá tak, že pole se indexuje. Každé pole začíná indexem 0 a končí indexem velikost-1. Index se zapisuje za jméno pole do hranatých závorek. K plnění polí se používají cykly. Následující úsek programu si od uživatele vyžádá zadání 12 celočíselných hodnot, které budou představovat počet slunečných dnů v daném měsíci. Budem potřebovat ještě jednu celočíselnou proměnnou, která bude představovat indexy pole.

int i;

for(i=0; i<12; i++){
    printf("Zadejte pocet slunecnych dni v %d. mesici\n", i+1);
    scanf("%d", &mesic[i]);
}

Začíná se zde s indexem nula a končí s indexem 11. Vyžádání načtení hodnoty do prvku mesic[12] by bylo chybné, protože 13. prvek neexistuje. Začíná se od 0 a 12 je tedy index 13. prvku pole. Hranice pole opět nesmí být překročeny, jinak může dojít k havárii programu nebo přinejmenším k neobvyklému chování.

Jedno pole se nedá přiřadit druhému poli, ikdyž jsou stejného typu a stejné délky. Toto je špatně:

int pole1[5], pole2[5];

/* pole1 se treba naplni nejakymi hodnotami */

pole2 = pole1; /* pole se nezkopiruje */

Pole se takto nezkopíruje, zkopíruje se pouze adresa (ukazatel) na první prvek. To se sice dá využít, ale ne tady. Místo toho je zapotřebí pro zkopírování obsahu jednoho pole do druhého pole použít příkaz pro cyklus a zkopírovat jednotlivé prvky pole.

for(i=0; i<5; i++)
    pole2[i] = pole1[i];

Zatím byla řeč pouze o jedno-rozměrných polích, ale C-čko dovoluje vytvářet dvou i více-rozměrné pole. Dvourozměrné pole se vytvoří přidáním dalšího čísla do hranatých závorek. Takto si můžeme vytvořit pole, které bude obsahovat, kolik minut každou hodinu v měsíci... něco, třeba běžel nějaký stroj. Použijem den o 24 hodinách a měsíc o 30 dních.

int stroj[30][24];
int i, j;

for(i=0; i<30; i++){
    for(j=0; j<24; j++){
        printf("Zadejte pocet minut.\n");
        scanf("%d", &stroj[i][j]);
    }
}

Tento příklad sice uživatele zničí (protože se ho zeptá na počet minut 30*24=720 krát), ale jako příklad to postačí. Máme tam vnořený cyklus for, který se zeptá na zadání 24 hodnot, pak skončí, program se vrátí k vnějšímu for, přidá k i jedničku a znovu vyvolá vnitřní for pro zadání 24 hodnot. A tak to jede pořád dokola 30x.

Počet rozměrů není nijak omezen, ale použítí vícerozměrných polí se moc nevyskytuje. Spíš jenom tak do 2-3 rozměrů. Při více rozměrech se stává omezující také paměť. Představte si celočíselnou proměnnou, která je dlouhá 4 bajty. Když vytvoříte jednorozměrné pole o velikosti 100, tak to zabere 400 bajtů. Při použití pole 100x100 už to dělá 40 000 bajtů. Čtyřrozměrné pole 100x100x100x100 sežere 400 000 000 bajtů paměti. To už je hodně i při dnešních pamětech. Takové pětirozměrné pole zbaští 40 000 000 000 bajtů paměti a to dnes (rok 2004) nemá doma nikdo:-) Z toho vyplývá - všeho s mírou.

A je to. Konečně mi taky napište. K.

Příklady

Zpět

Programování v C | CZ 175/477 | Mapa stránek
Bc. Petr Klimánek, student Ostravské univerzity v Ostravě