Cílem cvičení je seznámit se se způsoby zápisu cyklů a procvičit si zpracování posloupnosti hodnot. Dále pak rozvinout dovednosti programování a kompilace programu z příkazové řádky, zadávání vstupních argumentů programu a přesměrováním standardního vstupu a výstupu programu z/do souboru.
Výchozí projekt obsahuje rozšířenou implementaci třídy TextIO z minulého cvičení, která nově zapouzdřuje volání metody třídy Scanner
pro načítání celého řádku ze standardního vstupu. Při vytvoření nové instance třídy TextIO
dojde také k vytvoření instance třídy Scanner
, která je rovnou napojena na standardní vstup System.in
. Výchozí projekt si stáhněte z archívu: pr1-lab06.zip. Struktura zdrojových kódu je podobná projektům předchozích cvičení i zde je hlavní třída Start
, ze které je volána metoda start
třídy Lab06
. V metodě start
je však nově implementováno zpracování prvního vstupního argumentu, který určí jaká čast programu bude po spuštění vykonána. Všiměte si, že pokud není zadán žádný argument volá se příslušná část programu odpovídající hodnotě konstantní proměnné DEFAULT_PART
. Pro tento účel je využito ternárního operátoru:
final int DEFAULT_PART = 2; int part = (args.length > 0 && TextIO.isInteger(args[0]) ? Integer.parseInt(args[0]) : DEFAULT_PART);
for (inicializace; podmínka; změna) { tělo cyklu }
for
cyklu se provede pouze před prvním provedením těla cyklu.
cyklus vypíše prvních deset násobků čísla i
.
int i = 3; for (int k=1; k<=10; k++) { int j = i * k; System.out.print(j + ", "); }
while(podmínka) { tělo cyklu }
Nejprve se otestuje platnost podmínky. Je-li splněna, provede se tělo cyklu a poté se opět otestuje platnost podmínky. V případě nesplnění podmínky při prvním testování, neproběhne tělo cyklu ani jednou.
Cyklus vypíše násobky čísla i až do hodnoty menší než 100.
int i = 5, j = 0; while (j < 100) { System.out.print(j + ", "); j += i; }
do { tělo cyklu } while (podmínka);
Co dělá následující kód?
java.util.Scanner in = new java.util.Scanner(System.in); int a; do { a = in.nextInt(); suma += a; if (a!=0) { soucet++; } } while (a!=0);
break
ukončí provádění cyklu a pokračuje zpracováním kódu za tělem cyklu.
for (int i=1; i<4; i++) { for (int j=1; j<4; j++) { if (i==2 && j==2) { break; } System.out.println(j + " "); } }bude posloupnost
1 2 3 1 1 2 3
for (int i=1; i<4; i++) { for (int j=1; j<4; j++) { if (i==2 && j==2) { continue; } System.out.print(j + " "); } }bude posloupnost
1 2 3 1 3 1 2 3
Kromě kompilace a spuštění programu ve vývojovém prostředí je součástí standarního vývojářského balíku Java SDK také kompilátor a vlastní virtuální stroj JVM (Java Virtual Machine). Přestože při vývoji je zpravidla pohodlnější využít jak pro kompilaci tak pro spouštění programu vývojového prostředí (např. Netbeans) jsou situace, kdy je výhodnější sestavovat program přímo příkazem. Takové případy jsou například servery automatické kompilace a ověřování zdrojového kódu, u kterého při vývoji ve více členém týmu probíhají modifikace na různých částech a jedním z hlavním problémů je integrace a správné provázání jednotlivých částí. Předklad zdrojového kódu pak probíha kontinuálně tak jak jsou přidávány do projektu nové funkcionality a je vhodné celý proces automatizovat. Právě v takových situací jsou využívány nástroje pro řízení překladu a jedním z nich je systém Apache Ant ( http://ant.apache.org/ ). Ten vyniká jednoduchou syntax zápisu pravidel překladu http://www.root.cz/clanky/ant-nebojte-se-mravence/ a lze jej považovat za de facto standard pro překlad Java projektů. Rovněž vývojové prostředí Netbeans využívá tento systém pro překlad projektů.
Postup sestavení projektu je zapisovám v XML souboru build.xml
a ukázku takového souboru můžete najít v poskytovaných projektech na jednotlivá cvičení. Pro naše účely vystačíme se základním použitím a vyjdeme právě z dodaného souboru. Předtím si však připomene sestavení programu kompilátorem javac. Nechť aktuální pracovní adresář obsahuje zdrojové kódy poskytnutého projektu pr1-lab06
. Překlad jednolivých souborů lze provést příkazy
--- Výpis obsahu adresáře zdrojových souborů v balíčku cz.cvut.fel.pr1 ls src/cz/cvut/fel/pr1 Lab06.java Start.java TextIO.java --- Překlad souborů javac src/cz/cvut/fel/pr1/TextIO.java javac -classpath src src/cz/cvut/fel/pr1/Start.java javac -classpath src src/cz/cvut/fel/pr1/Lab06.java --- Výpis obsahu adresáře, nově se zkompilovanými soubory .class ls src/cz/cvut/fel/pr1 Lab06.class Lab06.java Start.class Start.java TextIO.class TextIO.java
Všiměte si, že pro překlad tříd Start
a Lab06
je nutné specifikovat dodatečnou cestu, kde má kompilátor hledat závislosti, neboť tyto třídy využívají naši novou třídu TextIO
, která není standardní součástí Java SDK. Proto specifikujme cestu k balíku přepínačem -classpath
(zkráceně -cp
) s jedním argumentem.
Spuštění programu (přeloženého bytekódu) provedeme příkazem java
, kde je nutné uvést plné jméno třídy, tj. včetně jména balíku, ve kterém se třída nalézá. Jméno balíku je uvedeno ve zdrojového souboru za klíčovým slovem package
. V našem případě spouštíme třídu Start
z balíku cz.cvut.fel.pr1
:
--- Spuštění třídy Start a výstup programu pro část part1() java -classpath src cz.cvut.fel.pr1.Start i: 00 - value 0.00 i: 01 - value 0.10 i: 02 - value 0.20 i: 03 - value 0.30 i: 04 - value 0.40 i: 05 - value 0.50 i: 06 - value 0.60 i: 07 - value 0.70 i: 08 - value 0.80 i: 09 - value 0.90V tomto případě specifikujeme cestu, kde má JVM hledat třídy přepínačem -
classpath
(-cp
) s uvedením cesty k adresářové struktuře, tj. kde jsou uloženy zkombilované třídy (.class).
Tento způsob překladu však není příliš komfortní a použitelný je jen pro velmi malé projekty. Nicméně sofistikvanější nástroje nakonec nedělají nic jiného, než že generují takováto individuální volání překladače javac
.
V naše případě využijeme pro sestavení projektu příkaz ant
, který v základní konfiguraci hledá soubor buidl.xml
v aktuálním pracovním adresáři. Po načtení souboru s definicí překladu spustí překlad pro definovaný cíl, který je možné specifikovat prvním argumentem. Pro jednoduchost využijeme cíl jar
, který nejen že přeloží příslušné zdrojové soubory projektu, ale také vytvoří archív (zip) přeložených souboru spolu s označením hlavní spustitelné třídy v balíku (v takzvaném manifestu1).
--- Příklad výpisu při sestavení projektu příkazem ant ant jar Buildfile: build.xml build: [echo] Build Example [mkdir] Created dir: build [javac] Compiling 3 source files to build jar: [jar] Updating jar: dist/lab06.jar BUILD SUCCESSFUL Total time: 2 seconds
Všiměte si, že přeložené třídy .class jsou uloženy v adresáři build
a výsledný jar balík je pak umístěn v adresáři dist
. Nyní můžeme program spustit přímo z jar:
--- Výpis přeložení souborů ls build/cz/cvut/fel/pr1 Lab06.class Start.class TextIO.class --- Výpis vytvořeného distribučního balíku ls dist lab06.jar --- Spuštění balíku java -jar dist/lab06.jar i: 00 - value 0.00 i: 01 - value 0.10 ...
Výhodou výtvořeného balíku je snadné spuštění což v kombinaci s přenositelností Java byte kódu umožňuje jednoduše zkopírovat balík lab06.jar
na jiný počítač a spustit jej, je-li vybaven instalací JVM.
ant
mocným nástrojem a dobře použitelný pro řadu projektů, v současné době je spíše používán jeho následovník Maven
http://maven.apache.org/. Ten představuje moderní nástroj a jeho syntax je však o něco složitější a vyžaduje hlubší nastudování problematiky. To je však odměněno jeho bohatými možnostmi.
Nejdříve se seznamte s výpisem deseti hodnot v části part1
(). Program modifikujte tak, aby vypsal čísla od deseti do jedné.
--- Příklad očekávaného výstupu programu i: 10 - value 1.00 i: 09 - value 0.90 i: 08 - value 0.80 i: 07 - value 0.70 i: 06 - value 0.60 i: 05 - value 0.50 i: 04 - value 0.40 i: 03 - value 0.30 i: 02 - value 0.20 i: 01 - value 0.10
Do části part2
() napište program, který
--- Ukázka výpisu volání programu s argumentem 2 pro spuštění druhé části part2() java -jar dist/lab06.jar 2 Even numbers: 2 4 6 8 10 12 14 16 18 20 Numbers divisible by 7: 14 21 28 35
V metodě start
modifikujte větvění tak, aby v případě hodnoty proměnné PART == 1
došlo k volání jak part1() tak part2().
switch(PART) { case 1: part1(); case 2: part2(); break; ... }
Očekávaný výpis při spuštění programu s argumentem 1 pro první část je:
i: 10 - value 1.00 i: 09 - value 0.90 i: 08 - value 0.80 i: 07 - value 0.70 i: 06 - value 0.60 i: 05 - value 0.50 i: 04 - value 0.40 i: 03 - value 0.30 i: 02 - value 0.20 i: 01 - value 0.10 Even numbers: 2 4 6 8 10 12 14 16 18 20 Numbers divisible by 7: 14 21 28 35
Napište program v části part3()
, který načte ze standardního vstupu celočíselnou hodnotu a zjistí, zda-li je číslo prvočíslo. Vstupní hodnotu testujte, zda-li je celým číslem metodou TextIO.isInteger
a v případě neočekávaného vstupu vypište chybovou hlášku na standardní chybový výstup.
Testujte metodu pro různě veliké vstupy a v případě nepřiměřeně dlouhého výpočtu omezte vstupní hodnotu.
--- Ukázka výpisu java -jar dist/lab06.jar 3 Enter an integer number > 2 and < 10000000 11 Given number 11 is prime number
--- Ukázka výpisu java -jar dist/lab06.jar 3 Enter an integer number > 2 and < 10000000 6257134 Given number 6257134 is not prime number
--- Ukázka chybového výpisu java -jar dist/lab06.jar 3 Enter an integer number > 2 and < 10000000 0 Given number is out of range
--- Ukázka chybového výpisu java -jar dist/lab06.jar 3 Enter an integer number > 2 and < 10000000 2 Given number is out of range
--- Ukázka chybového výpisu java -jar dist/lab06.jar 3 Enter an integer number > 2 and < 10000000 eleven It is not an integer number
Seznamte se s metodou part4
() poskytnutého projektu, která počítá součet hodnot z posloupnosti zadaných čísel ze standardního vstupu. Všiměte si, jak je testován konec vstupu. Vstupní hodnoty jsou čteny jako textové řetězce po řádcích, přičemž se předpokládá, že na každém řádku je jedno číslo. Pokud řádek neobsahuje číslo, je jeho obsah ignorován.
java -jar dist/lab06.jar 4 1 2 3 4 5 End of input detected! Sum of the 5 input numbers is 15.0
Program rozšiřte o výpočet průměrné hodnoty. S očekávaným výstupem ve tvaru
java -jar dist/lab06.jar 4 1 2 3 4 5 End of input detected! Sum of the 5 input numbers is 15.0 Avg of the 5 input numbers is 3.0
V páté části cvičení si vyzkoušíme překlad programu z příkazové řádky a jeho následné spuštění s předáním vstupního argumentu pro výběr příslušné části programu, která bude vykonána. Také si vyzkoušíme přesměrování standardního vstupu ze souboru.
Nejdříve si otevřete terminál a přepněte se do adresáře se staženými projektovými soubory, např. cd ~/pr1/pr1-lab06
. V adresáři najdete zdrojové soubory v adresářové struktuře src
a dále pak soubor pro řízení předkladu build.xml
programu ant
, případně další projektové soubory vytvořené prostředím Netbeans.
--- Překlad zdrojových souborů ant jar
V archívu s projektovými soubory je také příklad vstupního souboru input.txt
pro část part4
(). Obsah textového souboru můžeme zobrazit příkazem cat
:
--- Výpis obsahu souboru input.txt na standardní výstup cat input.txt 23 3 1 3 4
Tento soubor použijeme jako vstup našeho programu. Nejdříve tak, že přesměrujeme standardní vstup na tento soubor při spuštění programu:
--- Spuštění programu s přesměrovaným vstupem (a argumentem 4 pro spuštění 4. části) java -jar dist/lab06.jar 4 <input.txt End of input detected! Sum of the 5 input numbers is 34.0 Avg of the 5 input numbers is 6.8
Alternativně můžeme použít standardní výstup jednoho programu jako standardní vstup jiného programu prostřednictvím znaku svislítko | (pipe):
--- Spuštění programu s přesměrovaným vstupem jako výstupem programu cat cat input.txt | java -jar dist/lab06.jar 4 End of input detected! Sum of the 5 input numbers is 34.0 Avg of the 5 input numbers is 6.8
Dále můžeme přesměrovat standardní výstup programu
--- Spuštění programu s přesměrovaným standardním výstupem do souboru output.txt cat input.txt | java -jar dist/lab06.jar 4 >output.txt End of input detected!
a také můžeme přesměrovat standardní chybový výstup, například do souboru err.txt
--- Spuštění programu s přesměrovaným standardním výstupem do souboru output.txt a chybovým výstupem do err.txt cat input.txt | java -jar dist/lab06.jar 4 >output.txt 2>err.txt
V pracovním adresáři vzniknout dva soubory output.txt
a err.txt
, které můžete vypsat na obrazovku příkazem cat
nebo otevřít ve vašem oblíbeném textovém editoru, např. gedit
.
V případě používání alternativního operačního systému pak třeba přímo na stránkách jeho tvůrce