Programovanie (1) v C/C++
1-INF-127, ZS 2024/25
Letný semester, prednáška č. 1
Obsah
Organizácia predmetu v letnom semestri
Základné črty jazyka Java a programovania v ňom
Prvoradým cieľom tohto predmetu je zvládnutie základov objektovo orientovaného programovania (OOP) prostredníctvom programovacieho jazyka Java. Na úvod je užitočné vedieť o tomto jazyku nasledujúce:
- Základné syntaktické konštrukcie jazyka Java sú v mnohom veľmi podobné jazykom C a C++. Už tento týždeň by sme mali zvládnuť prepísať do Javy väčšiu časť programov z minulého semestra; budúci týždeň by to už mali byť úplne všetky programy.
- Jazyk Java je silne (aj keď nie čisto) objektovo orientovaný. Použite tried – ktoré sú popri objektoch základným konceptom OOP – je nutné na napísanie aj toho najjednoduchšieho programu.
- Na druhej strane je triedu možné použiť aj ako obyčajný „obal” pre niekoľko metód (t.j. funkcií) podobného typu ako v minulom semestri. Takýmto spôsobom budeme s Javou pracovať na dnešnej prednáške. S ozajstným objektovo orientovaným programovaním začneme až budúci týždeň.
- Programy v jazyku Java sa obvykle nekompilujú do strojového kódu, ale do tzv. javovského bytekódu. Po skompilovaní programu teda nedostávame bežný spustiteľný súbor, ale súbor, ktorý možno spustiť na javovskom virtuálnom stroji (angl. Java Virtual Machine; skr. JVM). Vykonávanie takýchto programov je síce o niečo pomalšie, zato sú však prenositeľné medzi rôznymi operačnými systmémami a architektúrami.
Celkovo ide o jazyk omnoho vyššej úrovne, než jazyk C: v oveľa väčšej miere sa tu abstrahuje od počítačovej architektúry. Java napríklad neumožňuje priamy prístup k pamäťi počítača a o uvoľňovanie alokovanej pamäte sa stará JVM automaticky prostrednictvom mechanizmu tzv. garbage collection. Hoci teda jazyk nie je príliš vhodný na nízkoúrovňové programovanie, tvorba „bežných” používateľských programov je tu podstatne pohodlnejšia, než napríklad v jazyku C. Okrem toho Java disponuje veľkou knižnicou štandardných tried (Java Class Library; skr. JCL), v ktorej je okrem iného implementované aj množštvo algoritmov a dátových štruktúr. Orientáciu v možnostiach ponúkaných touto knižnicou značne uľahčuje dokumentácia k nej.
Rozdiel v úrovni abstrakcie medzi jazykmi C a Java sa premieta aj do typického programátorského štýlu. Od efektívnosti samotnej implementácie sa dôraz obvykle posúva k aspektom softvérového inžinierstva, ako sú napríklad čitateľnosť, rozšíriteľnosť a „spravovateľnosť” kódu. S niektorými elementárnymi princípmi softvérového inžinierstva sa zoznámime aj na tomto predmete.
Prvý program v jazyku Java
Tradične začneme programom, ktorý na konzolu vypíše text Hello, World!.
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- Názov súboru sa musí zhodovať s názvom triedy, ku ktorému sa pridá prípona .java – v našom prípade teda musí byť zdrojový kód uložený v súbore Hello.java.
- Program je potrebné skompilovať javovským kompilátorom a následne spustiť na javovskom virtuálnom stroji – návod možno nájsť na osobitnej stránke. Po skompilovaní programu získame súbor java.class spustiteľný na JVM.
Rozoberme postupne jednotlivé časti uvedeného programu:
- Funkcia main, ktorá sa podobne ako v C/C++ začne vykonávať bezprostredne po spustení programu, je „obalená” v triede, ktorú sme nazvali Hello. V jazyku Java musí byť všetok kód súčasťou nejakej triedy (význam tried pre OOP zatiaľ ponechajme bokom).
- Hlavička funkcie main musí byť vždy tvaru ako vyššie. Modifikátory public a static si vysvetlíme neskôr; nasleduje návratový typ void, názov funkcie main a argumenty funkcie main, ktorými sú argumenty programu z príkazového riadku (v podobe poľa reťazcov).
- Samotný výpis na konzolu realizuje metóda System.out.println.
Keďže jeden väčší program typicky pozostáva z množstva rôznych tried (v rôznych súboroch), je možné triedy ďalej umiestniť do balíkov; program tak často pozostáva z niekoľkých balíkov navzájom súvisiacich tried. Umiestnenie triedy do balíka možno realizovať príkazom na začiatku zdrojového súboru.
package somepackage;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- V našom prípade sme triedu Hello umiestnili do balíka somepackage. Pri práci s IDE ako napr. IntelliJ je často potrebné pridať balík aj do projektu; rozdiel je tiež pri kompilovaní a spúšťaní triedy z príkazového riadku. Viac sa možno dočítať tu.
- Pokiaľ deklarácia balíka chýba, považuje sa trieda za súčasť nepomenovaného balíka (angl. unnamed package alebo default package). Používanie nepomenovaného balíka vo všeobecnosti nie je dobrá prax, ale je zmysluplné pri menších programoch pre vlastnú potrebu (alebo pre potreby tohto predmetu).
- Za dobrú prax sa naopak považuje pomenúvanie balíkov tak, aby boli celosvetovo jednoznačne identifikovateľné – za týmto účelom preto boli vybracované špeciálne konvencie.
Za účelom sprehľadnenia zdrojového kódu a často pomerne rozsiahlych knižníc sa pri pomenúvaní identifikátorov v Jave používajú (okrem iných aj) nasledujúce konvencie:
- Názvy tried by mali vždy začínať veľkým písmenom.
- Názvy premenných, metód a balíkov by naopak mali vždy začínať malým písmenom.
Nedodržiavanie týchto konvencií budeme na tomto predmete považovať za chybu.
Príklad o niečo rozsiahlejšieho programu
import java.util.*;
public class Program {
/* Spocita sucet prvkov pola a.
*/
public static int sum(int[] a) {
int result = 0;
for (int i = 0; i <= a.length - 1; i++) {
result += a[i];
}
return result;
}
/* Spocita priemer hodnot prvkov pola a.
*/
public static double average(int[] a) {
return (double) sum(a) / a.length;
}
/* Najde najvacsi prvok pola a.
*/
public static int max(int[] a) {
int max = Integer.MIN_VALUE; // Premenna ma rovnaky nazov ako metoda
for (int i = 0; i <= a.length - 1; i++) {
if (a[i] >= max) {
max = a[i];
}
}
return max;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i <= n - 1; i++) {
a[i] = scanner.nextInt();
}
scanner.close();
System.out.println("Sucet: " + sum(a));
System.out.println("Priemer: " + average(a));
System.out.println("Maximum: " + max(a));
}
}