Programovanie (2) v Jave
1-INF-166, letný semester 2023/24

Prednášky · Pravidlá · Softvér · Testovač
· Vyučujúcich predmetu možno kontaktovať mailom na adresách uvedených na hlavnej stránke. Hromadná mailová adresa zo zimného semestra v letnom semestri nefunguje.
· JavaFX: cesta k adresáru lib je v počítačových učebniach /usr/share/openjfx/lib.


Prednáška 2: Rozdiel medzi revíziami

Z Programovanie
Skočit na navigaci Skočit na vyhledávání
Riadok 281: Riadok 281:
 
using namespace std;
 
using namespace std;
  
int main(void) {
+
int main() {
 
     int x;
 
     int x;
 
     cout << "Please enter some number: ";
 
     cout << "Please enter some number: ";

Verzia zo dňa a času 20:26, 22. september 2020

Oznamy

Opakovanie ako fungujú cvičenia:

  • Na začiatku cvičení v utorok sa na testovači objaví nová sada úloh
  • Prvá úloha je rozcvička, treba ju odovzdať do konca cvičenia, začnite teda touto úlohou
  • Zvyšok cvičenia riešte ďalšie úlohy
  • Čo nestihnete na cvičení, môžete dokončiť doma alebo na doplnkových cvičeniach v piatok, termín odovzdania je začiatok cvičenia ďalší utorok
    • Úlohy sa dajú odovzdávať aj po termíne, ale nedostanete za ne body, ak sme vám neudelili výnimku
  • V piatok príďte na cvičenia, ak vám zostalo veľa príkladov z utorka alebo sa vám zdajú ťažké, takže sa vám zíde pomoc. Tiež ak máte otázky k učivu všeobecne.
  • Obvykle nebudú cvičenia predbiehať prednášky, výnimka bola tento týždeň (príklady 4-6)
  • 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.
  • Body za prvé cvičenia sa objavia na testovači koncom budúceho týždňa, ale zväčša dostanete body za všetky príklady, kde testovač dal OK.

Cvičenia cez MS Teams

  • Ak by ste sa zo zdravotných dôvodov nemohli zúčastniť cvičení osobne, môžete sa zúčastniť online cez MS Teams, návod tu
  • Zatiaľ plánujeme cvičenia cez MS Teams sprístupniť tento piatok a budúci utorok, o ďalšom postupe vás budeme informovať

Najbližšie dni na programovaní

  • Dnes prednáška, ďalšie dve prednášky budúci týždeň
  • Dnes nepovinný test pre pokročilých (ak ste sa prihlásili)
  • Doplnkové cvičenia v piatok
  • Budúci utorok ďalšie cvičenia s ďalšou sadou úloh (k prednáške dnes a v pondelok)
  • Niektorí ste vyriešili všetky príklady na tento týždeň, pokúsime sa do piatku zverejniť aj pár úloh z budúceho týždňa, aby ste tí, čo ste pokročilejší, si ich mohli spraviť vopred. Neskôr už ale toto robiť nebudeme pre organizačnú náročnosť. Rozcvička na budúci týždeň sa objaví až na cvičeniach

Technické záležitosti

  • Na stránke Softvér nájdete príklady ďalších programov, ktoré môžete použiť namiesto Kate.
  • Ak sa vám páči Kate, prečítajte si časť o Kate a práci na príkazovom riadku. Vo Windows si môžete nainštalovať podobný editor, napr. Notepad++.
  • Ak by ste chceli viac klikacie prostredie, môžete skúsiť napríklad program Netbeans, dá sa použiť aj na skúške a možno ho budeme používať budúci semester. Mal by sa dať nainštalovať aj vo Windows.
  • Na svojom počítači máte širokú paletu možností, v čom programovať, aspoň občas ale skúste použiť Linux na cvičeniach, aby ste vedeli robiť skúšku (Kate alebo Netbeans alebo iné nástroje, nie však internetové prostredia).

Ďalšie upozornenia k štúdiu:

  • V rozvrhu http://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 4.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é a povinne voliteľné predmety by ste si mali zapísať, z výberových si môžete vybrať
  • Pozor na to, aby ste získali aspoň 20 kreditov za zimný semester.
  • Z angličtiny je povinná Angličtina 4 v letnom semestri (väčšinou prvý alebo druhý ročník), ostatné sú výberové s cieľom pripraviť sa na Angličtinu 4.
  • Bioinformatikom pripomíname možnosť prestupu na konverzné štúdium, ak by sa vám učilo v prých týždňoch zdalo príliš ťažké.

Opakovanie

Doteraz sme videli:

  • Načítavanie pomocou cin, výpis pomocou cout.
  • Celočíselné premenné typu int.
#include <iostream>
using namespace std;

int main() {
    int x, y;

    cout << "Please enter the first number: ";
    cin >> x;
    cout << "Please enter the second number: ";
    cin >> y;

    int result = x + y;
    cout << x << "+" << y << "=" << result << endl;
}

Komentáre

Do zdrojových kódov programov v jazykoch C a 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 <iostream>
using namespace std;

/* Tento program od pouzivatela nacita dve cele cisla
 * a vypise ich sucet. */

int main() {
    // vytvorime premenne x a y
    int x, y;

    // do premennych od pouzivatela nacitame cisla
    cout << "Please enter the first number: ";
    cin >> x;
    cout << "Please enter the second number: ";
    cin >> y;

    // do novej premennej result spocitame vysledok
    int result = x + y;
    // vysledok vypiseme
    cout << x << "+" << y << "=" << result << endl;
}

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 <iostream>
using namespace std;

int main(void) {
    int x;
    cout << "Zadajte cislo: ";
    cin >> x;

    if (x < 0) {
        cout << "Cislo " << x << " je zaporne." << endl;
    } else {
        cout << "Cislo " << x << " je nezaporne." << endl;
    }
}
  • Tu je príklad dvoch behov programu:
Zadajte cislo: 10
Cislo 10 je nezaporne.
Zadajte cislo: -3
Cislo -3 je zaporne.
  • Ako vidíme, za príkazom if je zátvorka s podmienkou. V našom príklade podmienka je x < 0.
  • Ak je podmienka v zátvorke splnená (t.j. ak x je menšie ako nula), vykonáme príkazy v zloženej zátvorke za príkazom if.
  • Ak podmienka nie je splnená (t.j. ak je x väčšie alebo rovné nule), vykonáme príkazy v zloženej zátvorke za slovom else
  • Časť else {...} je možné vynechať, ak nechceme vykonávať žiadne príkazy.
  • Ak za if alebo else nasleduje 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čenie:

  • 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ť.

Dátové typy int, double a bool

Na začiatok budeme pracovať s troma dátovými typmi:

  • typ int pre celé čísla – príkladmi konštánt typu int1, 42, -2, alebo 0.
  • typ double pre reálne čísla – príkladmi konštánt typu double4.2, -3.0, 3.14159, alebo 1.5e3 (1.5e3 je tzv. semilogaritmický zápis znamenajúci 1,5 ⋅ 103, t.j. 1500).
  • typ bool pre logické hodnoty – jedinými konštantami sú true (ekvivalentná číselnej hodnote 1) a false (ekvivalentná číselnej hodnote 0).

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 int zvyč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 double zvyč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. Typ double tak možno použiť na prácu s reálnymi číslami približne v rozsahu od 10-300 po 10^{300} 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 ľubovoľného ďalšieho z týchto typov. V takom prípade hovoríme o pretypovaní. Platí pritom nasledujúce:

  • Konverzia z „menej všeobecného” typu na „všeobecnejší” sa správa očakávateľným spôsobom. Booleovské hodnoty false resp. true sa konvertujú na celé čísla 0 resp. 1, prípadne na reálne čísla 0.0 resp, 1.0; celé číslo sa tiež konvertuje na reálne číslo, ktoré je mu rovné.
  • Konverzia zo „všeobecnejšieho” typu na „menej všeobecný” dodržiava určité vopred stanovené pravidlá. Napríklad pri konverzii z int alebo double na bool sa ľubovoľná nenulová hodnota skonvertuje na true a nula sa skonvertuje na false. Pri konverzii z double na int dôjde k zaokrúhleniu smerom k nule (čiže nadol pri kladných číslach, nahor pri záporných).

Pretypovanie je možné realizovať dvoma spôsobmi:

  • Implicitne, napríklad priradením premennej jedného typu do premennej iného typu, alebo použitím premennej jedného typu v kontexte, kde sa očakáva premenná druhého typu.
  • 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 <iostream>
using namespace std;

int main() {
  bool b1 = true;
  int n1 = 4;
  double x1 = 1.234;

  bool b2;
  int n2;
  
  b2 = n1; // b2 = 1
  n2 = x1; // n2 = 1 
  cout << b2 << " " << n2 << endl; // Vypise 1 1
  
  x1 = n2; // x1 = 1.0
  cout << x1 << endl; // Vypise 1
  
  cout << (bool) 7 << " " << (bool) 0 << endl; // Vypise 1 0 
  cout << (int) 4.2 << " " << (int) -4.2 << endl; // Vypise 4 -4
  
}

Aritmetické operátory a výrazy

Na typoch int aj double sa dajú robiť základné aritmetické operácie

  • sčítanie +
  • odčítanie -
  • násobenie *
  • 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/3 má hodnotu 1.
  • 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.0 a 5/(double)3 teda majú všetky hodnotu 1.66667.
#include <iostream>
using namespace std;

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
    cout << a / b << endl; 
    // Necelociselne delenie: 4 / 3.0 = 1.33333
    cout << a / d << endl; 
    // Necelociselne delenie: (1.0 * 4) / 3 = 4.0 / 3 = 1.33333
    cout << (1.0 * a) / b << endl; 
    // Necelociselne delenie: 3.0 / 4 = 1.33333 
    cout << ((double)a) / b << endl; 
    
    // Do e je priradeny vysledok celociselneho delenia 4 / 3 = 1; 
    // po pretypovani je to rovne 1.0
    double e = a / b; 
    // Vypise 1
    cout << e << endl; 
    // Vypise 0.5, lebo 1.0 / 2 je necelociselne delenie  
    cout << e / 2 << endl; 
}
  • Na celých číslach je definovaný operátor %, ktorého výstupom je zvyšok po celočíselnom delení (modulo). Napríklad výraz 5%3 má hodnotu 2.
  • Ďalšie matematické operácie a funkcie vyžadujú #include <cmath> (pre jazyk C++) v hlavičke programu:
    • Napríklad cos(x), sin(x), tan(x) (tangens), acos(x) (arkus kosínus), exp(x) (ex), log(x) (prirodzený logaritmus), pow(x,y) (xy), sqrt(x) (odmocnina), abs(x) (absolútna hodnota), floor(x) (dolná celá časť), ...
    • Viac detailov možno nájsť v dokumentácii.

Relačné operátory

Hodnoty typov int, double a bool 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 alebo false.

Logické operátory a výrazy

Na výrazoch typu bool sú definované logické operátory, ktoré sa správajú rovnako ako logické spojky známe z výrokovej logiky:

  • || pre disjunkciu (or, alebo);
  • && pre konjunkciu (and, a súčasne);
  • ! pre negáciu (not, opak)

Logickým výrazom je napríklad !((x >= 2) && (x <= 4)) alebo !true.

Operátory priradenia, inkrementu a dekrementu

Operátor priradenia premenna = hodnota už poznáme. Často realizovanou 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ď.

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.

Viac o podmienkach

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 <iostream>
using namespace std;

int main() {
    int x;
    cout << "Please enter some number: ";
    cin >> x;

    if (x == 0) {
        cout << "Zero" << endl;
    } else {
        if (x > 0) {
            cout << "Positive" << endl;
        } else {
            cout << "Negative" << endl;
        }
    }

}

Logické výrazy môžu byť efektívnym nástrojom na elimináciu množstva vnorených podmienok: napríklad konštrukcia typu

if (a == 0) {
    if (b == 0) {
        čokoľvek
    }
}

je ekvivalentná konštrukcii

if (a == 0 && b == 0) {
    čokoľvek
}

Upozornenie

Častou chybou je použitie priradenia namiesto porovnania. Nasledujúci kúsok programu do premennej x priradí nulu, ktorá sa premení na false pre účely vyhodnotenia podmienky.

if (x=0) cout << Null << endl;


Ďalšia bežná chyba je zabudnutie zložených zátvoriek

if (x==0) cout << Null; cout << endl;

Tento program vykoná cout << endl 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) { cout << Null; cout << endl; }

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

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 <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cout << " " << i;
    }
    cout << endl;
}

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 = 1 vytvorí novú celočíselnú premennú i a priradí jej hodnotu 1.
  • Podmienka i <= n určuje dokedy sa má cyklus opakovať. V tomto prípade to má byť kým je hodnota premennej i menš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 premennej i zvýš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 premennej i.

