Prednáška 2
- Oznamy
- Opakovanie
- Komentáre
- Podmienka (if)
- Operátory
- Dva programy s podmienkou
- Dátový typ
doublepre reálne čísla - Dátový typ
boolpre logické hodnoty - Cyklus
for - Ďalšie detaily o typoch
intadouble - Zhrnutie
Oznamy
Najbližšie dni na programovaní
- Dnes prednáška, ďalšie dve prednášky budúci týždeň
- Do pondelka 22:00 riešte úlohy zo včerajšieho cvičenia, ktoré sú na testovači.
- Ideálne ich zvládnete sami, ale ak budete mať problémy, spýtajte sa na cvičení budúci pondelok.
- Ak vám testovač k príkladu vypíše zelené OK, prešiel testami. Ak vypíše oranžový kód chyby, niečo je zle, treba opraviť a odovzdať znovu.
- Budúci pondelok aj v utorok sa na začiatku cvičenia objavia na testovači nové úlohy.
- Neskôr v semestri budú na cvičeniach aj iné aktivity, napr. riešenie úloh na papieri.
- Dnes o 18:10 nepovinný test pre pokročilých v posluchárni A (bolo sa treba prihlásiť do včera).
Technické záležitosti
- Na stránke Softvér nájdete návod na používanie softvéru v učebni a aj príklady programov, ktoré si môžete nainštalovať na vlastný počítač.
- Ak máte problémy s inštaláciou, prineste si svoj počítač na cvičenie a skúsime vám poradiť, pokiaľ zostane čas. Váš počítač je ale hlavne vaša zodpovednosť.
Ďalšie upozornenia k štúdiu:
- V rozvrhu https://candle.fmph.uniba.sk/ vidíte všetky predmety, ktoré sú povinné, povinne voliteľné alebo výberové pre váš ročník, ale nie všetky si musíte zapísať a naopak, môžete si zapísať aj iné predmety.
- Dôležité je skontrolovať si, či to máte zapísané v AIS, sedí s tým, na čo aj reálne chodíte.
- Prvé dva týždne (do 2.10.) si môžete v AIS pridávať a uberať predmety, potom treba kontaktovať študijné emailom, aby vám uzatvorili zápisný list.
- Prvácke povinné predmety by ste si mali zapísať, z výberových si môžete vybrať.
- Pozor na to, aby ste získali aspoň 15 kreditov za zimný semester.
Opakovanie
Doteraz sme videli:
- Načítavanie pomocou
scanf, výpis pomocouprintf. - Celočíselné premenné typu
int.
#include <stdio.h>
int main() {
int x, y;
printf("Please enter the first number: ");
scanf("%d", &x);
printf("Please enter the second number: ");
scanf("%d", &y);
int result = x + y;
printf("%d + %d = %d\n", x, y, result);
}
Komentáre
Do zdrojových kódov programov v jazyku C je možné pridávať komentáre, čo sú časti kódu ignorované kompilátorom.
- Komentár je časť programu začínajúca
/*a končiaca*/(aj cez viac riadkov) - Komentár je aj text od
//až po koniec riadku. To je užitočné na písanie krátkych komentárov.
Do komentárov sa zvyknú písať poznámky k významu okolitých príkazov, čo zlepšuje orientáciu v kóde a jeho pochopenie inými programátormi.
Príklad:
#include <stdio.h>
/* Tento program od používateľa načíta dve celé čísla
* a vypíše ich súčet. */
int main() {
// vytvoríme premenné x a y
int x, y;
// do premenných od používateľa načítame čísla
printf("Please enter the first number: ");
scanf("%d", &x);
printf("Please enter the second number: ");
scanf("%d", &y);
// do novej premennej result spočítame výsledok
int result = x + y;
// výsledok vypíšeme
printf("%d + %d = %d\n", x, y, result);
}
Podmienka (if)
- Niekedy chceme vykonať určité príkazy len ak sú splnené nejaké podmienky. To nám umožňuje príkaz if.
- Nasledujúci program si vypýta od používateľa číslo a vypíše, či je toto číslo záporné alebo nezáporné.
#include <stdio.h>
int main() {
int x;
printf("Zadajte cislo: ");
scanf("%d", &x);
if (x < 0) {
printf("Cislo %d je zaporne.\n", x);
} else {
printf("Cislo %d je nezaporne.\n", x);
}
}
Tu je príklad dvoch behov programu:
Zadajte cislo: 10
Cislo 10 je nezaporne.
Zadajte cislo: -3
Cislo -3 je zaporne.
- Za príkazom
ifje zátvorka s podmienkou. V našom príklade podmienka jex < 0. - Ak je podmienka v zátvorke splnená (t.j. ak
xje menšie ako nula), vykonáme príkazy v zloženej zátvorke za príkazomif. - Ak podmienka nie je splnená (t.j. ak je
xväčšie alebo rovné nule), vykonáme príkazy v zloženej zátvorke za slovomelse - Časť
else {...}je možné vynechať, ak nechceme vykonávať žiadne príkazy. - Ak za
ifaleboelsenasleduje iba jeden príkaz, zátvorky{a}môžeme vynechať. To však ľahko vedie k chybám, preto je lepšie ich vždy použiť.
Cvičenia:
- Pomocou podmienky vypíšte absolútnu hodnotu načítaného čísla.
- Namiesto vypísania uložte túto hodnotu do premennej
y, ktorá by sa dala ďalej v programe použiť.
Operátory
S číselnými premennými potrebujeme robiť rôzne operácie, napr. sčítanie, odčítanie, násobenie a delenie, porovnávanie.
Aritmetické operátory a výrazy pre celé čísla
- sčítanie
+ - odčítanie
- - násobenie
* - delenie
/pre celé čísla sa používa celočíselné delenie, hodnota podielu zaokrúhli smerom k nule - zvyšok po celočíselnom delení
%(modulo)
Tento program načíta dve celé čísla a vypíše výsledky rôznych operácií:
#include <stdio.h>
int main() {
int a, b;
printf("Zadajte dve cele cisla: ");
scanf("%d %d", &a, &b);
printf("%d + %d = %d\n", a, b, a + b);
printf("%d - %d = %d\n", a, b, a - b);
printf("%d * %d = %d\n", a, b, a * b);
printf("%d / %d = %d\n", a, b, a / b);
printf("%d %% %d = %d\n", a, b, a % b);
}
Všimnite si, že pri vypísaní zvyšku po delení sme použili %%, aby sa vypísal znak %. V opačnom prípade by príkaz printf očakával za znakom % typ premennej, ktorý sa má vypísať, napríklad %d.
Príklad behov programu:
Zadajte dve cele cisla: 23 10
23 + 10 = 33
23 - 10 = 13
23 * 10 = 230
23 / 10 = 2
23 % 10 = 3
Zadajte dve cele cisla: -23 10
-23 + 10 = -13
-23 - 10 = -33
-23 * 10 = -230
-23 / 10 = -2
-23 % 10 = -3
Zadajte dve cele cisla: 23 0
23 + 0 = 23
23 - 0 = 23
23 * 0 = 0
Floating point exception (core dumped)
Všimnite si celočíselné delenie: 23/10 bolo 2 a -23/10 bolo -2.
V poslednom behu nastala chyba kvôli deleniu nulou. Program sa predčasne ukončil a nevypísal posledné dva riadky.
Relačné operátory
Celé čísla možno porovnávať nasledujúcimi relačnými operátormi:
==pre rovnosť;!=pre nerovnosť;<pre reláciu „menší”;>pre reláciu „väčší”;<=pre reláciu „menší alebo rovný”;>=pre reláciu „väčší alebo rovný”.
Výstupom relačného operátora je logická hodnota true (pravda, 1) alebo false (nepravda, 0).
Logické operátory
Logické hodnoty true (1) alebo false (0) možno kombinovať pomocou logických operátorov. ktoré sa
správajú ako logické spojky z výrokovej logiky:
||pre disjunkciu (or, alebo);&&pre konjunkciu (and, a súčasne);!pre negáciu (not, opak)
Takže x || y je pravdivé, ak je aspoň jedna z hodnôt x alebo y pravdivá, x && y je pravdivé, ak sú obe hodnoty pravdivé a !x je pravdivé, ak je hodnota x nepravdivá.
Cvičenie: pre aké hodnoty premennej x je výraz !((x >= 2) && (x <= 4)) pravdivý?
Operátory priradenia, zvýšenie a zníženie hodnoty o 1
Operátor priradenia premenna = hodnota už poznáme. Často potrebnou
operáciou na číslach je zvýšenie hodnoty o 1. To možno urobiť napríklad
nasledujúcimi spôsobmi:
x = x + 1;x += 1;x++;
Analogicky sú definované operátory ako --, -=, *=, atď.
Dva programy s podmienkou
Vnorené podmienky
Príkazy if môžeme navzájom vnárať.
Príklad: načítaj číslo a zisti, či je kladné, záporné alebo nula.
#include <stdio.h>
int main() {
int x;
printf("Please enter some number: ");
scanf("%d", &x);
if (x == 0) {
printf("Zero\n");
} else {
if (x > 0) {
printf("Positive\n");
} else {
printf("Negative\n");
}
}
}
Počet núl
Príklad: načítaj tri čísla a vypíš, koľko z nich je nulových.
- Vytvoríme premennú
count, ktorá bude počítať počet núl. Postupne porovnáme každé číslo s nulou a ak je rovné nule, zvýšimecounto 1. Na konci vypíšeme hodnotucount.
#include <stdio.h>
int main() {
int a, b, c;
printf("Zadajte tri cisla: ");
scanf("%d %d %d", &a, &b, &c);
int count = 0;
if (a == 0) {
count++;
}
if (b == 0) {
count++;
}
if (c == 0) {
count++;
}
printf("Pocet nul: %d\n", count);
}
Upozornenie
Častou chybou je použitie priradenia namiesto porovnania. Nasledujúci
kúsok programu do premennej x priradí nulu, ktorá sa považuje za false
pre účely vyhodnotenia podmienky.
if (x = 0) printf("zero\n");
Ďalšia bežná chyba je zabudnutie zložených zátvoriek
if (x == 0) printf("x is zero\n"); count++;
Tento program vykoná count++ vždy, nezávisle od podmienky. V
prípade, že chceme vykonať v podmienke viacero príkazov, nesmieme
zabudnúť ich uzátvorkovať:
if (x==0) { printf("x is zero\n"); count++; }
Cvičenia
- Napíšte program, ktorý načíta čísla a,b,c a vypíše, či sú
usporiadané vzostupne, t.j. či platí a<b<c
- Pozor, výraz a<b<c treba rozpísať na dve porovnania spojené logickou spojkou
Dátový typ double pre reálne čísla
- Doteraz sme pracovali s typom
intpre celé čísla. - Často však potrebujeme pracovať s reálnymi číslami, ktoré môžu mať aj desatinnú časť. Na to slúži typ
double. - V programe zapisujeme konštanty typu
doubles desatinnou bodkou, napr.-1.0alebo3.14 - Môžeme použiť aj tzv. semilogaritmický zápis, napr.
1.5e3(čo znamená 1,5 ⋅ 103 = 1500). - Operátory
+,-,*,/sú definované aj pre typdouble. Operátor/sa správa ako delenie reálnych čísel, t.j. výsledok sa nezaokrúhľuje na celé číslo. Operátor%nie je definovaný pre typdouble.
double x = 1.5e3; // x = 1500.0
double y = 3.14;
double z = x / y; // z = 477.707006
Vypisovanie a načítavanie hodnôt typu double
Pri použití printf sa pre typ double používa formátovací reťazec %f a v scanf sa používa %lf.
Nasledujúci program načíta dve reálne čísla a vypíše výsledky rôznych operácií:
#include <stdio.h>
int main() {
double a, b;
printf("Zadajte dve realne cisla: ");
scanf("%lf %lf", &a, &b);
printf("%f + %f = %f\n", a, b, a + b);
printf("%f - %f = %f\n", a, b, a - b);
printf("%f * %f = %f\n", a, b, a * b);
printf("%f / %f = %f\n", a, b, a / b);
}
Príklad behu programu:
Zadajte dve realne cisla: 2.3 10
2.300000 + 10.000000 = 12.300000
2.300000 - 10.000000 = -7.700000
2.300000 * 10.000000 = 23.000000
2.300000 / 10.000000 = 0.230000
Dátový typ bool pre logické hodnoty
- Logické hodnoty môžeme reprezentovať pomocou typu
bool - V jazyku C je potrebné ho definovať pomocou knižnice
stdbool.h. - Premenné typu
boolmôžu nadobúdať iba dve hodnoty:true(pravda, 1) afalse(nepravda, 0). - Vypisujeme ich ako celé čísla pomocou
%d, načítavať ich priamo nebudeme.
#include <stdio.h>
#include <stdbool.h>
int main() {
// vytvorenie logických premenných
bool b1 = true;
bool b2 = false;
bool b3 = (1 < 2) || b2; // b3 bude true
// výpis logických hodnôt ako celých čísel
printf("b1 = %d, b2 = %d, b3 = %d\n", b1, b2, b3);
// použitie logických hodnôt v podmienke
if (b3) {
printf("b3 je pravda\n");
} else {
printf("b3 je nepravda\n");
}
}
Program vypíše:
b1 = 1, b2 = 0, b3 = 1
b3 je pravda
Cyklus for
Dôležitou časťou programovania je schopnosť opakovanie vykonávať tie
isté príkazy. Prvou možnosťou ako to robiť, je cyklus for.
Príklad 1: vypisovanie čísel od 1 po n
Nasledujúci program načíta zo vstupu číslo n a postupne vypíše
prirodzené čísla od 1 po n (pred každé dá medzeru).
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
printf(" %d", i);
}
printf("\n");
}
Tu je výstup programu pre n = 9:
1 2 3 4 5 6 7 8 9
Cyklus for vyzeral v programe takto:
for (int i = 1; i <= n; i++) {
telo cyklu
}
Táto konštrukcia pozostáva z kľúčového slova for nasledovaným
zátvorkou s troma časťami oddelenými bodkočiarkami:
- Príkaz
int i = 1vytvorí novú celočíselnú premennúia priradí jej hodnotu1. - Podmienka
i <= nurčuje dokedy sa má cyklus opakovať. V tomto prípade to má byť kým je hodnota premennejimenšia alebo rovnán. - Príkaz
i++hovorí, že po každom zopakovaní cyklu (t.j. po každej jeho iterácii) sa má hodnota premennejizvýšiť o jedna. - Medzi zloženými zátvorkami
{a}je potom tzv. telo cyklu – čiže jeden alebo viac príkazov, ktoré sa budú opakovať postupne pre rôzne hodnoty premenneji.- V príklade 1 je telom cyklu iba príkaz
printf(" %d", i);, ktorý vypíše medzeru a hodnotu premenneji.
- V príklade 1 je telom cyklu iba príkaz
Čo sa stane ak zadáme n = 0?
Príklad 2: vypisovanie čísel od 0 po n-1
Drobnou zmenou predchádzajúceho programu môžeme napríklad vypísať všetky
čísla od 0 po n-1:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf(" %d", i);
}
printf("\n");
}
Tu je výstup programu pre n = 9:
0 1 2 3 4 5 6 7 8
Ďalšie detaily o typoch int a double
Rozsah hodnôt
Premenné typu int a double zaberajú pevne daný počet bitov, preto do
nich nie je možné uložiť ľubovoľné celé alebo reálne číslo. Presný
rozsah možných hodnôt môže závisieť od kompilátora, v súčasnosti však
väčšinou platí:
- Typ
intzvyčajne zaberá 4 bajty (32 bitov) a dajú sa ním reprezentovať celé čísla z intervalu <-2 147 483 648, +2 147 483 647>. - Typ
doublezvyčajne zaberá 8 bajtov. Ním reprezentované reálne čísla sú v pamäti uložené vo forme z ⋅ a ⋅ 2b, kde z je znamienko, a je reálne číslo z intervalu <1,2) (mantisa) a b je celé číslo (exponent). Na uloženie mantisy sa používa 52 bitov a na uloženie exponentu 11 bitov. Typdoubletak možno použiť na prácu s reálnymi číslami približne v rozsahu od 10-300 po 10300 s presnosťou na 15 až 16 platných číslic. Pri tejto reprezentácii sa nevyhradzujú pevné počty bitov na reprezentáciu celej a desatinnej časti; počet cifier pred a za rádovou čiarkou je určený exponentom. Hovoríme preto o pohyblivej rádovej čiarke.
Pretypovanie
Hodnotu niektorého z typov bool, int, double je možné
skonvertovať na „zodpovedajúcu” hodnotu iného z týchto typov, tejto
operácii hovoríme pretypovanie.
- Pretypovanie
intnadouble: hodnota čísla zostáva tá istá - Pretypovanie
doublenaint: zaokrúhleniu smerom k nule (čiže nadol pri kladných číslach, nahor pri záporných), t.j. “urezanie” desatinných cifier - Pretypovanie
boolnaintalebodouble:truesa konvertuje na 1 alebo 1.0 afalsena 0 alebo 0.0 - Pretypovanie z
intalebodoublenabool: nula sa skonvertuje nafalse, ľubovoľná nenulová hodnota natrue
Pretypovanie je možné realizovať dvoma spôsobmi:
- Implicitne, napríklad priradením premennej jedného typu do premennej iného typu, alebo
- Explicitne, použitím pretypovacieho operátora:
(nazov_noveho_typu) vyraz_stareho_typu.
Možnosti pretypovania sú ilustrované nasledujúcim ukážkovým programom.
#include <stdio.h>
#include <stdbool.h>
int main() {
int n1 = 4;
double x1 = 1.234;
int n2 = x1;
printf("%d\n", n2); // Vypíše 1
x1 = n2;
printf("%f\n", x1); // Vypíše 1.000000
printf("%d %d\n", (int) 4.2, (int) -4.2); // Vypíše 4 -4
bool b1 = n1;
printf("%d %d\n", n1, (int)b1); // Vypíše 4 1
}
Celočíselné a reálne delenie
Operátor / sa na argumentoch typu int správa ako celočíselné
delenie – hodnota podielu sa zaokrúhli smerom k nule.
- Napríklad výraz
5/3má hodnotu1. - Akonáhle je však aspoň jeden operand typu
double, interpretuje sa/ako delenie reálnych čísel. - Výrazy
5.0 / 3.0,5.0 / 3,5 / 3.0a5 / (double)3teda majú všetky hodnotu1.666667.
Nasledujúci program demonštruje implicitné a explicitné pretypovanie pri delení, t.j. kedy delíme celočíselne a kedy je výsledkom reálne číslo aj s desatinnými ciframi.
#include <stdio.h>
int main() {
int a = 4;
int b = 3;
// Automaticky pretypuje cele cislo 3 na realne cislo 3.0
double d = 3;
// Celociselne delenie: 4 / 3 = 1
printf("%d\n", a / b);
// Necelociselne delenie: 4 / 3.0 = 1.333333
printf("%f\n", a / d);
// Necelociselne delenie: (1.0 * 4) / 3 = 4.0 / 3 = 1.333333
printf("%f\n", (1.0 * a) / b);
// Necelociselne delenie: 4.0 / 3 = 1.333333
printf("%f\n", ((double)a) / b);
// Do e je priradeny vysledok celociselneho delenia 4 / 3 = 1;
// po pretypovani je to rovne 1.0
double e = a / b;
// Vypise 1.000000
printf("%f\n", e);
// Vypise 0.500000, lebo 1.0 / 2 je necelociselne delenie
printf("%f\n", e / 2);
}
Priorita a asociativita operátorov
Výrazy sa vyhodnocujú v nasledujúcom poradí preferencie jednotlivých operátorov. Operátory v jednom riadku majú rovnakú prioritu a operátory vo vyššom riadku majú vyššiu prioritu, než operátory v nižších riadkoch.
++(inkrement),--(dekrement),!(logická negácia)*,/,%+,-<,>,<=,>===,!=&&(logická konjunkcia)||(logická disjunkcia)=(priradenie)
Poradie vyhodnocovania je možné meniť zátvorkami, ako napríklad vo
výraze 4*(5-3).
Uvedené operátory sa väčšinou vyhodnocujú zľava doprava (hovoríme, že sú
zľava asociatívne) – napríklad 1 - 2 - 3 sa teda vyhodnotí ako (1 -
2) - 3, t.j. -4 a nie ako 1 - (2 - 3), t.j. 2. Výnimkou sú operátory
!, ++, -- a =, ktoré sú sprava asociatívne. To umožňuje
napríklad viacnásobné priradenie a = b = c, ktoré najprv priradí
hodnotu c do b a následne hodnotu výrazu b = c – tou je nová
hodnota premennej b, čiže hodnota premennej c –, do a.
Viac sa o operátoroch v C++ možno dočítať napríklad tu.
Zhrnutie
Poznáme základné stavebné prvky, z ktorých sa dajú spraviť aj pomerne zložité programy:
- premenné typu
int,double,boola operátory, ktoré s nimi vedia počítať - podmienku
if, ktorá umožňuje vykonávať určité časti programu len za nejakých okolností - cyklus
for, ktorý umožnuje opakovať určité časti programu veľa krát
Cieľom najbližšej prednášky a cvičení je hlavne precvičiť si tieto stavebné prvky na veľa ďalších príkladoch.