sqrt
.sin
. Sine and Cosine: ExpansionsZákladná enumerácia
Postupne vytvorte funkciu 1E cez nasledovné medziúlohy. Tieto úlohy zväčša vyžadujú konštrukciu základného for
cyklu so špecifickou inicializáciou, testovacou podmienkou a inkrementu.
Príklady výstupov pri interaktívnom testovaní:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Zadaj n: 7 Zadaj a: -5 Zadaj b: 10 Zadaj x: 3 Vystup 1A: 1 2 3 4 5 6 7 Vystup 1B: 2 4 6 Vystup 1C: 3 6 Vystup 1D: -3 0 3 6 9 Vystup 1E: -1 -3 0 0 1 3 2 6 3 9 Vystup 1E od konca: 3 9 2 6 1 3 0 0 -1 -3 |
Spracovanie postupností načítaných zo vstupu
scanf
…). Pozn.: Na toto je asi najvhodnejší cyklus do-while, lebo sa načítať musí aspoň 1 číslo. scanf
, na prerušenie s ukončením funkcie využite príkaz return
. continue
.. Na vyčistenie vstupu je potrebné použiť napr. nasledujúcu konštrukciu:
1 2 3 4 5 6 7 8 9 10 11 |
if (scanf("%i", &hodnota) == 0) { //vycistenie zle zadanych znakov - "vymaze" zvysok riadku while (getchar() != '\n') { //nerobime nic, a teda zahadzujeme nacitane znaky } //TODO: osetrenie chyby, napr. pokracovanie v cykle pomocou continue... } |
Generované postupnosti
Príklad výstupov pri interaktívnom testovaní:
1 2 3 4 5 |
Zadaj n: 7 Zadaj x1: -5 Zadaj x2: 10 Postupnost: -5 10 5 15 20 35 55 |
Zadanie: napíšte funkciu, ktorá overí, či je zadané rodné číslo platné. Rodné číslo je zadané funkcii v dvoch celočíselných parametroch. Vráti 0 ak nie je, 1 ak patrí mužovi a -1 ak žene.
scanf("%d/%d", &c1, &c2);
, kde c1 a c2 budú 2 intové premenné. Podľa výsledku funkcie na overenie RČ vypíšte výsledok (vetvenie). Obrázky z hviezdičiek
Zložitejšie obrazce:
Príklad výstupu (parametre 5, 3):
1 2 3 4 5 6 7 8 |
* *** * ***** * * * *** * *********** |
Extra príklady
pow
. pow
. pow
. Pre každý príklad vytvorte funkciu, ktorá dostane na vstup ako argumenty pole, počet platných prvkov poľa, a ďalšie potrebné parametre. Ak funkcia niečo počíta/zisťuje, vráťte danú hodnotu cez return
. Vo funkcii main vytvorte interaktívne testovanie, t.j. načítajte hodnoty do poľa (alebo inicializujte pole nejakou vhodnou funkciou), načítajte parametre zo vstupu, aplikujte funkciu, vypíšte výsledok/výsledky funkcie/modifikované pole. (Aspoň vybrané) Funkcie sa pokúste aj otestovať (interaktívne, alebo automatizovane) – porozmýšľajte aj nad tým, či existujú nejaké špeciálne prípady, kedy by vaše riešenie mohlo zlyhať.
stdlib.h
). poleA[i]*poleB[i]
cez všetky i). poleA[i] == poleB[i]
pre všetky i). poleOut[i] = poleA[i]+poleB[i]
, pre všetky i). poleA[i] = poleA[i]+k*poleB[i]
, pre všetky i). (void*)
a size – veľkosť údaju v bajtoch. Funkcia prehodí obsah pamäte na týchto adresách.
(void*)
a size – veľkosť údaju v bajtoch. Funkcia vypíše postupne bajty na danej adrese v hexadecimálnom tvare. Použite túto funkciu na výpis premenných rôzneho typu (napr. unsigned int i = 0xdeadbeef; double pi = 3.14
), prípadne vyskúšajte aj so smerníkom na funkciu/pole.unsigned long long*
). Funkcia zmení endian, t.j. poradie bajtov. Napr. keď na adrese bolo uložené: 0x0102030405060708ull
, po zavolaní funkcie tam bude 0x0807060504030201ull.
NULL
. Vráti smerník na dynamické pole smerníkov (ukazujúcich na začiatky slov). Napíšte si zvlášť funkciu, ktorá postupnosti čísel z takto zadaného poľa smerníkov vypíše (viete, že každá postupnosť končí nulou), každú na iný riadok.V príkladoch otestujte funkcie v nejakej inej funkcii volanej z main
(napr. funkcia na výpis), a alokované polia korektne uvoľnite.
Využitie dynamickej pamäte
Vytvorte a otestujte nasledovné funkcie, dbajte na to, aby ste správne alokovali a uvoľnili dynamickú pamäť:
realloc
. Reťazec je v jazyku C pole znakov ukončené znakom '\0'
. Na prácu so znakmi máme k dispozícii funkcie štandardnej knižnice deklarované v ctype.h
. Na prácu s reťazcami máme k dispozícii štandardné funkcie deklarované v string.h
(a plus túto reprezentáciu používajú ďalšie štandardné funkcie, napr. z stdio.h
, …).
Práca so znakmi
scanf/printf
s "%c"
maskou, alebo cez getchar/putchar
). char
a výstup typu int
. Ak znak nie je alfanumerický, funkcia vráti -1.Parametre príkazového riadku
Odskúšajte si nasledovný program:
1 2 3 4 5 6 7 8 9 |
int main(int argc, char* argv[]) { int i; for (i = 0; i < argc; i++) printf("argv[%i]: %s\n", i, argv[i]); return 0; } |
Keď program spustíte z príkazového riadku, mal by vypísať zoznam parametrov, každý na nový riadok:
1 2 3 4 5 |
> program.exe 1 aaa "b c d" argv[0] program.exe argv[1] 1 argv[2] aaa argv[3] b c d |
Pomocou Google (alebo iných vyhľadávačov) zistite, ako dostanete parametre do programu v Debug móde (Google: command line arguments visual studio c). Odskúšajte si, či viete krokovať program s argumentmi.
Teória: Vstupom funkcie main
je pole reťazcov (argv
) a ich počet (argc
). Reťazce pripraví OS pri spustení programu z konzoly. Parametre sú rozdelené medzerami, ak chcete v rámci parametra mať medzeru, musíte ho dať do úvodzoviek.
Pozn.: Ak viete používať parametre na príkazovom riadku, ušetríte si robotu s načítavaním vstupov…
Načítanie reťazca zo štandardného vstupu (klávesnice)
scanf
a gets/fgets
s rôznymi vstupmi (AAA BBB, AAAAAAAAAAAAAAAAAAAAAA):
1 2 3 4 5 6 7 8 9 |
char text[10+1]; //nacitanie 1 slova - po whitespace scanf("%s", text); //co sa stane, ked zadate viac ako 10 znakov? (skuste ovela viac) scanf("%10s", text); //nacita max 10 znakov //nacitanie riadku gets(text); //UPLNA KATASTROFA! NEPOUZIVAT!!! fgets(text, 10+1, stdin); //nacita max. 10 znakov, vratane '\n' |
Úloha: Vytvorte si vlastnú funkciu, ktorej vstupom je pole znakov (smerník) a jeho kapacita max. Do poľa načítavajte znaky zo vstupu (pomocou funkcie getchar()
alebo scanf("%c")
), kým nenarazíte na koniec riadku '\n'
, koniec súboru (scanf
zlyhá, getchar
vráti EOF
), alebo nanačítate max-1 znakov. Znak '\n'
do reťazca nevkladajte, reťazec ukočte znakom '\0'
.
Porovnanie a priradenie reťazcov
Vyskúšajte si nesprávne varianty priradenia/porovnania a zistite (aj pomocou debug módu), čo spraví správna a nesprávna verzia.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
char buffer[100]; char *ptr; //Priradenie: // NESPRAVNE: snaha priradit smernik ako novu adresu pola //buffer = "nejaky text"; // SPRAVNE: nastavenie hodnoty volneho smernika ptr = "nejaky text"; // SPRAVNE: vytvorenie kopie retazca // vyuziva sa strncpy - nie strcpy, kvoli bezpecnosti strncpy(buffer, "nejaky text", sizeof(buffer)); //Porovnanie: // NESPRAVNE: porovnavaju sa smerniky // if (buffer == "nejaky text") { nieco(); } // SPRAVNE: vyuziva sa strcmp if (strcmp(buffer, "nejaky text") == 0) { nieco(); } |
Štandardné funkcie na prácu s reťazcami
V string.h sú deklarované viaceré užitočné funkcie pre prípad, že v jazyku C potrebujete s reťazcami pracovať. Pozrite a odskúšajte si príklady z referenčnej časti a vyskúšajte si úlohy (väčšinou vlastné verzie štandardných funkcií alebo modifikácie).
'\0'
a zavoláte funkciu strlen. fgets
, pripravte dosť dlhé pole na uchovanie znakov), rozdelí ho na slová (pomocou strtok
) a vypíše slová v opačnom poradí (najjednoduchšie je uchovať výsledné smerníky, ktoré vráti strtok
do poľa smerníkov, a to pole prejsť odzadu)Ďalšie vhodné štandardné funkcie
Pozrite si funkcie v stdlib.h v časti String conversions – umožňujú skonvertovať text na číslo, napr. „123“ na 123
Vyrobte vlastnú funkciu btoi
, ktorá skonvertuje binárny reťazec na číslo, t.j. pri vstupe „10011“ vráti číslo 17
Dôležitá funkcia: sprintf
– umožňuje zapísať do reťazca text podobne ako by sme ho vypisovali na výstup. Funkcia je NEBEZPEČNÁ, musíte dávať pozor na dostatočnú kapacitu reťazca, kam zapisujete.
Vyrobte vlastnú funkciu itob
, ktorá skonvertuje číslo, na binárny reťazec t.j. pri vstupe 17 naplní zadané pole znakov tak, že tam vznikne reťazec „10011“ (aká je dostatočná kapacita poľa pre 32-bitové čísla?)
Pre konverziu textu na čísla je vhodnejšia funkcia sscanf
, pretože umožňuje otestovať úspešnosť konverzie a vstupný reťazec môže byť v rôznych formátoch.
Ďalšie príklady na reťazce
'\n'
(ten sa do poľa neuloží), pričom načíta maximálne max-1 znakov (kde max je zadaný parameter). Na koniec poľa zapíše znak konca reťazca '\0'.
Výstupom funkcie je počet znakov, ktoré sa načítali.rand()%26
a „aritmetiku“ znakov). Nezabudnite ukončiť reťazec.rand()
).rand()
bude použitý ako index v reťazci, pozor na rozsah náhodných čísel).fn(pole, 3+1, "EA","MV");
môže vygenerovať reťazce „EVA“, „EMA“, „AMA“…strcmp
porovná 2 reťazce, ale je case-insensitive (t.j. ‚a‘ je to isté ako ‚A‘)strtok
strtok
printf("%s", f("*-*-*", "ABC")); //A-B-C
f("LA*ALA", "BAJA*A")
vráti 1.f("1A")
vráti 26f("1A")
vráti 161f("(*.***x)", 3);
vypíše: (…***xxx)p={2,3,4,5,7,9}; f("(*.***x)", p);
vypíše (..***xxxx) '\0'
. HINT: Využite statické pole znakov.Podobné typy úloh sa môžu objaviť na skúške:
time_t
(počet sekúnd od referenčného času), alebo štruktúra tm
, a na konverziu sa používajú funkcie mktime/localtime/gmtime
. Pozrite si príklad na difftime
a spravte si program, ktorý umožní zistiť, koľko dní uplynulo od používateľom zadaného dátumu alebo umožní vypočítať dátum, ktorý bude o x dní (pre záporné x: pred x dňami) od zadaného dátumu/aktuálneho dátumu.int
záznam, koľko je tam bodov, a pole bodov s nejakým definovaným maximálnym počtom bodov, napr. max. 50 bodov). Vytvorte funkcie na načítanie polygónu, funkciu na zistenie obvodu polygónu, a funkciu na vykreslenie polygónu. Základná práca so súborom
fgetc
a fputc
.
fread
a fwrite
. Porovnajte výkonnosť na dlhom súbore.Dbajte aj na správne ošetrenie chýb: vyskúšajte situáciu, keď vstupný súbor neexistuje, keď výstupný súbor je read-only.
Pokročilejšia práca so súbormi
Vytvorte si nasledovné funkcie a vyskúšajte ich vo vhodnom testovacom programe:
const char*
). Funkcia súbor otvorí, spočíta riadky, zatvorí a vráti počet riadkov.FILE*
) – využite kód predošlej funkcie, ale vhodne ho rozdeľte (prvá časť čo otvára a zatvára súbor zostane, zvyšok sa robí v novej funkcii). Vyskúšajte, či sa dá použiť táto funkcia dvakrát po sebe s tým istým otvoreným súborom? Vyskúšajte to opraviť pomocou príkazu rewind
alebo fseek
. FILE*
). Využite fscanf
, kontrolujte výstup fscanf
. fseek
a ftell
. Použite túto funkciu v demo programe, v ktorom načítate celý obsah súboru do dynamicky alokovaného poľa. fread/fwrite
. Nevýhoda je, že takto vytvorené súbory nie sú (vždy) prenosné medzi rôznymi platformami, a nie sú čitateľné pre človeka (pozrite si obsah vytvoreného súboru). fprintf/fscanf
(zvoľte si vhodný formát – ako riešiť viacslovné texty?). Výhodou je čitateľnosť a prenosnosť, ale musíte k tomu viac programovať (a plus súbor je väčší).Práca s viacerými súbormi
sprintf
). Do súborov zapisujte 1000000 náhodných bajtov (rand()%256
, cez putc/fwrite
). Porovnajte výsledné veľkosti súborov v prípade, že súbory otvoríte pomocou „wb“ a iba pomocou „w“. append
.
Ako matice môžete využívať polia pevnej veľkosti, alebo polia smerníkov, kedy príslušné rozmery sú dynamicky určené (dodatočným parametrom).