V príklade 1 je telom cyklu iba príkaz cout << " " << i;, ktorý vypíše medzeru a hodnotu premennej i.

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 <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cout << " " << i;
    }
    cout << endl;
}

Tu je výstup programu pre n = 9:

 0 1 2 3 4 5 6 7 8

Príklad 3: výpočet faktoriálu

Nasledujúci program si od používateľa vypýta číslo n a vypočíta n!, t.j. súčin celých čísel od 1 po n.

#include <iostream>
using namespace std;

int main() {
    int n;
    
    cout << "Zadajte n: ";
    cin >> n;
    
    int vysledok = 1;
    for (int i = 1; i <= n; i++) {
       vysledok = vysledok * i;
    }
    
    cout << n << "! = " << vysledok << endl;
}

Príklad behu programu pre n=4 (1*2*3*4=24):

Zadajte n: 4
4! = 24
  • Program používa premennú vysledok, ktorú na začiatku inicializuje hodnotou 1 a postupne ju násobí číslami 1, 2, ..., n.
  • Riadok vysledok = vysledok * i; zoberie pôvodnú hodnotu premennej vysledok, vynásobí ju hodnotou premennej i (t.j. jedným z čísel 1, 2, ..., n) a výsledok uloží naspäť do premennej vysledok (prepíše pôvodnú hodnotu). To isté sa dá napísať ako vysledok *= i;

Funkcia n! však veľmi rýchlo rastie a už pre n=13 sa výsledok nezmestí do premennej typu int. Dostávame nezmyselné hodnoty:

12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184
17! = -288522240

Správne hodnoty (ktoré možno získať zmenou typu premennej vysledok na long long int) sú:

12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000


Cvičenie: rozšírte program tak, aby okrem výpisu výsledku aj rozpísal faktoriál ako súčin:

Zadajte n: 4
4! = 1*2*3*4 = 24

Zhrnutie

Poznáme základné stavebné prvky, z ktorých sa dajú spraviť aj pomerne zložité programy:

  • premenné typu int, double, bool a 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.