Počítače a programování 1 3. přednáška
Přiřazení hodnoty proměnným (operátor přiřazení) Operátor přiřazení: ”=” se používá ke změně hodnoty proměnné Význam: ”Přiřaď hodnotu výrazu na pravé straně proměnné na levé straně” Termín l-hodnota (l-value) – vše co má adresu v paměti – nejčastěji proměnná Terminologie: česky anglicky symbolicky prakticky výraz expression výraz i * 2 + 3 přiřazení assignment l-hodnota=výraz j=i * 2 + 3 příkaz statement l-hodnota=výraz; j=i * 2 + 3; Výraz má vždy hodnotu (číselnou nebo booleovskou) Přiřazení je výraz a jeho hodnotou je hodnota přiřazená levé straně Přiřazení se stává příkazem, je-li ukončeno středníkem
Přiřazovací příkaz - příklady Různé typy přiřazovacích příkazů : j = 5; d = ’z’; f = f * 3.14 * i ; Jelikož přiřazení je výraz, smí být použito v podmínce např. int j, i = 5; if (i == ( j = 5 )) System.out.println(i); Přiřazení je výraz – je možné několikanásobné přiřazení k = j = i = 2; které se vyhodnocuje zprava doleva tedy: k = (j = (i = 2));
Konverze datových typů Rozeznáváme dva základní druhy: rozšiřující konverze – provádějí se implicitně, tj. do programu nemusíme psát operátor přetypování a kompilátor si tuto konverzi provede sám zužující konverze – operátor přetypování se musí napsat Další konverze: základní datové typy na řetězec řetězec na základní datové typy identické - nic se neprovádí konverze referencí zakázané - např. konverze reference na double nebo na void
Operátor přetypování Přetypování (konverze datových typů) se používá tehdy, máme-li k dispozici jeden datový typ a potřebujeme z něj vyrobit jiný datový typ int i=5; char c = ’A’; double d; int i = (int) c; d = (double) i; char d = (char) i; Přetypování má nejvyšší prioritu – pokud přetypováváme výraz je nutné ho uzavřít do závorek jinak se přetypuje pouze první člen výrazu (double) i + j // přetypuje se pouze i (double) (i + j) // přetypuje se celý výraz
Rozšiřující konverze Operátor přetypování není nutný, nedochází ke ztrátě informace Jedná se o konverze, kdy výsledný datový typ má větší obor hodnot (rozsah) než původní typ Rozšiřující konverze pro základní datové typy: byte --> short --> int --> long --> float --> double Význam : např. typ short lze kdykoliv bez použití operátoru převést na long, float a double, na typ byte pouze s operátorem přetypování POZOR !!!! – typ boolean není číselný datový typ a proto jej na ně nelze převést
Zužující konverze Může dojít ke změně nebo ztrátě původní hodnoty -> kompilátor vyžaduje zápis operátoru přetypování, čímž nás nutí abychom si uvědomili případné důsledky Zužující konverze pro základní datové typy : double --> float --> long --> int --> short --> byte
Aritmetické výrazy Aritmetické výrazy jsou tvořené pomocí operátorů, které mohou být : unární – pouze jeden operand (proměnná nebo konstanta) binární – operátor je zleva i zprava obklopen operandy ternární – operátor složený ze dvou znaků mezi nimiž je prostřední operand Unární operátory +, - používají se podobně jako v matematice, píší se před operand int j; int i = - 3; j = - i;
Aritmetické výrazy speciální unární operátory ++ inkrement, -- dekrement : oba operátory je možné použít jako prefix i jako suffix jako prefix : ++ l-hodnota inkrementováno před použitím Proměnná je nejprve zvětšena o jedničku a pak je tato nová hodnota vrácena jako hodnota výrazu jako suffix : l-hodnota -- inkrementováno po použití je vrácena původní hodnota proměnné a ta je pak zvětšena o jedničku int i = 5, j = 1, k; i++; // i bude 6 j = ++i; // j bude 7, i bude 7 j = i++; // j bude 7, i bude 8 k = --j + 2; // k bude 8, j bude 6, i bude 8
Aritmetické výrazy Binární operátory + sčítání - odčítání * násobení / reálné dělení - je-li alespoň jeden z operandů float popř. double / celočíselné dělení – pouze jsou-li oba operandy typu int % dělení modulo (tj. zbytek po celočíselném dělení) Při aritmetických operacích může dojít k přetečení popř. podtečení –> výsledek je pak matematicky nesprávný. !!! Pozor !!! Při přetečení/podtečení Java nehlásí žádnou chybu – kromě případu dělení nulou u celočíselných typů (ArithmeticException)
Přiřazovací operátory Základní operátor přiřazení je = Rozšířené operátory l-hodnota operátor= výraz jsou zkrácenou verzí přiřazení l-hodnota = l-hodnota operátor výraz Dají se použít následující přiřazení: l-hodnota += výraz l-hodnota |= výraz l-hodnota -= výraz l-hodnota >>= výraz l-hodnota *= výraz l-hodnota <<= výraz l-hodnota /= výraz l-hodnota >>>= výraz l-hodnota %= výraz l-hodnota &= výraz l-hodnota ^= výraz
Relační operátory Pomocí relačních operátorů se v Javě vytvářejí booleovské výrazy
Booleovské výrazy mohou nabývat hodnot true nebo false,obykle se skládají z booleovských operátorů, relačních výrazů nebo boleovských proměnných používají se většinou v testech u řídicích příkazů hodnoty booleovských výrazů mohou být přiřazeny booleovské proměnné Booleovské operátory : && logický součin se zkráceným vyhodnocovánímm || logický součet se zkráceným vyhodnocováním & logický součin s úplným vyhodnocováním | logický součet s úplným vyhodnocováním ! negace
Pravdivostní tabulky pro booleovské operátory && (and) || (or) Value of A Value of B A && B true true true true false false false true false false false false Value of A Value of B A || B true true true true false true false true true false false false Value of A !A true false false true ! (not)
Zkrácené vyhodnocení logických výrazů Operandy výrazu jsou vyhodnocovány zleva doprava a jakmile je možné určit konečný výsledek, vyhodnocování se ukončí Důvod použití – zrychlení výpočtu Použití – ve složených logických výrazech, kdy při logickém součinu – první hodnota false způsobí ukončení vyhodnocování součtu – první hodnota true způsobí ukončení vyhodnocování Př: if (y!=0 && x/y < z ) v tomto případě si nemusíme dělat starosti s prípadným dělením 0 – nedojde k němu
Zkrácené vyhodnocování - příklady i = 1; j = 2; k=3; if (i == 2 && ++j == 3) k = 4; System.out.println(”i = ”+ i + ”, j= ”+ j + ”, k = ”+ k); Vypíše: i = 1, j = 2, k = 3 Protože i==2 je false, nedochází k vyhodnocení výrazu ++j a hodnota j tedy zůstává 2 if (i == 1 || ++j == 2) Vypíše: i = 1, j = 2, k = 4 Protože i==1 je true, nedochází k vyhodnocení výrazu ++j a hodnota j tedy
Úplné vyhodnocení logických součtů a součinů Při úplném vyhodnocení se provádí vyhodnocení všech částí booleovského výrazu bez ohledu na pravdivost dílčích členů výrazu Operátory pro úplné vyhodnocení: logický součin & logický součet | Příklad: i = 1; j = 2; k=3; if (i == 2 & ++j == 3) k = 4; System.out.println(”i = ”+ i + ”, j= ”+ j + ”, k = ”+ k); Vypíše: i = 1, j = 3, k = 3 přestože i==2 je false, dojde k vyhodnocení výrazu ++j a hodnota j se tedy změní na 3
Terminálový vstup a výstup V Javě se téměř nepoužívá, použití je omezeno na cvičné a zkušební příklady Důvody proč se nepoužívá : Java umožňuje používat GUI (grafická uživatelská rozhranní), která jsou ve skutečných programech vhodnější Program s terminálovým I/O není čistá Java –některé OS (např. MAC OS) nemají vůbec terminálový V/V Pokud terminálový vstup/výstup použijeme je nutné importovat balík java.io příkazem import java.io.*; // středník je nutný !!
Vyhodnocování výrazů Vyrazy v Javě se vyhodnocují vždy zleva do prava s ohledem na prioritu operátorů Priorita operátorů Nejvyšší priorita unární operátory: +, -, ++, --, a ! binarní arithmetické operatory: *, /, % binarní arithmetické operatory: +, - booleovské operátory: <, >, =<, >= booleovské operátory: ==, != booleovský operátor: & booleovský operátor: | booleovský operátor: && booleovský operátor: || Nejnižší priorita
Formátovaný výstup Formátovaný výstup: metoda System.out.print() popř. System.out.println() Funkce: metoda převede proměnnou, která je jejím parametrem na řetězec představující dekadickou hodnotu proměnné a tento řetězec vytiskne Příklady: System.out.print(” Toto je hodnota i ” + i + ” a toto j: ”+j); i=4; j=7; System.out.print(” Soucet je ” + i + j); Vypíše: Soucet je 11 System.out.println(” Soucet je ”+(i + j)+ ”\tSoucin je ”+(i*j)); Vypíše: Soucet je 11 Soucin je 28 a odřádkuje
Formátovaný vstup Java nepodporuje formátovaný vstup žádnou knihovní metodou inverzní k print() . Je ale možné si tuto metodu vyrobit (viz cvičení ) popř. doporučená lit. Přiklad metody pro vstup celého čísla import java.io.*; public class VstupData { public static int ctiInt() { // Z1 byte[] pole = new byte[20]; String nacteno; int i; try { System.in.read(pole); nacteno = new String(pole).trim(); i=Integer.valueOf(nacteno).intValue(); // Z2 return i; }
Formátovaný vstup catch (IOException e) { System.out.println(”Chybne nactene cislo !”); return 0; } Pro vstup čísle typu float a double je možné předchozí metodu modifikovat Např. pro typ double budou změny následující Z1 : public static double ctiDouble() Z2 : d=Double.valueOf(nacteno).doubleValue
Větvení Cykly Metoda exit(n) Datový typ Boolean, booleovské výrazy Řídicí struktury Větvení Cykly Metoda exit(n) Datový typ Boolean, booleovské výrazy
Co jsou řídicí struktury Řídicí struktury určují v jakém pořadí se budou provádět jednotlivé příkazy programovacího jazyka – standardně se provádí sekvenční zpracování, řídicí struktury toto pořadí mění Každý program se obvykle skládá z následujících elementů: 1. Sekvence – pokračuje se prováděním další instrukce 2. Selekce – volba jedné ze dvou (popř. několika) variant 3. Opakování – cyklus (opakování části kódu)
Řídicí příkazy jazyka Java Větvení (selekce): if if-else if-else if-else if- … - else switch Cyklus while do-while for Sekvence implicitní Java automaticky provádí následující instrukci pokud nenarazí na příkaz cyklu, větvení nebo násilného ukončení programu
Příkaz if Jednoduchý výběr ze dvou variant (neúplný podmiňovací příkaz) Pokud je podmínka (booleovský výraz) splněna pokračuje se následujícím příkazem, jinak se tento příkaz přeskočí Syntaxe: if (Boolean_Expression) // závorky jsou nezbytné příkaz; //provádí se při splněné podmínce další příkaz; //provede se pokaždé V závorkách musí být booleovský výraz jehož hodnotou je buď true nebo false (pozor změna oproti C/C++ kde to mohl být integer výraz Za if může být pouze jediný příkaz (může jich být více ale provede se pouze jeden) nebo složený příkaz ( blok příkazů ohraničený závorkami { } )
if Example If (i>3) { j=5; i=7; } // žádný středník Doporučení : z hlediska čitelnosti je vhodné dávat do složených závorek i jediný příkaz Pokud je to možné uvádějte podmínky v testu v aserci (kladné znění tvrzení) a ne v negaci – je to pak čitelnější Nevhodné: if(!( c==’a’ || c==’b’ || c==’c’)) Lepší: if( c!=’a’ && c!=’b’ && c!=’c’))
Úplná podmínka if-else Výběr jedné ze dvou možností Povádí se buď příkaz1 nebo příkaz2 v závislosti na hodnotě booleovského výrazu Syntaxe: if (Boolean_Expression) { Příkaz1 //execute only if true } else Příkaz2 //execute only if false Příkaz3 // always executed test Příkaz 1 Příkaz 2 Příkaz 3
if-else - příklady Příklad bloku s jediným příkazem if(time < limit) System.out.println(”You made it.”); else System.out.println(”You missed the deadline.”); Příklad bloku se složeným příkazem { bonus = 100; } bonus = 0;
Vícenásobné větvení: if-else if-else if-…-else Jeden ze způsobů jak je možné vícenásobně větvit program Syntaxe: if(Boolean_Expression_1) Příkaz_1 else if(Boolean_Expression_2) Příkaz_2 . else if(Boolean_Expression_n) Příkaz_n else Default_Action test1 Příkaz_1 test2 Příkaz_2 test3 Příkaz_n Default
if-else if-else if-…-else Example if(score >= 90) grade = ’A’); else if (score >= 80) grade = ’B’; else if (score >= 70) grade = ’C’; else if (score >= 60) grade = ’D’; else grade = ’E’;
Podmíněný výraz - ternární operátor Syntaxe : booleovský_výraz ? výraz_1 : výraz_2 Význam je podobný jako if (booleovský_výraz) výraz_1; else výraz_2; Rozdíl je v tom že se nejedná o příkaz, ale o výraz, který předává hodnotu. Ternální operátor může být použit i samostatně a ne pouze v přiřazovacím příkazu (viz příklad)
Vícenásobné větvení : switch Další možnost jak provádět vícenásobné větvení (alternativa k else if ) Výraz musí být char, int, short or byte Výraz a Case_Label musí být stejného typu počet větví (větev začíná case) není omezen v každé větvi může být více příkazů, které není nutno uzavírat do složených závorek lze použít větev default, která se provádí, když žádná z větví case nevyhovuje Pokus se příkaz break vynechá pokračuje se příkazy z následující větve case
Vícenásobné větvení : switch switch(Výraz) { case Case_Label: příkazy … break; default: } Může být libovolný počet větví. break může být vynechán – provádí se následující příkazy Default je volitelný – nemusí být použit
switch Example switch(seatLocationCode) { case 1: System.out.println(”Orchestra”); price = 40.00; break; case 2: System.out.println(”Mezzanine”); price = 30.00; case 3: System.out.println(”Balcony”); price = 15.00; default: System.out.println(”Unknown seat code”); }
Iterační příkazy: Cykly Používají se k opakování určité části programu, obvykle se skládají ze tří částí inicializace řídicích proměnných cyklu (nemusí být součástí příkazu cyklu) tělo cyklu podmínka ukončení cyklu Java používá 3 příkazy cyklu while do-while for
Cyklus while Syntaxe: while(Boolean_Expression) { //tělo cyklu První_příkaz; ... Poslední_příkaz; } tělo cyklu se opakovaně provádí pokud má Boolean_Expression hodnotu true podmínka se testuje před vstupem do cyklu –> tělo cyklu nemusí být provedeno ani jednou . uvnitř těla by měl být příkaz který změní Boolean_Expression na false – jinak bude cyklus nekonečný podmínka tělo cyklu
while : Příklad 1- cyklus s daným počtem opakování Cyklus sečte 10 čísel zadaných uživatelem int next; // Inicializace cyklu int count = 1; int total =0; while(count <= 10) //Podmínka ukončení { //Body of loop next = VstupData.ctiInt(); total = total + next; count++; //čítač počtu průchodů }
while: Příklad 2 : ukončení hodnotou zadanou ze vstupu Cyklus sčítá kladná čísla zadaná uživatelem Cyklus končí zadá-li uživatel záporné číslo //Initializace int next = 0; int total = 0; while(next >= 0) // Podmínka ukončení { //Tělo cyklu total = total + next; next = VstupData. ctiInt(); }
while: Příklad 2 : ukončení hodnotou zadanou ze vstupu Jelikož je vstupní hodnota čtená před podmínkou vstupu do cyklu nemusí se cyklus vůbec provést. (je-li vstup záporný ) //Initialization int next; int total = 0; next = VstupData.ctiInt(); while(next >= 0)//Podmínka ukončení { //Body total = total + next; }
Cyklus do-while Syntaxe do { //tělo cyklu první_příkaz; ... poslední_příkaz; } while(Boolean_Expression); tělo cyklu se opakovaně provádí pokud má Boolean_Expression hodnotu true test ukončení cyklu se provádí na konci ® tělo cyklu se provede nejméně jedenkrát. uvnitř těla by měl být příkaz který změní Boolean_Expression na false – jinak bude cyklus nekonečný tělo cyklu podmínka
do-while: Příklad int count = 1; int number = 10; do //Tiskne čísla 1 – 10 na jedné řádce { System.out.print(count + ”, ” ); count++; }while(count <= number);
while: Příklad 2 : ukončení hodnotou zadanou ze vstupu Cyklus sčítá kladná čísla zadaná uživatelem Cyklus končí zadá-li uživatel záporné číslo //Initializace int next = 0; int total = 0; do { //Tělo cyklu next = VstupData. ctiInt(); if (next>0) total = total + next; } while(next >= 0) // Podmínka ukončení
Cyklus for Používá se v případech kdy předem známe omezující kritéria - počáteční nastavení, ukončující podmínku a způsob ovlivnění řídicí proměnné Syntaxe: for(výraz_start; výraz_iter;výraz_iter) tělo cyklu;
Cyklus for for(výraz_start; výraz_stop ; výraz_iter) tělo cyklu; Význam jednotlivých částí příkazu for : 1. výraz_start – provede se pouze jednou před vstupem do cyklu 2. výraz_stop – musí to být booleovský výraz – pokud je hodnota true provádí se tělo cyklu 3. výraz_iter – provádí se po ukončení těla cyklu – měl by po určité době změnit hodnotu podmínky výraz_stop na false
Cyklus for Doporučení : Používat pouze jednu řídicí proměnnou inicializovanou v inicializační části ( výraz_start ) Řídicí proměnná má být ovlivňována pouze v části určené pro změnu rídicí proměnné (výraz_iter ) a ne v těle cyklu Pokud má for cyklus prázdné tělo měl by být středník ukončující prázdný příkaz na nové řádce Inicializace cyklu výraz_start Test výraz_stop Tělo cyklu Změna řídicí proměnné cyklu výraz_iter
For cyklus : Příklad Odpočítávání od 9 do 0 for(int count = 9; count >= 0; count--) { System.out.print(”T = ” + count); System.out.println(” and counting”); } System.out.println(”Blast off!”);
for : Příklad 1- cyklus s daným počtem opakování Cyklus sečte 10 čísel zadaných uživatelem int next; for (count=1; count <=10 ; count++) { // tělo cyklu next = VstupData.ctiInt(); total = total + next; }
Příkazy break a continue Lze je použít u všech cyklů, oba příkazy mění nějakým způsobem ”normální” průběh cyklu break ukončuje nejvnitřnější neuzavřenou smyčku - opouští ihned cyklus continue skáče na konec nejvnitřnější neuzavřené smyčky (tj. přeskočí zbytek těla cyklu) a tím vynutí další iteraci smyčky – cyklus neopouští Oba příkazy mají i verze s návěštím , tj. break náveští – ukončuje cyklus s návěštím continue návěští – vynucuje další obrátku cyklu s návěštím
break: příklad public class pbreak { public static void main(String[] inp) { System.out.print("Zacatek"); odskok: { for (int i=1; i< 10; i++ ){ if (i==5) break odskok; // break; System.out.print(i+" "); } System.out.print("Stred "); System.out.println(„Konec !!!! "); Vypíše: Začátek 1 2 3 4 Konec !!!! - pro break odskok Začátek 1 2 3 4 Stred Konec !!!! - pro break
continue: příklad public class pnavest { public static void main(String[] inp) { navesti: for (int n=0; n< 4; n++ ){ for (int m=0; m<3; m++) { if (n==2 && m==1 ) continue navesti; // continue; System.out.print(n+"-"+m+" "); } Vypíše : 0-0 0-1 0-2 1-0 1-1 1-2 2-0 3-0 3-1 3-2 – pro continue navesti 0-0 0-1 0-2 1-0 1-1 1-2 2-0 2-2 3-0 3-1 3-2 – pro continue
metoda exit Pokud během tvorby programu vyskytne situace, kdy je zbytečné aby program dále pokračoval (např. zadání chybných parametrů, nedostatek paměti apod.) je možné ho ukončit voláním metody exit(n) Parametr n se často používá k určení zda byl program ukončen normálně nebo ne n je obvykle 0 pro normalní ukončení programu a různé od nuly pro ukončení v důsledku chyby
exit : Příklad použití metody System.out.println(”Enter e to exit or c to continue”); char userIn = VstupData.ctiZnak(); if(userIn == ’e’) System.exit(0); else if(userIn == ’c’) { //příkazy pro další zpracování } else System.out.println(”Invalid entry”); //příkazy pro zpracování nevhodně zadaného parametru