[itk] Számítástechnika kezdőknek

Programozási alapfogalmak, alapvető kérdések, C++, Javascript példák

[2024. február 12.] [ christo161 ]

Ez egy alapozó, gyorstalpaló tananyag azoknak, aki még soha nem programoztak, és el szeretnék kezdeni. A tananyagban alapvető programozási fogalmakról lesz szó (változó, tömb, osztály/objektum, elágazás, ciklus), illetve a gyakran feltett kérdésekről is leírom a véleményem (kell-e matek vagy erős számítógép a programozáshoz, milyen programozási nyelvvel érdemes kezdeni), bár bevallom őszintén, ezekről a gyakori kérdésekről azért nem szeretek írni, mert rengeteget lehet rajtuk vitatkozni, és talán nem is lehet rájuk objektív, precíz választ adni, illetve ha valaki ilyen kérdéseket tesz fel valamilyen fórumon vagy facebook csoportban, akkor jellemzően teljesen ellentétes válaszokat kap.

Ebben a tananyagban lesznek példák is, C++ és Javascript nyelven, de a példákban nem oldunk meg minden problémát (pl. ha mondjuk bekérünk egy szám értéket a felhasználótól, de nem számot ad meg, hanem egyéb karaktereket).
A C++ és Javascript nyelv viszonylag hasonlít sok más népszerű programozási nyelvre. A Javascript kódot HTML kódba ágyazzuk be.
A HTML nyelv elemeit, szabályait ebben a tananyagban nem vesszük át nagyon a részletekbe menően, szinte csak annyi HTML-t írunk, hogy a benne lévő Javascript kód működni tudjon.

Ebben a tananyagban nem lesz szó a programozási nyelvek apró sajátosságairól. 

Ajánlom továbbá egy nagyjából elkészült tananyagomat, ami a programozási fogalmak viszonylag részletes megismerését célozza meg (illetve a C++ programnyelv alapvető megismerését):

Tervezek készíteni egy webfejlesztés tananyagot is, ami arra koncentrál, hogy legfőbbképpen csak olyan tudnivalókat tartalmazzon, amik konkrétan egy honlap (legyen az statikus vagy dinamikus) elkészítéséhez szükségesek:

Tartalomjegyzék

Előszó

Ezt a tananyagocskát (illetve a C++ programozás kezdőknek vagy a gyakorlatias webfejlesztés tananyagokat) igazából azért készítettem/készítem, mert nem értek egyet más programozási tananyagok tematikájával. Például nem tartom jónak, ha egy programozási tananyag pl. ilyenekkel kezdődik:

  • a számítógépek történetének ismertetése
  • a számítógép hardvereinek részletesebb (nem alapvető) ismertetése
  • számrendszerek, számrendszerek közti átváltás
  • általános iskolai matematikánál bonyolultabb matematika
  • a programozási alapvető fogalmak ismertetésének kihagyása (pl. sok könyvben nem írják le, mit jelent a programozásban a függvény, csak elkezdenek beszélni függvényekről)
  • a programozási fogalmak, tudnivalók szerintem rossz sorrendben történő ismertetése (pl. előbb van szó (részletesen) függvényekről, mint elágazásokról, ciklusokról vagy tömbökről)

Ez tehát az én véleményemen, az én meglátásaimon alapul. Erről lehet vitatkozni, én azt mondom, hogy aki szeretne, nyugodtan írjon szerinte jobb tananyagokat mint én.

Ezt itt most még nem kell érteni.

Amiket itt leírok, azok olyan programnyelvekre vonatkoznak, amikre jellemzőek ezek a tulajdonságok:

  • magasszintű programozás
  • imperatív programozás
  • struktúrált programozás
  • jobbára objektum-orientált programozás

Példák: C, C++, C#, Java, Javascript, Pascal, Basic, Python, Perl, PHP, Rust
Ellenpéldák: Haskell, Clean, OCaml, F#, Lisp, Prolog

Miért írom le ezt, ha még nem kell érteni?

Azért, mert vannak olyan programozási nyelvek, amikben az itt leírt fogalmak mást jelenthetnek (pl. funkcionális programozási nyelvekben mást jelent a változó, mint fogalom, mint az imperatív programozási nyelvekben).
Noha kevés az esélye, hogy akinek fogalma sincs a programozásról, pont egy olyan programnyelvvel kezdjen el ismerkeni, amikre a fentebb felsorolt jellemzők nem vonatkoznak, de azért gondoltam, hogy talán mégis érdemes tudni erről.

Illetve a következő jellemzők szerint is lehet csoportosítani a programozási nyelveket:

  • erősen típusos, statikusan típusos
  • gyengén típusos, dinamikusan típusos

Ezekről sem kell tudni még most, hogy mit jelentenek, a lényeg, hogy mindkettőre lesz példa a tananyagban:

  • erősen típusos és statikusan típusos: C++ programozási nyelv 
  • gyengén típusos és dinaimukusan típusos: Javascript programozási nyelv

Milyen programozási nyelvet érdemes tanulni?

Szerintem ezek közül valamelyiket:

  • webfejlesztés
  • Java
  • C#
  • Python

A webfejlesztés alapvetően ezekből a nyelvekből áll: HTML, CSS, Javascript, PHP, MySQL, esetleg NodeJS, NoSQL, illetve az ezekre épülő függvénykönyvtárak, frameworkok (pl. Bootstrap, JQuery, ReactJS, Angular, Laravel, Symphony).
(Igen, a HTML és a CSS nem programozási nyelv, hanem csak leírónyelvek, de ez most nem lényeg).

Miért ezeket ajánlom?

  • Magyarországon (és talán más országokban is) ezekkel a legkönnyebb elhelyezkedni
  • ezekből nem feltétlenül kell vérprofinak lenni, illetve nem kell 5-10 éves tapasztalat az elhelyezkedéshez
  • ezekhez van a legtöbb tananyag, segítség az interneten
  • ezeket viszonylag könnyű megtanulni más programozási nyelvekhez képest (pl. a C vagy C++ nyelveket sokkal több idő megtanulni)
  • ezekhez van a legtöbb más programozók által megírt megoldás alapvető vagy hasznos feladatokhoz (itt az úgynevezett függvénykönyvtárakra, frameworkökre gondolok)

Természetesen nem muszáj ezek közül a nyelvek közül választani. Szinte bármilyen programozási nyelvet meg lehet tanulni, de érdemes a következőkön elgondolkodni:

  • milyen hamar szeretnél ebben a szakmában elhelyezkedni (pl. ha fiatal vagy, és akár éveket is tudsz gyakorolni, az teljesen más, mintha munka mellett tanulsz és belátható időn belül szeretnél szakmát váltani)
  • mi a célod egy programnyelv megismerésével (pl. szeretnéd-e megérteni mi hogyan működik, vagy nem baj, ha mondjuk valakiről lemásolsz egy kódot, amiről nem tudod pontosan hogyan működik, csak látod, hogy működik)
  • tudsz-e gyorsan tanulni akár nehezen érthető dolgokat, vagy csak apránként tudsz haladni

Ez a honlap segítséget nyújthat abban, hogy az egyes programozási szakterületekhez pontosan milyen programozási nyelveket, egyéb dolgokat érdemes megtanulni.

Nem biztos, hogy ezt a tananyagot mindig tudom frissíteni, ha esetleg megváltozna az, hogy milyen programozási nyelvekkel lehet munkát találni. De azt mindenképp tudom ajánlani, hogy érdemes nézegetni az álláshirdetéseket, azokból viszonylag jól le lehet szűrni, hogy mik az elvárások.

Félni kell-e attól, hogy elavul az a tudás, amit megszereztünk?

Ezt sokszor emlegetik a programozás kapcsán, hogy mindig frissíteni kell a tudást, de szerintem ha valaki egyetlen programozási nyelvet is megtanult elég alaposan, akkor sem lesz teljesen elveszve ha akár egy másik nyelvet kell megtanulnia, vagy ha a nyelv, amit megtanult, valamennyire megváltozik.

Milyen szintű matek kell a programozáshoz?

Egyrészt ez alapvetően attól függ, hogy valaki milyen területen szeretne programozni (vannak olyan területek, amik nem igényelnek különösebb matektudást).
Másrészt, nem egy programozó van, aki arra esküszik, hogy aki sokat foglalkozott matekkal, annak majd jobban fog menni a programozás. Erről jókat lehet vitatkozni, itt most ebbe nem megyünk bele.

Sok tipikus program egy adatbázisból kérdez le (jelenít meg), módosít, hozzáír, töröl adatokat, amihez biztosan nem kell egyetemi matek.

Szerintem elég tisztában lenni ilyesmikkel:

  • mit jelent az, hogy páros vagy páratlan egy szám
  • mit jelent a maradékos osztás (más néven egész osztás), pl egy szám akkor páratlan, ha 2-vel osztva 1-et ad maradékul, páros, ha 0-t
  • mit jelent az, hogy egész vagy valós egy szám
  • műveleti sorrend (pl. ha nincs zárójelezés, akkor a szorzást előbb végezzük el, mint az összeadást)
  • mit jelent két vagy több szám átlaga

Talán nem árt tisztában lenni azzal, hogy mit jelentenek a prímszámok, mert azt szinte minden tanfolyamon fel szokták hozni példának.

Néhány példa amik jellemzően nem szükségesek a programozáshoz:

  • másodfokú egyenlet megoldóképlete
  • legkisebb közös többszörös, legnagyobb közös osztó
  • szögfüggvények (sinus, cosinus, tangens)
  • függvények ábrázolása koordináta rendszerben
  • egyenletek megoldása
  • képletek, tételek megtanulása (pl. binomiális tétel)
  • geometria (pl. kerület, terület), koordinátageometria

Előfordulnak olyan tanárok, tanfolyamok, akik előszeretettel adnak fel olyan programozási feladatokat, ahol matekfeladatok megoldásait kell egy programmal kiszámítani és kiíratni.

A programozásban sokszor fogunk találkozni a függvény (function) kifejezéssel, de a programozásban a függvény többnyire nem a matematikai függvényeket jelenti, hanem a programon belül egy részfeladatot, alprogramot.

Összességében tehát azt tudnám mondani, hogy középiskolai/gimnáziumi, sőt talán akár általános iskolai matek is elég lehet ahhoz, hogy valaki egy ilyen fent említett tipikus programot vagy egy weblapot elkészítsen, amivel akár már el is lehet helyezkedni, pénzt lehet vele keresni.

Felsőfokú matektudást igényő területek a programozásban:

  • 3d grafika
  • kriptográfia, titkosítás
  • satöbbi

Ajánlom ezt a két magyar nyelvű videót is:

Milyen számítógép/hardver ajánlott a programozáshoz?

A tanuláshoz jellemzően elég lehet akár egy 10 éves számítógép is.

Webfejlesztéshez, Javahoz, Pythonhoz is. Talán C#-hoz egy kicsit jobb gép ajánlott a Visual Studio (amiben C#-ban tudunk programozni) gépigénye miatt, de ahhoz sem kell erőművet venni.

Erős gép jellemzően akkor szükséges, ha többmillió soros kódot kell fordítani, vagyis ha nagy programokkal dolgozunk.

Ha valaki anyagilag megengedheti, érdemes lehet programozáshoz és a szokásos otthoni tevékenységekhez (pl. képek, filmek, zenék, játék) külön-külön számítógépet használni.

Mi a programozás? 

A programozás az, amikor egy programot készítünk el.

Programokra biztosan mindenki tudna példát mondani. Például webböngésző, jegyzettömb (windowson notepad.exe, linuxon gedit, kate, featherpad, satöbbi), szöveg- vagy inkább dokumentumszerkesztő (Microsoft Word, LibreOffice Writer), képszerkesztő (Microsoft Paint, Adobe Photoshop), videólejátszó (VLC Player), zenelejátszó (Winamp, Audacious).

Amiket most felsoroltam, azokat a programokat nem egy ember készíti, hanem akár többszáz fős szervezet(ek)/cég(ek).
Olyan programokra példa, amiket egy ember is el tud készíteni: naptár, todo list, snake, sudoku, pasziánsz, tetris és hasonlók.
Persze nem ezekkel szokták a programozást kezdeni, hanem Hello Worldel, illetve az alapvető fogalmak megismerésével (ezekről lesz itt szó), ezek apró programocskák.

Erre a válaszra sokan jó eséllyel azt reagálnák, hogy dehát ez teljesen egyértelmű, vagy azt, hogy ez nem jó vagy bugyuta válasz, mégis sokszor előfordul, hogy akiknek egyáltalán nincs fogalmuk a programozásról, azok valami olyasmit értenek a programozás alatt, mint például az operációs rendszer (Windows, Linux, Mac OS, OS X) telepítése vagy a számítógépen bizonyos dolgok beállítása.

Hogyan lesz a programkódból program?

Ez programnyelv függő.

Webfejlesztés

Például webfejlesztés, honlapkészítés esetén valamilyen plain text fájl (formázást nem tartalmazó fájl) szerkesztésére alkalmas programmal (jegyzettömb/notepad (linuxon gedit, kate, satöbbi) VSCode, notepad++, Sublime text, Atom, Brackets, satöbbi) megírjuk a kódot mondjuk egy html kiterjesztésű/formátumú fájlba, és ezt a fájlt dupla kattintással futtatjuk valamilyen webböngészővel.

A webfejlesztésben szerver oldali nyelven írt kódot (pl. PHP, nodejs) nem tudunk így futtatni. Vagy fel kell töltenünk a fájlokat egy webszerverre, és akkor láthatjuk az eredményt, vagy valamilyen lokális szerver programmal (pl. VSCodeban a Live Server kiegészítővel (extensionnel), vagy mondjuk XAMPP-al) futtathatjuk az adott fájlt.
(Zárójelben megjegyezhetjük, hogy a html nem programozási nyelv (és a css sem), viszont egy html fájlon belül lehet Javascript kód is, ami viszont már programozási nyelv.)

HTML

Egy weblap alapvető szerkezeti elemei. Pl. címsor, bekezdés, kép, táblázat, űrlap, felsorolás.

CSS

Egy weblap HTML elemeinek a formázása CSS nyelvben történik. Pl. itt adhatjuk meg a szövegek igazítását, margókat, illetve azt, hogy bizonyos tartalmak pl. egymás mellé, egymás alá legyenek elhelyezve.

Javascript

Gombra kattintáskori események, form validation (pl. regisztrációnál érvényes email címet vagy érvényes dátumot adott-e meg a felhasználó), legördülő menü, slider (váltakozó képek a honlap fejlécében), stb.

PHP, SQL

Jellemzően szerver oldali (pl. adatbázisból származó adatok) kiíratása, módosítása, törlése. De pl. php-val meg lehet oldani ilyen feladatokat is mint mondjuk képek átméretezése (pl. thumbnailek készítése), captcha kód kiíratás, ellenőrzés.

Fordított nyelvek (compiled languages)

Vannak olyan programnyelvek, amik esetén a kódot szintén plain text fájlokba írjuk meg (a fájlok kiterjesztése/formátuma programnyelv függő, pl C++ programozási nyelv esetén cpp, C# programozási nyelv esetén cs), VAGY olyasmi kódszerkesztővel, amiket a webfejlesztés esetén felsoroltam (pl. VSCode), VAGY valamilyen integrált fejlesztői környezettel (IDE) (ez utóbbira példák: Visual Studio, NetBeans, Eclipse), viszont a futtatható fájlt egy úgynevezett fordító (compiler) készíti el. Ebben az esetben a futtató fájl használatához nincs szükség a fordítóra vagy a forráskódra.

Értelmezett nyelvek (interpreted languages)

Vannak olyan programnyelvek is, amiknél jellemzően nem készül futtatható fájl, hanem valahányszor a programot futtatjuk, az általunk megírt kódot valamilyen értelmező (interpreter) soronként értelmezi és lefuttatja. Ilyen nyelv például a Pyhon, Perl.

Köztes kód (bytecode)

Vannak olyan nyelvek, amiknél a fentebbi két eset egyesítve érvényes. Fordítani is kell, viszont a lefordított kód köztes kód, kell hozzá valamilyen program (virtuális gép vagy futtatókörnyezet), amivel a köztes kódot futtatni lehet.
Ilyen nyelvek a Java és a C#. Java esetén a köztes kódot a JVM (Java Virtual Machine) futtatja, C# esetén, pedig a .NET Framework.

Alapvető elmélet

Egy program adatokkal dolgozik, másképp fogalmazva adatokból adatokat állít elő.

program_input_output.png

Képzeljük el úgy, hogy egy program elkészítésekor, vagyis amikor programozunk, akkor ezt bontjuk részfeladatokra. Vagyis a programon belül létrehozunk sok kicsi, úgynevezett alprogramot, más néven függvényt (function), amik adatokból adatokat állítanak elő, és ezeket az előállított adatokat adogatják át egymásnak.

Az adatokat a programon belül jellemzően változókban, tömbökben vagy objektumokban tároljuk.
(Ezekről a fogalmakről bővebben lesz szó lentebb).

  • változó: a program futásának egy adott pillanatában egyetlen adatot lehet benne tárolni
  • tömb: a program futásának egy adott pillanatában több (sok programozási nyelvben jellemzően csak azonos típusú) adatot lehet benne tárolni
  • objektum: a program futásának egy adott pillanatában több, jellemzően különböző típusú adatot lehet benne tárolni

Az adatok típusa a programozási nyelvekben jellemzően:

  • egész szám
  • valós szám
  • karakter
  • string (szöveg, több karakter, karakterlánc)
  • boolean (igaz/hamis érték)
  • dátum

Egy program a feldolgozás alatt lévő adatokat a számítógép memóriájában (RAM, random access memory) tárolja. Ezek az adatok megszűnnek a számítógép kikapcsolásakor.
Azokat az adatokat, amikre tartósan szükségünk van, jellemzően fájlokban szoktuk tárolni (a számítógép háttértárolóján (HDD vagy SSD) vagy az interneten/felhőben). Egy adatbázisban tárolt adatok is technikailag a háttérben fájlokban vannak tárolva (akár a számítógép háttértárolóján vagy az interneten).

function.png

Persze azt hozzá kell tenni, hogy egy program futása során nem biztos, hogy mindig ugyanazok a függvények ugyanabban a sorrendben lesznek végrehajtva. Pont ez egy program egyik lényege, hogy attól függően, hogy a felhasználó mit csinál, más lesz a program futásának az eredménye, vagy akár úgy is mondhatjuk, hogy a felhasználói interakciótól függően eltérő adatokat állít elő a program.

Alapvető fogalmak

Plain text fájl

Olyan szöveget tartalmazó fájl, ami nem tartalmaz formázást (tipikus példa rá a txt kiterjesztésű/formátumú fájlok).

Ellenpélda

Formázást tartalmazó fájl például amit Microsoft Worddel vagy LibreOffice Writerrel készítünk el (doc, docx, odt kiterjesztésű/formátumú fájlok).

Minden program forrásfájljai plain text fájlok. Csak a kiterjesztés/formátum függ a programnyelvtől.
Pl. webfejlesztés, honlapkészítés esetén a forrásfájlok kiterjesztése (txt helyett) például html, css, js, php. Pl. C++ programozási nyelven cpp vagy h.

Kiterjesztés/formátum (extension)

A fájl neve után, a fájl nevétől ponttal elválasztva néhány betű. Például txt, doc, jpg, png, mp3, (Windowsban) exe.

(Windowsban előfordulhat, hogy el van rejtve a kiterjesztések megjelenítése).

(Linuxon a futtatható fájloknak jellemzően nincs kiterjesztése, csak neve).

Forrásfájl, forrásfájlok (source file, source files)

Azok a fájlok, amikbe egy program forráskódját írjuk.

Forráskód, más néven programkód (source code)

Egy bizonyos programozási nyelv szerinti utasítások sorozata, amiből a programot állítjuk elő értelmező (interpreter) vagy fordító (compiler) segítségével (lásd fentebb).

Warning

Olyan hiba, ami esetén elő tudunk állítani futtatható programot, viszont illik kijavítani vagy számon tartani.

Fordítási hiba (error)

Olyan hiba, ami esetén nem tudunk futtatható programot előállítani.

Szintaktikai hiba

Olyan hiba, ami egy programozási nyelv szabályainak a rossz használatából adódik.

Szemantikai hiba

Olyan hiba, ami esetén a program lehet szintaktikailag helyes, viszont valamit logikailag nem jól raktunk össze. Ilyen hiba esetén elképzelhető, hogy létre tudunk hozni futtatható programot, csak a program nem (vagy nem mindig) azt csinálja, amit szeretnénk.

Kódrészlet (code snippet)

Olyan utasítás, utasítások vagy kifejezés, kifejezések, amik önmagukban nem futtatható programok, viszont futtatható programok forráskódjába a megfelelő helyre bemásolhatjuk őket, és akkor lehet, hogy működnek.

Például C++ programnyelvben:

std::cout << "Hello World!\n";

Például Javascript programnyelvben:

document.querySelector("#hello_world_container").textContent = "Hello World!";

Ebben a tananyagban sok kódrészlet lesz, de lesznek majd olyan példák, amik működőképes programok, és felölelik az előzőekben tárgyalt kódrészleteket. Ez utóbbiakat példaprogramnak nevezem itt ebben a tananyagban.

Megjegyzések, kommentek a forráskódban

A programozó feljegyzései a forráskódban. Olyan szövegek, amiket a fordító vagy az értelmező nem kísérel meg futtathatóvá alakítani.

Persze ahhoz, hogy a fordító, ételmező tudja, hogy mit tekintsen kommentnek a kódban, ezt valahogy jelölni kell.

C++-ban és Javascriptben a követőző jelöléseket használjuk kommentelésre:

//comment example
code //comment example
/*comment example*/
code /*comment example*/ code
/*comment example line 1
comment example line 2*/
code /*comment example line 1
comment example line 2*/ code

A // komment a // jeltől kezdve tart az adott sor végén lévő sorvége jelig (ezt úgy kell érteni, hogyha egy jegyzettömbben vagy kód editorban bekapcsoljuk a hosszú szövegek tördelését (word wrap), akkor attól még a fordító/értelmező csak azt fogja különálló sornak tekinteni, amelyik sor végén sorvége jel van).

A /**/ komment a /* jeltől kezdve a legközelebbi */ jelig tart. A lezáró (*/) jel lehet akár több sorral a nyitó jel /* alatt, de akár egy soron belül is elhelyezkedhet mind a nyitó (/*), mind a záró (*/) jel.

CSS-ben ezek közül csak a /**/ jelölés működik.

Html-ben ezt a jelölést használjuk kommentelésre:

<!-- comment example -->
code <!-- comment example --> code
<!-- comment example line 1
comment example line 2 -->
code <!-- comment example line 1
comment example line 2 --> code

A <!-- --> hasonlóan működik mint a /**/

1. Példaprogram: alapvető kód, Hello World program

Az alapvető kód az, amit le kell írni a forráskódba ahhoz, hogy egy program működjön, de önmagában nem csinál semmi érdemlegeset. Vagyis ha csak ezt írjuk le, majd futtatjuk, a futtatás eredménye nem ad kimenetet.

Az alapvető kód persze nem azt jelenti, hogy az összes program nagyjából így néz ki. Ezek a példák csak egyszerű programok alapvető kódjai. Bonyolultabb programokban is lehetnek alapvető kódok, de jellemzően nem pont így, mint az itteni példákban.

Az első példaprogramok kódjának itt ebben a tananyagban nem magyarázzuk el minden sorát, hogy mire való, de kommentben megjelöljük azt a helyet, ahová jellezően a további kódrészleteket, utasításokat írhatjuk (legalábbis az egyszerű programok esetén).

Egy másik C++ tananyagomban például a C++ Hello World program minden sora alaposal el van magyarázva. Ez a tananyagrész itt található:

1.0cpp példaprogram

Például egy nagyon egyszerű, parancssoros C++ program alapvető kódja tipikusan így néz ki:

//essential code of a simple command line cpp program
#include <iostream>

int main() {
  //write your code here
}

C++ nyelvben a program végrehjtása a main függvény első sorával kezdődik. Javascriptben nincs main függvény, ott a Javascript kód első sorával kezdődik a végrehajtás.

1.1cpp példaprogram:

Egy Hello World program C++ nyelven így néz ki:

//Hello World! example in cpp
#include <iostream>

int main() {
  std::cout << "Hello World!\n";
}

Láthatjuk, hogy az érdemi utasítást, amit a program csinál, a kapcsos zárójelek közé írtuk.

C++ nyelvben a kiíratásra vonatkozó utasítás nem egy ördöngősség. std::cout << után kell megadni, azt, amit ki szeretnénk írni. Ha ez szöveg, akkor idézőjelek közé kell tenni (különben a fordító "azt hinné", hogy változó). \n-el jelöljük a sortörést.

Ezt a példaprogramot egyébként online C++ fordítóval kipróbálhatjuk, ha bemásoljuk valamelyikbe:

  • wandbox.org
  • godbolt.org
  • coliru.stacked-crooked.com
1.0js példaprogram:
<!-- essential code of a simple Javascript example, which is embedded in html code -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Example text in Web browser's window title</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        /* write your code here */;
      });
    </script>
  </head>
  <body>
    <h1>Title in webpage content</h1>
    <div id="container_example"></div>
  </body>
</html>

A document.addEventListener("DOMContentLoaded", () => { }); függvény mindösszesen annyiért felelős, hogy amit beleírunk, az azt követően fut le, ha már betöltődött az egész oldal (minden html tag a </html>-ig bezárólag).

1.1js példaprogram:

Egy Javascript Hello World program sokféleképp is kinézhet (például ehelyett alert függvénnyel is ki lehetne íratni). Egy példa:

<!-- Hello World example in Javascript -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World in Javascript example</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("div#hello_world_container").textContent = "Hello World!";
      });
    </script>
  </head>
  <body>
    <h1>"Hello World!" text inserted here by Javascript:</h1>
    <div id="hello_world_container"></div>
  </body>
</html>

Kipróbálhatjuk, ha bemásoljuk:

  • codepen.io/pen
  • js.do

Láthatjuk, hogy a script tagek közé (<script> és </script>) helyezhetjük el a Javascript nyelven írt kódot. A script tagek, és az őket körülvevő kód HTML nyelven íródott. A HTML rész tulajdonképpen csak azért felelős, hogy egy html fájlba bemásolva is ki lehessen próbálni a kódot.

A document.querySelector függvénnyel választjuk ki a html tagek közül azt, aminek a tartalmát módosítani szeretnénk. Ennek a függvénynek paraméterben idézőjelek közt megadjuk, hogy mit válasszon ki. Segít, ha a tag típusát megadjuk (ez esetben div), de tulajdonképpen elég ha csak az adott tag id-ját adjuk meg (html tag id-ból nem lehet egy html fájlban 2 vagy több azonos).

Miután a document.querySelector függvény megtalálta a hello_world_container id-val ellátott div html taget, ha annak a textContent tulajdonságát módosítjuk, akkor azzal azt adjuk meg, hogy milyen szöveget írjon bele a Javascript kód.

Sortörést nem kell elhelyeznünk, mivel a div html tagek alapbeállítás szerint külön sorba íródnak.

Ha a szövegbe szeretnénk sortörést tenni, akkor viszont ne a textContent tulajdonságot módosítsuk, hanem az innerHTML-t. A C++-ban használt \n helyett html-ben a <br> a sortörés. Erre egy példa:

document.querySelector("div#hello_world_container").innerHTML = "line1<br>line2";

Javascript esetén ennek a programnak gyakorlatilag nincs értelme. A html tagekbe is beleírhattuk volna, hogy hello world, ami így nézne ki: <div>Hello World</div> és akkor nem lenne szükség a script tagekre és annak a tartalmára.
Ennek a programnak annyi értelme van, hogy bemutassa, hogy Javascript esetén mi lehetne a C++-os példa megfelelője technikailag.

1.2js példaprogram:

A Javascriptnek megvan az a tulajdonsága például a C++-al szemben, hogy az eredmény látványosabb, ha mondjuk egy gombra történő kattintás után jelenítjük meg az eredményt, ez viszont valamivel bonyolultabbá teszi a kódot.

<!-- Hello World example in Javascript (with button) -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World in Javascript example</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("button#btn_print").addEventListener("click", () => {
          document.querySelector("div#hello_world_container").textContent = "Hello World!";
        });
      });
    </script>
  </head>
<body>
  <div><button id="btn_print">Print Hello World text</button></div>
  <h1>"Hello World!" text inserted here by Javascript:</h1>
  <div id="hello_world_container"></div>
</body>
</html>

A document.querySelector függvénnyel kiválasztjuk a gombot (paraméterként megadjuk neki, hogy button típusú html taget keressen, aminek az id-ja btn_print), és az addEventListener függvénnyel hozzárendelünk egy klikkeseményt, úgy, hogy az első paraméternek megadjuk, hogy "click" a második paraméternek pedig megadjuk azokat az utasításokat, amiket szeretnénk, ha lefutnának a gombra való kattintáskor. Ebben az esetben a hello world szöveg beillesztése.

1.3js példaprogram (feladat):

Készítsünk egy másik gombot, amire kattintva a hello world szöveg eltűnik. Ez technikailag azt jelenti, hogy a .textContent tulajdonságnak egy üres szöveget adunk értékül, amit két idézőjellel jelülünk, ami között nincs semmi: ""

Alapvető tudnivalók a változókról, konstansokról, literálokról

A most következő példakódoknak önmagukban nincs gyakorlati értelme, egészen a következő példaprogramokig, de ezeknek az elmagyarázására mégis szükség van ahhoz, hogy a későbbi példaprogramokat megértsük.

Változó (variable, esetleg variant)

Egy programon belül valamilyen adat tárolására, kezelésére alkalmas (jellemzően egész szám (pl. 1, 128, 0, -3), vagy valós szám (pl. 3,14, -1,6), vagy karakter (pl. a, b, x, y, 0, 1, +, %), vagy szöveg, vagy logikai (igaz/hamis)), a programozó által névvel ellátott memóriaterület.
Azért kell elnevezni, hogy később (pl. amikor a változóban tárolt adatot fel akarjuk használni, módosítani akarjuk, ki akarjuk íratni), akkor valahogy tudjunk rá hivatkozni. Másképp fogalmazva egy változóra a forráskódban a változó nevével hivatkozunk.

Magasszintű programozási nyelvekben nem a programozó dönti el, hogy egy változónak a számítógép memóriájában lefoglalt memóriaterület pontosan hol legyen a számítógép memóriájában (másképp fogalmazva nincs direkt memória címzés).

A változó elnevezés onnan ered, hogy egy változóban tárolt adat (úgynevezett érték, value), a forráskód bármelyik utasításában/sorában megváltoztatható.

Vannak olyan programozási nyelvek, ahol egy változónak van típusa, és ez a típus jellemzően nem változtatható meg a program futása során (vagyis a forráskód utolsó soráig). Ilyen programozási nyelv például a C, C++, C#, Java, Pascal.
Vannak olyan programozási nyelvek, ahol egy változónak a benne tárolt adat határozza meg a típusát, és egy változó típusa megváltoztatható. Ilyen programozási nyelv például a Javascript vagy a PHP.

Változó értéke (value of variable)

Egy változóban a program futásának egy adott pillanatában tárolt adat.

Változó típusa (type)

Egy változó típusa ilyesmi lehet általában a programozási nyelvekben:

  • int, integer (egész szám)
  • float, esetleg double (valós szám)
  • char (karakter)
  • string (szöveg, vagyis több karakter)
  • bool vagy boolean (igaz/hamis, (angolul true/false) érték)

Például Javascript vagy PHP nyelvben egy változónak nincs típusa, a változóban tárolt adatnak, a változó értékének van típusa.

Javascriptben nincs char típus, ha egyetlen karaktert tárolunk egy változóban, az is string (szöveg) típusú.
Javascriptben nincs egész szám vagy valós szám típus, number típus van, és abban valós számokat tárolunk (a valós számoknak ugyabár részhalmaza az egész számok, tehát egy number típusú változóban egész számokat is tudunk tárolni Javascript nyelvben).

Változók nevei, azonosítók

A változók, tömbök, függvények, objektumok, osztályok, egyéb dolgok neveit összefoglaló néven angolul indentifier-nek (azonosítónak) szokták nevezni.

Egyrészt a névadáskor be kell tartani bizonyos szabályokat. Jellemzően:

  • Egy azonosító nem kezdődhet számmal
  • Egy azonosító nem tartalmazhat szóközt
  • Egy azonosító egyedi kell, hogy legyen (pl. egy blokkon (kapcsos zárójeles részen) belül nem lehet két azonos nevű változót létrehozni)
  • Egy azonosító nem lehet azonos az adott programozási nyelv kulcsszavaival (más néven foglalt szavaival)

Ezek például C++ és Javascript nyelvben érvényesek, de lehet, hogy van olyan programozási nyelv, ahol ezektől eltérőek a szabályok.

Ezeket nem csak a változók elnevezésekor, hanem bármilyen azonosítónál be kell tartani.

Bővebben:

Másrészt a névadáskor bizonyos konvenciókhoz (közös megegyezésen alapuló szokásokhoz) szoktuk magunkat tartani:

  • A C++ nyelvben jellemzően snake_case-t használunk, azaz ha több szóból áll például egy változó neve, akkor a szavakat alsóvonallal választjuk el egymástól. Pl: variable_example
  • Javascript nyelvben jellemzően camelCase-t használnunk, azaz ha több szóból áll például egy változó neve, akkor az első szót kisbetűvel, a többi szót nagybetűvel kezdjük, és nem írunk semmilyen elválasztó jelet közéjük. Pl: variableExample

Előfordul, hogy egy forráskódban különféle dolgok elnevezéséhez különféle elnevezési konvenciókat használunk. Java nyelvben például a függvények neveit tipikusan camelCase szerint írjuk, az osztályok neveit viszont PascalCase szerint.

Bővebben:

Én az itt szereplő példakódokban, példaprogramokban a Javascriptben is snake_case-t használok, megszokásból.

Változó létrehozása (definiálása, deklarálása)

Sok programozási nyelvben jelezni kell a számítógépnek, hogy valamilyen adatot tárolni/kezelni szeretnénk, mielőtt még bármilyen érdemleges műveletet végeznénk az adattal.

C++ nyelvben ezt például úgy tehetjük meg, hogy megadjuk a változó típusát és a nevét. Például:

int variable_example;

Ekkor a számítógép memóriájában lefoglalódik egy egész szám tárolásához szükséges memóriaterület, amire a programunk forráskódjában variable_example-el hivatkozhatunk, ezzel a névvel érjük el a változóban tárolt értéket.

C++ nyelvben ha már egyszer létrehoztunk egy változót akkor azt (egy adott blokkban) nem hozhatjuk létre mégegyszer.

Javascript nyelvben gyanezt például úgy tehetjük meg, hogy var vagy let kulcsszót követően

var variable_example1;
let variable_example2;

Javascriptben a var kulcsszóval létrehozott változókat létrehozhatjuk többször is, viszont a let kulcsszóval létrehozott változókat csak egyszer. Javascriptben manapság a var kulcsszó használata kerülendő.

PHP nyelvben nem kell jeleznünk, hogy létre szeretnénk hozni egy változót. Ahogy leírjuk a nevét, automatikusan létrejön. Viszont ahhoz, hogy PHP nyelv el tudja különíteni egy változó nevét más dolgoktól, a változók neve dollár jellel kezdődik. Például:

$variable_example;

Inicializálás (kezdőértékadás)

Amikor egy változónak a létrehozásával azonos utasításban adunk értéket.

C++ nyelvben például:
int variable_example1 = 5;
double variable_example2 = 3.14;
char variable_example3 = 'a';
std::string variable_example4 = "something";
bool variable_example5 = false;
Javascript nyelvben például:
let variable_example1 = 5;
let variable_example2 = 3.14;
let variable_example3 = 'a';
let variable_example4 = "something";
let variable_example5 = false;

Fontos, hogy mindig adjunk kezdőértéket a változóinknak (akár 0-val egyenértékű értéket, vagy string esetén üres stringet: ""), mert ha ezt nem tesszük meg, az jellemzően a program hibás működéséhez vezet.

Értékadás (assignment)

Egy már definiált/deklarált változónak az értékét megváltoztatjuk, módosítjuk valamilyen új értékre.

Pl. ha a variable_example egy string/szöveg típusú változó akkor:

variable_example = "new_value";

Egy értékadásban egy változó régi értékét is felhasználhatjuk.

Például ha a variable_example egy int típusú változó, akkor így adhatunk hozzá 5-öt az addigi értékéhez:

variable_example = variable_example + 5;

Ugyanerre kitaláltak egy egyszerűsített jelölést is:

variable_example += 5;

Például ha a variable_exaplme egy string típusú változó:

variable_example += "_end"

Fontos, hogy értékadáskor már ne adjuk meg a változó típusát (C++), vagy ne használjunk var vagy let kulcsszavakat (JS).

Literál

A forráskód szövegében szereplő konkrét érték.

C++ nyelvben például:
  • int típusú literál: 5
  • double típusú literál: 1.2 vagy 1.0, vagy 5. (5.0) vagy .4 (0.4)
  • char típusú literál: 'a', '1', '\n' (sortörés), '\t' (tabulátor) 
  • stringliterál: "example" vagy "Hello World!" vagy esetleg "a"
  • bool (logikai) típusú literál: true vagy false

Fontos, hogy C++ nyelvben a karakter literálokat aposztrófok közé írjuk, a stringliterálokat pedig idézőjelek közé írjuk.

Javascriptben például:
  • number típusú literál: 5 vagy 1.2
  • stringliterál: "a" vagy 'Hello World!'
  • boolean típusú literál: true vagy false

Javascriptben a stringliterálok írhatók aposztrófok közé, idézőjelek közé vagy akár backtickek (``) közé is. 

Fontos, hogy szinte minden programnyelvben a valós számoknál nem tizedesvesszőt, hanem tizedespontot használunk.

Literálokat például akkor használunk ha értéket vagy kezdőértéket adunk egy változónak (lásd inicializálás), vagy például ha egy konkrét értéket ki szeretnénk íratni (a számítógép képernyőjére).

Konstans (const variable)

Olyan "változó", aminek az értéke nem változhat meg, másképp fogalmazva egy konstans értéke a program futásának végéig (vagy ameddig az adott konstans élettartama tart (jellemzően az adott blokk végéig)) a konstans kezdőértéke.

Szokták őket konstans változónak nevezni, amely elnevezés talán megtévesztő, mivel a változó elnevezés pont abból ered, hogy az értéke megváltozhat, egy konstansnak meg nem változhat meg az értéke.

C++ programnyelvben például így hozunk létre konstansokat:
const int c_example1 = 5;
const double c_example2 = 2.6;
const std::string c_example3 = "can not be changed";

C++ programnyelvben const kulcsszóval létrehozott konstansoknak értékül lehet adni akár egy nem konstans változó értékét is. Van viszont egy olyan kulcsszó, hogy constexpr, aminek csak fordítási időben ismert értéket lehet adni. Például:

constexpr int ce_example = 5;
Javascript programozási nyelvben:
const c_example = 'can not be changed';

Előfordulhat, hogy valaki a literálokat is konstansnak nevezi, és amit én itt konstansnak nevezek, azt nevezi konstans változónak.

Fontos tudni a konstansokról, hogy ne úgy tekintsünk rájuk, mint valami korlátozás. Egy programozó azért hoz létre valamit konstansnak, és nem hagyományos változónak, mert azt szeretné, hogy az az érték ne változhasson meg, és ha mondjuk egy másik programozó valahol a kódban meg szeretné változtatni, akkor a fordító/értelmező hibát dobjon és ne engedje a kódot futtathatóvá alakítani.

A konstansok és a literálok között jellemzően az a különbség, hogy a literálokat csak egyszer használjuk, a konstansokban pedig olyan értéket tárolunk, amit a programban többször is fel szeretnénk használni. 

Kiíratás (print)

Változók, konstansok, literálok értékét kiírathatjuk. Ezekben a példákban a változók létrehozását is elvégezzük, mielőtt kiíratjuk őket

C++ nyelven:
//commandline output in cpp
#include <iostream>
#include <string>

//...

std::string variable_example = "something";
std::cout << variable_example << '\n';
Javascript nyelven:
//html output in js
let variable_example = "something";
document.querySelector("#id_of_html_container").textContent = variable_example;

Javascriptben a document.write függvény hasonlóan működik, mint C++-ban az std::cout, viszont ennek a használata honlapok esetén (html-ben) kerülendő.
Mivel Javascript kódot a legtöbbször honlapokban használunk, ezért törekedjünk arra, hogy a honlap html részeire hivatkozzunk a Javascript kódban, és a html tagek .textContent vagy .innerHTML tulajdonságát módosítsuk.

Bekérés (user input)

Bekérésnek nevezzük, ha a felhasználót kérjük meg arra, hogy adjon értéket pl. változóknak. A bekéréskor érdemes kiíratni, hogy milyen értéket írjon be a felhasználó.

A beolvasott értékek nem biztos, hogy egyeznek azzal, amit a felhasználó megad. Ezzel kapcsolatban néhány dolgot érdemes tudni:

C++ nyelvben:
//user input in commandline cpp
#include <iostream>#include <string>

//...

std::string variable_example;
std::cout << "Please enter some text type value\n";
std::cin >> variable_example;
Javascript nyelvben:

Javascript nyelvben általában úgy szoktunk a felhasználótól értéket bekérni, hogy létrehozunk a html részben input mezőket, és azoknak az értékét olvassuk be a Javascript kódban (ha valamilyen műveletet végzünk az értékekkel, azt pedig valamilyen gombra kattintáskor végezzük el és íratjuk ki).

Fontos, hogyha megtaláltuk document.querySelector függvénnyel a keresett input mezőt, akkor annak az értékét a .value tulajdonsággal tudjuk lekérdezni. Az is fontos, hogy ez az érték minden esetben string. Akkor is, ha <input type="number"> html tagről van szó. A következő példaprogramokban láthatjuk, hogy kell átkonvertálni Javascriptben a stringet számmá.

<!-- user input in Javascript -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World in Javascript example</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("button#btn_alert").addEventListener("click", () => {
          let dom_user_input = document.querySelector("input#user_input");
          alert(dom_user_input.value);
        });
      });
    </script>
  </head>
  <body>
    <p><input type="text" id="user_input"></p>
    <p><button id="btn_alert">Show user input value</button></p>
  </body>
</html>

Javascriptben a prompt függvény hasonlókép működik, mint a C++-ban az std::cin, viszont ennek a használata honlapok esetén kerülendő.

2. példaprogram: létrehozás, bekérés, műveletvégzés, kiíratás (változók)

Egy egyszerű példaprogram, ami a változók használatát mutatja be, négy lépésből szokott felépülni:

  • definíció (létrehozás), esetleg inicializálás (kezdőértékadás)
  • bekérés (user input)
  • valamilyen művelet elvégzése a bekért adatokkal
  • az eredmény kiíratása

Ezek közül az első kettő néha összevonható.

2.0cpp példaprogram (két szám átlaga):

Létrehozunk két double típusú változót, amikbe a felhasználótól bekérünk két számot. Kezdőértéket is érdemes nekik adni.

A feldolgozás részben létrehozzuk azt a változót, amiben az eredményt tárolni fogjuk. Miért itt hozzuk létre, és miért nem az első két változóval együtt? Azért mert sokkal jobb, ha egy változót csak akkor hozunk létre, amikor szükségünk van rá.

Két szám átlagát úgy számolhatjuk ki, ha összeadjuk őket, és elosztjuk őket kettővel (mivel két számot adtunk össze).

Majd az output részben kiíratjuk az eredményt.

//variables cpp example: avg of 2 numbers
#include <iostream>
#include <string>

int main() {
//define, initialize
  double num1 = 0, num2 = 0;

//user input
  std::cout << "Please enter number1:\n";
  std::cin >> num1;
  std::cout << "Please enter number1:\n";
  std::cin >> num2;

//processing
  double avg = (num1 + num2) / 2;

//output
  std::cout << "average of num1 and num2: " << avg << '\n';
}
2.0js példaprogram (két szám átlaga):

Ebben a példában szerepel CSS kód is, azért, hogy ne kelljen <p></p> tagek közé rakni a label, input, output, button tageket ahhoz, hogy azok külön sorban jelenjenek meg. Ezt a style tagek között látható módon érjük el.

Vegyük észre, hogy az egész Javascript kód egy függvényben szerepel (leszámítva a "DOMContentLoaded"-es részt, amiről már volt szó korábban), amit a gombra kattintáskor futtatunk le.
Ezt úgy oldjuk meg, hogy először document.querySelector függvénnyel megkeressük a gombot, majd az addEventListener függvénynek első paraméterként megadjuk, hogy "click", második paraméterként pedig megadjuk a kódot, ami a gombra kattintáskor fut le.
A második paraméter technikailag egy arrow function (ami így néz ki: () => {} ), ezt most itt ebben a tananyagban nem fejtjük ki, jegyezzük meg, hogy ilyen szintaktikával lehet ezt megoldani.

Mint ahogy azt már említettem, Javascriptben a bekérést úgy szoktuk megoldani, hogy a html részbe input html tageket helyezünk el, és amit a felhasználó oda beír, azt kérdezzük le és dolgozzuk fel Javascriptben.

Fontos, hogy amikor létrehozzuk a num1 és num2 változókat, akkor az input_num1 és input_num2 id-jú input mezőkből kiolvasott értékeket alakítsuk át számmá. Ezt a parseFloat függvénnyel, vagy a Number konstruktorral tehetjük meg.

Az átlagszámítás ugyanúgy történik, mint a C++ példában.

Az outputot akár egy utasításba is írhatnánk, így:

document.querySelector("output#avg_result").textContent = avg;

Viszont most érdekességképp megjegyezhetjük, hogy a let dom_output = document.querySelector("output#avg_result"); utasítás esetén a dom_output egy változó, aminek a típusa  HTMLElement, vagy ha nem találta amit keresünk, akkor null érték. A HTMLElement technikailag egy objektum típusú változó, amiről később lesz szó.

<!-- variables js example: avg of 2 numbers -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>variables js example: avg of 2 numbers</title>
    <style>
      label, input, output, button {
        display:block;
      }
    </style>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("button#btn_print_avg").addEventListener("click", () => {
        //define, initialize, input
          let num1 = parseFloat(document.querySelector("input#input_num1").value);
          let num2 = parseFloat(document.querySelector("input#input_num2").value);

        //processing
          let avg = (num1 + num2) / 2;

        //output
          let dom_output = document.querySelector("output#avg_result");
          dom_output.textContent = avg;
        });
      });
    </script>
  </head>
  <body>
    <h1>Avg of 2 numbers:</h1>
    <label for="input_num1">Input number 1:</label>
    <input type="number" id="input_num1" value="1">
    <label for="input_num1">Input number 2:</label>
    <input type="number" id="input_num2 value="1">
    <button id="btn_print_avg">Print avg result</button>
    <label for="avg_result">Result of avg:</label>
    <output id="avg_result"></output>
  </body>
</html>

2.1 példaprogram: random szám generálás

Tipp a random szám generáláshoz: bármilyen programozási nyelven ha tesztelni akarjuk, hogy az alsó és a felső érték is benne lehet-e a random generált számok között, kicsi intervallumot adjunk megm és úgy könnyebben tudjuk ellenőrízni.

2.1cpp példaprogram (véletlen szám generálás)

Arról itt most nem lesz szó, hogy melyik utasítás konkrétan mit csinál. Látszik hol kell megadni, hogy melyik két szám között generáljon véletlen számokat a program. Az is látszik, hogy milyen kifejezéssel lehet új véletlen számot generálni.

CPP 1 és 100 között:
//random integral number between 1 and 100
//including 1 and 100
#include <iostream>
#include <random>

int main() {
//initialization
  std::random_device rnd_device;
  std::mt19937 rnd_generator(rnd_device());
  std::uniform_int_distribution<int> int_dist(1,100);

//random generation
  int random_number = int_dist(rnd_generator);

//output
  std::cout << random_number << '\n';
}
CPP 0 és 1 között:
//random number between 0.0 and 1.0
//including 0.0 and 1.0
#include <iostream>
#include <random>

int main() {
  std::random_device rnd_device;
  std::mt19937 rnd_generator(rnd_device());
  std::uniform_real_distribution<double> real_dist(0.0,1.0);

  double random_number = real_dist(rnd_generator);

  std::cout << random_number << '\n';
}
2.1js példaprogram (véletlen szám generálás):

Javascriptben a random generálás alapvetően így működik:

let random_number = Math.round(Math.random() * (max - min) ) + min;

A max a felső érték, a min pedig az alsó.

Alapvetően a Math.random() függvény 0 és 1 közötti értéket ad vissza, és a toFixed függvénynek adott paraméterrel lehet megadni, hogy hány tizedesjegyig szeretnénk kiíratni egy tizedestört számot (pl. a toFixed(2) két tizedesjegyet ír ki).

A Math.round függvény arra használható, hogy ne tört szám legyen az eredmény, hanem egész szám.

Ha Javascriptben egy string esetén nem aposztrófot és nem idézőjelet használunk, hanem backticket, akkor használhatunk benne úgynevezett template literálokat, amiknek a jelölése ${}.
Ha ebben a jelölésben a kapcsos zárójelek közé írunk egy változó nevét, akkor a változó értéke lesz behelyettesítve a változó neve helyére, ha pedig egy kifejezést írunk, akkor a kifejezés eredménye.

<!-- random numbers example -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>random numbers example</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
      //from 0 to 10
        let rand_num1 = Math.round(Math.random() * 10);

      //from 5 to 10
        let rand_num2 = Math.round(Math.random() * (15 - 5) ) + 5;

      //from 0 to 1
        let rand_num3 = Math.random().toFixed(2);

        document.querySelector("div#output").innerHTML = `
        <p>random number 1: ${rand_num1}</p>
        <p>random number 2: ${rand_num2}</p>
        <p>random number 3: ${rand_num3}</p>
        `;
      });
    </script>
  </head>
  <body>
    <h1>Random numbers:</h1>
    <div id="output"></div>
  </body>
</html>

További random generálás példák:

Elágazás (selection)

Az elágazásokkal érhetjük el, hogy egy program ne mindig ugyanazokat az utasításokat hajtsa végre, hanem bizonyos esetben (pl. user inputtól függően) más egyéb utasításokat.

3. példaprogram: elágazások

3.0cpp példaprogram, if-else (melyik szám nagyobb):

Bekérünk két számot a felhasználótól, és egy elágazásban összehasonlítjuk őket. Ebben három eset létezik: az egyik nagyobb, a másik nagyobb vagy egyenlőek.

Fontos: egy elágazásban nem kell kiírni az utolsó eset feltételét, ha az lefedi azt, ami nem tartozik az eddig felsorolt esetek feltételei közé.
Például itt ebben a feladatban ha már megvizsgáltuk, azt a két esetet, hogy az egyik nagyobb vagy a másik nagyobb, akkor a harmadik eset nyilvánvalóan csak az lehet, hogy egyenlőek, kizárásos alapon, ezért is kommenteltük ki az utolsó eset feltételét, mivel oda elég sima else-t írni, nem kell else if (/*feltétel/*).

Erre mindig nagyon figyeljünk oda, hogy egy elágazásban az else előtt lévő esetek lefedik-e azt, amit az else nem.
Mondok erre egy példát. Megvizsgáljuk, hogy egy szám páros-e. Mondhatjuk-e azt, hogyha egy szám nem páros, akkor páratlan? Csak akkor, ha egész számokat vizsgálunk, de például Javascript nyelvben nincs külön egész szám típus, ezért gondolni kell arra is, hogy mi van, ha a felhasználó nem egész számot ad meg, hanem valós számot, aminek nem csak egész része, hanem tört része is lehet.

//which number is greater
#include <iostream>

int main() {
  double num1 = 0, num2 = 0;

  std::cout << "Please enter a floating point value:\n";
  std::cin >> num1;
  std::cout << "Please enter a floating point value:\n";
  std::cin >> num1;

  if (num1 > num2) {
    std::cout << num1 << " is greater.\n";
  } else if (num2 > num1) {
    std::cout << num2 << " is greater.\n";
  } else /* if (num1 == num2)*/ {
    std::cout << "The two values are equals (" << num1 << ").\n";
  }
}
3.0js példaprogram, if-else (melyik szám nagyobb):
<!-- which number is greater -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>which number is greater</title>
    <style>
      label, input, output, button {
        display:block;
      }
    </style>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("button#btn_print_greater").addEventListener("click", () => {
          let num1 = parseFloat(document.querySelector("input#input_num1").value);
          let num2 = parseFloat(document.querySelector("input#input_num2").value);

          let result = "";
          if (num1 > num2) {
            result = `${num1} is greater`;
          } else if (num2 > num1) {
            result = `${num2} is greater`;
          } else /*if (num1==num2)*/ {
            result = `num1 and num2 are equals (${num1})`;
          }

          let dom_output = document.querySelector("output#greater_result");
          dom_output.textContent = result;
        });
      });
    </script>
  </head>
  <body>
    <h1>Which number is greater:</h1>

    <label for="input_num1">Input number 1:</label>
    <input type="number" id="input_num1" value="1">
    <label for="input_num1">Input number 2:</label>
    <input type="number" id="input_num2" value ="1">

    <button id="btn_print_greater">Print greater result</button>

    <label for="greater_result">Result of greater:</label>
    <output id="greater_result"></output>
  </body>
</html>
3.1cpp példaprogram, if-else, (egész szám vagy valós szám):

Fontos. Ha azt vizsgáljuk, hogy két dolog értéke egyenlő-e, akkor a legtöbb programozási nyelven az == operátort használjuk, nem pedig az = operátort, mivel az utóbbit az értékadásra használjuk. Ha a kettőt összekeverjük, hibás lesz a programunk működése.

//integer or floating point number
#include <iostream>

int main() {
  double num = 0;
  std::cout << "Please enter a number:\n";
  std::cin >> num;

  if (num == static_cast<int>(num)) {
    std::cout << num << " is integer number.\n";
  } else /*if (num != static_cast<int>(num))*/ {
    std::cout << num << " is floating point number.\n";
  }
}
3.1js példaprogram, if-else (egész szám vagy valós szám):
<!-- integer or floating point number -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>integer or floating point number</title>
    <style>
      label, input, output, button {
        display:block;
      }
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      document.querySelector("button#btn_print_intorfloat").addEventListener("click", () => {
        let num = parseFloat(document.querySelector("input#input_num").value);

        let result = "";
        if (num == parseInt(num)) {
          result = `${num} is integer number`;
        } else /*if (num != parseInt(num)*/ {
          result = `${num} is floating point number`;
        }

        let dom_output = document.querySelector("output#intorfloat_result");
        dom_output.textContent = result;
      });
    });
    </script>
  </head>
  <body>
    <h1>int/float number:</h1>

    <label for="input_num">Input number:</label>
    <input type="number" id="input_num" value="1">

    <button id="btn_print_intorfloat">Print int/float result</button>

    <label for="intorfloat_result">int or float result:</label>
    <output id="intorfloat_result"></output>
  </body>
</html>
3.2cpp példaprogram, ternáris operátor (negatív szám-e):

Az úgynevezett ternáris operátorokkal helyettesíteni lehet if-else utasításokat, illetve kifejezéseket is. Ezekben a példákban az utóbbira nézünk példát.

Ternáris operátort sokszor érdemesebb használni, főleg Javascriptben amikor kifejezésként és nem utasítástként használjuk.

Nem érdemes ternáris operátort használni, ha sok egymásba ágyazott elágazásról van szó, mert ott a ternáris operátor átláthatatlanná teszi a kódot.

A ternáris operátor használatának szemléltetése

(logikai kifejezés) ? kifejezés/utasítás ha a logikai kifejezés igaz : kifejezés/utasítás ha a logikai kifejezés hamis

Röviden: (logkif) ? igaz esetén : hamis esetén

Előfordulhat, hogy egy ternáris operátoros kifejezés csak akkor működik megfelelően, ha az egészet bezárójelezzük.

Ha azt vizsgáljuk, hogy egy szám negatív-e, akkor egyértelmű, hogy akkor negatív, ha 0-nál kisebb, tehát elég egy if és egy else ág, illetve ternáris operátor esetén nem kell egymásba ágyazni több ternáris operátort.

//is negative number
#include <iostream>

int main() {
  double num = 0;
  std::cout << "Please enter a number:\n";
  std::cin >> num;

  std::cout << num << ( (num < 0) ? " is negative number.\n" :  " is positive number.\n" );
}
3.2js példaprogram, ternáris operátor (negatív szám-e):
<!-- is negative number -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>is negative number?</title>
    <style>
      label, input, output, button {
        display:block;
      }
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      document.querySelector("button#btn_print_isnegative").addEventListener("click", () => {
        let num = parseFloat(document.querySelector("input#input_num").value);

        let dom_output = document.querySelector("output#intorfloat_result");
        dom_output.textContent = `${num} is ${ ( num < 0 ) ? "negative." : "positive." }`;
      });
    });
    </script>
  </head>
  <body>
    <h1>Is negative:</h1>

    <label for="input_num">Input number:</label>
    <input type="number" id="input_num" value="1">

    <button id="btn_print_isnegative">Is negative number?</button>

    <label for="intorfloat_result">isnegative result:</label>
    <output id="intorfloat_result"></output>
  </body>
</html>
3.3cpp példaprogram, switch-case (hétköznap vagy hétvége):

A switch-case elágazás akkor használható, ha mindig egy adott kifejezés értékét vizsgáljuk, és annak az értékétől függően hajtunk végre más-más utasításokat.
C++ nyelvben ennek a kifejezésnek az eredménye csak egész szám (int) típusú lehet.

Viszonylag bugyuta példa, de a switch-case működését egész jól megmutatja. A program bekér egy számot a felhasználótól és ha az 1 és 7 között van, akkor kiírja róla, hogy az a hét napjaként értelmezve hétköznap vagy hétvége. 1-5-ig hétköznap, 6 és 7 pedig hétvége.

Mint ahogy az a példában látható, ha különböző utasítást szeretnénk a különböző értékekhez használni, akkor az utasítás után kell egy break; utasítás is. Ha ezt lehagyjuk (pl. 1-5 esetén vagy 6-7 esetén), akkor a következő break utasításig minden utasítás le fog futni. Ebben a példában persze csak egy utasítás fut le, mert például nincs az 1 vagy a 2 esetre írva külön utasítás, ami ne lenne break; utasítással lezárva.

A default érték felel meg az if-elseif-elseif-else esetén az else ágnak, vagyis ez az az eset, ami nem a többi eset.

//isweekend
#include <iostream>

int main() {

  int day_of_week = 0;

  std::cout << "Please enter a number of a day of the week (1-7):\n";
  std::cin >> day_of_week;

  switch (day_of_week) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      std::cout << "Day " << day_of_week << " of the week is weekday.\n";
      break;
    case 6:
    case 7:
      std::cout << "Day " << day_of_week << " of the week is weekend.\n";
      break;
    default:
      std::cout << "Number: " << day_of_week << " is not between 1 and 7\n";
      break;
  }
}
3.3js példaprogram, switch-case (hétköznap vagy hétvége?):

Javascriptben egy szám típusú input mezőnek megadhatunk alsó és felső értéket, viszont egyrészt a felhasználó beírhat más értéket is ettől függetlenül, másrészt pedig egy webböngészőben a fejlesztői eszközök segítségével (jellemzően f12 billentyű) át lehet írni az alsó és felső értékét az input mezőnek. Tehát jobb ha itt is kezeljük a default értéket.

<!-- is weekend -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>is weekend</title>
    <style>
      label, input, output, button {
        display:block;
      }
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      document.querySelector("button#btn_print_isweekend").addEventListener("click", () => {
        let day_of_week = parseFloat(document.querySelector("input#input_num").value);

        let dom_output = document.querySelector("output#isweekend_result");

        switch (day_of_week) {
          case 1:
          case 2:
          case 3:
          case 4:
          case 5:
            dom_output.textContent = `Day ${day_of_week} is weekday`;
            break;
          case 6:
          case 7:
            dom_output.textContent = `Day ${day_of_week} is weekend`;
            break;
          default:
            dom_output.textContent = `${day_of_week} is not between 1-7`;
            break;
        }
      });
    });
    </script>
  </head>
  <body>
    <h1>Is weekend:</h1>

    <label for="input_num">Input number:</label>
    <input type="number" id="input_num" min="1" max="7" value="1">

    <button id="btn_print_isweekend">Is weekend?</button>

    <label for="isweekend_result">isweekend result:</label>
    <output id="isweekend_result"></output>
  </body>
</html>

Milyen kifejezéseket írhatunk az elágazásoknál a feltétel helyére?

Erről ebben a tananyagomban van szó:

Tömbök, ciklusok

Tömb (array)

Egy tömb egy olyan adatszerkezet, amiben a program futásának egy adott pillanatában több érték tárolható (egy változóban csak egy).
Egy tömb tulajdonképpen olyan, mintha több változót használnánk, de csak egy nevet adnánk nekik, és az egyes elemeit úgy tudjuk elérni, ha megadjuk a tömb nevét, illetve azt, hogy a tömb hanyadik elemével szeretnénk dolgozni (ez utóbbit a tömb indexeinek nevezzük, és a számozása 0-tól kezdődik és a tömb elemszámánál eggyel kisebb számmal végződik).
Egy tömb elemei a számítógép memóriájában egymás mellett helyezkednek el (ellentétben például a láncolt listával).

itk_programming_array_example.png

Mivel a változóknál a definiálásról, inicializálásról már volt szó, ezért a tömböknél ezt nem vesszük külön, hanem egy feladaton belül fognak szerepelni a tömbök használatával.

A tömböknél nem fogunk bekérést használni, mivel már egy 10-20 elemű tömbnél is sok idő lenne, amíg a felhasználó megadná az egyes elemeket. Ehelyett a kódban előre megadott értékeket használunk, mert úgy a program futásának eredményét is könnyebb ellenőrízni.

A C++ nyelvben többféle tömbszerű adatszerkezet létezik. Itt ebben a tananyagban az std::vector-t fogjuk használni, mivel ez hasonlít legjobban más programozási nyelvekben szereplő tömbökre (pl. a Javascriptben szereplő tömbökre).

Ciklus (loop)

Egy ciklust egy utasítás vagy több utasítás többszöri lefuttatására használunk.

Háromféle ciklus létezik, for ciklus, while ciklus és do-while ciklus, illetve a for ciklusnak létezik egy speciális változata, amit a legtöbb programozási nyelvben foreach ciklusnak neveznek (C++ nyelvben ranged for ciklusnak).

for ciklus

Főként akkor használjuk, ha a program futása során meg lehet állapítani, hogy a ciklus hányszor fog lefutni, például ha végiglépkedünk for ciklussal egy tömb elemein, akkor tudjuk hányszor fog lefutni, hiszen a program ismeri a tömb elemszámát.
Tömböket fel tudunk vele dolgozni (a foreach-el ellentétben) úgy is, hogy pl.

  • az utolsó elemtől haladunk az első elemig (fordított sorrendben)
  • kihagyunk pl. minden második elemet
  • nem az első elemtől indulunk és/vagy nem az utolsó elemig lépkedünk
  • valamilyen más feltételt is megadunk (pl. ha megtaláltunk egy bizonyos feltételnek megfelelő elemet a tömbben, akkor álljon le a ciklus)
  • lehetnek speciális esetei (pl. ha több random generált számot előállítunk, de nem szeretnénk, hogy legyen köztük két azonos értékű)

A for ciklus működéséről alapos magyarázat itt található:

foreach ciklus

Főként akkor használjuk ha egy tömbszerű adatszerkezet elemein lépkedünk végig, a tömb első elemétől az utolsó eleméig (esetleg break; utasítással kiléphetünk a ciklusból).

while ciklus

Főként akkor használjuk, ha a program futásakor nem ismert, hogy a ciklus hányszor fog lefutni. Pl. ha fájlból, adatbázisból olvasunk be adatokat, és a fájlban vagy adatbázisban lévő adatok száma napról napra változhat.

do-while ciklus

Két dologra használjuk: input validation illetve egy kódrészlet újrafuttatásának felajánlása a felhasználónak.

Jellegzetessége, hogy egyszer mindenképp lefut, a többi fajta ciklussal ellentétben. De gondoljuk át, ha például azt szeretnénk, hogy egy program addig kérjen be adatot, amíg az nem felel meg bizonyos feltételeknek (pl. dátum esetén a felhasználó hónapnak nem adhat meg 13-at), akkor ahhoz, hogy el tudjuk dönteni, hogy megfelel-e, egyszer mindenképp be kell kérnünk a felhasználótól.

4. példaprogram: tömbök bejárása for ciklussal

4.0cpp példaprogram, páros számok kiíratása (ranged for ciklus és for ciklus):

Létrehozunk egy std::vectort néhány példaértékkel.

Az első (ranged for) ciklusban végigmegyünk a tömbszerű adatszerkezet minden elemén és először azt vizsgáljuk, hogy a soron következő elem egész szám-e, ha pedig igen, akkor pedig azt, hogy páros-e.

Egy szám akkor páros, ha kettővel osztva nullát ad maradékul. Ezt a programozásban általában így ellenőrízzük: number % 2 == 0
Egy szám akkor páratlan, ha kettővel osztva egyet ad maradékul. Hasonlóan az előzőhöz: number % 2 == 1

A második (for) ciklusban kiíratjuk a tömb elemeit. Bár ez kicsit erőltetett megoldás, de a for ciklusban csak a tömb utolsó előtti eleméig megyünk, és a tömb utolsó elemét a ciklus után egy külön utasítással íratjuk ki, mégpedig azért, hogy az utolsó elem után ne szóköz legyen, hanem sortörés.

//print even numbers
#include <iostream>
#include <vector>

int main() {
  std::vector<double> numbers_example = {2, 3, 5, 8, 1.2, 10.5, -6 };
  std::vector<int> even_numbers;

  for (const double& element : numbers_example) {
    int element_to_int = static_cast<int>(element);
    if (element == element_to_int && element_to_int % 2 == 0) {
      even_numbers.push_back(element);
    }
  }

  for (int i = 0; i <= even_numbers.size()-2; ++i) {
    std::cout << even_numbers[i] << ' ';
  }
  std::cout << even_numbers[even_numbers.size()-1] << '\n';
}
4.0js példaprogram, páros és páratlan számok kiszínezése (forEach ciklus):

Ha Javascript esetén a kiválogatás eredményét a html kódba szeretnénk beilleszteni, az sajnos bonyolultabb, mint a C++ kód.

Először is a html kódban lévő vesszővel elválasztott elemeket be kell olvasni Javascripttel és át kell alakítani tömbbé, méghozzá szám típusú tömbbé, mivel számokkal végezhető műveleteket szeretnénk végrehajtani.

Tekintsük át az utasításokat.

A split függvénnyel tudunk feldarabolni egy stringet, aminek az eredménye egy string típusú tömb lesz. A split függvénynek paraméterben adhatjuk meg, hogy mi legyen az az elválasztó karakter, aminek mentén a stringet darabolja fel, és az egyes tömbelemeket hozza létre.

Az Array.from(str_arr, element => parseFloat(element)) kifejezés egy tömböt állít elő egy másik tömbből, ahol a => operátor segítségével adhatjuk meg, hogy egy elemen milyen műveleteket végezzünk el.
Ezzel a kifejezéssel tulajdonképpen megspórolunk egy for ciklust.

Az eredményt egy stringbe állítjuk elő, és ezt a stringet fogjuk majd értékül adni annak a div elemnek, ami a vesszővel elválasztott értékeket tartalmazza.

A Javascriptes forEach ciklusnak kicsit más a szintaxisa, mint a C++-os ranged fornak, de azért a működése könnyen átlátható, kitalálható. Van viszont néhány html-hez köthető újdonság:
Egyrészt a span html tagről eddig még nem volt szó, illetve a css osztályokról sem. Ezt a két dolgot általában együtt használjuk (bár a css classt használhatjuk más esetben is). A span html taggel tudunk egy olyan html tartalomnak formázást adni, amit nem akarunk a környezetétől sortöréssel elválasztani. A css osztály az id-val ellentétben több html tagre vonatkozhat, így tehát több dolognak tudunk vele ugyanolyan formázást adni.

Ebben a példaprogramban is lehetett volna úgy kiíratni az elemeket, mint C++-ban, hogy az utolsó előtti elemig megy egy for ciklus, azokat vesszővel elválasztva íratjuk ki, az utolsó elemet pedig a for ciklus után vessző, és a vessző után szóköz nélkül.
Itt viszont inkább egy más trükköt mutatok meg, mégpedig azt, hogy hogyan lehet karaktereket törölni egy html tag tartalmából. Az innerHTML ugyebár egy string, a split(0, -2) függvénnyel pedig egy string utolsó két karakterét tudjuk eltávolítani a stringből. Vegyük észre, hogy a stringből való törlés önmagában nem elég, az eredményét értékül is kell adni az innerHTML-nek.

<!-- mark even and odd numbers -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>mark even and odd numbers </title>
    <style>
      span.even { color: red; }
      span.odd { color: blue; }
      button { display: block; margin-top:10px;}
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      let dom_button = document.querySelector("button#btn_filter_even_odd");
      dom_button.addEventListener("click", () => {
        //convert div#array_elements (string) to array of numbers
        let dom_arr_elements = document.querySelector("div#array_elements");
        let str_arr = dom_arr_elements.textContent.split(",");
        let num_arr = Array.from(str_arr, element => parseFloat(element));

        //create a string with html tags
        let result_str = [];
        num_arr.forEach((element) => {
          if (element != parseInt(element)) {
            result_str += `${element}, `;
          } else if (parseInt(element) % 2 == 0) {
            result_str += `<span class="even">${element}</span>, `;
          } else if (parseInt(element) % 2 == 1) {
            result_str += `<span class="odd">${element}</span>, `;
          }
        }); //end of foreach


        //insert result_str into div#array_elements
        dom_arr_elements.innerHTML = result_str;

        //delete last comma (and space after it)
        //comma+space = 2 characters, so this is why slice's second argument is -2
        dom_arr_elements.innerHTML = dom_arr_elements.innerHTML.slice(0, -2);

        dom_button.disabled = true;
      }); //button eventlistener
    }); //domcontentloaded eventlistener
    </script>
  </head>
  <body>
    <h1>Even and odd numbers</h1>
    <div id="array_elements">2, 3, 5, 8, 1.2, 10.5, -6</div>
    <button id="btn_filter_even_odd">Filter even/odd numbers</button>
  </body>
</html>

5. példaprogram: while ciklus, véletlenszám generálás két azonos értékig

Például ha addig generálunk véletlen számokat, amíg nem lesz köztük két azonos érték, akkor nem tudjuk előre megmondani, hogy a ciklus hányszor for lefutni.

Ez esetben nem azt kell vizsgálni, hogy az aktuális random generált szám benne van-e már a tömbben (vagy a tömbszerű adatszerkezetben), hiszen ha egyszer belerakjuk, akkor is benne lesz (és így a ciklus az első random generált számnál le is állna), hanem azt, hogy kétszer benne van-e.

Érdemes viszonylag kis intervallumot megadni (pl. 1 és 10 közötti számokat), mert ha túl nagy intervallumot adunk meg, akkor csak soká fog előfordulni olyan eset, hogy kétszer ugyanazt a random generált számot kapjuk.

Szintén érdemes sorbarendezni a tömb vagy tömbszerű adatszerkezet elemeit, mert így könnyebben átlátható, hogy melyik elem szerepel benne kétszer.

C++ nyelven:
//random integral numbers between 1 and 10, until duplicate value
//including 1 and 10
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>

int main() {
  std::random_device rnd_device;
  std::mt19937 rnd_generator(rnd_device());
  std::uniform_int_distribution<int> int_dist(1,10);

  int random_number = 0;
  std::vector<int> numbers;
  while(std::count(numbers.cbegin(), numbers.cend(), random_number) != 2) {
    random_number = int_dist(rnd_generator);
    numbers.push_back(random_number);
  }

  std::sort(numbers.begin(), numbers.end());

  for (const int& element : numbers) {
    std::cout << element << ' ';
  }
  std::cout.put('\n');
}
Javascript nyelven:

A Javascript kódban két jelentősebb különbség van a C++ kódhoz képest.
Egyrészt Javascriptben a tömbök sort() tagfüggvénye alapbeállítás szerint lexikografikusan rendez, ami azt jelenti, hogy például a 10 előbb lesz mint a 2, mert 1-essel kezdődik. Hiába van egy tömbben csak szám típusú érték, ez akkor is így lesz. Ezért jegyezzük meg, hogy Javascriptben, ha számokat szeretnénk sorba rendezni, akkor arra az array_name.sort((num1,num2) => num1 - num2); utasítást tudjuk használni.
Másrészt ha nem konvertáljuk át a tömböt stringgé, akkor automatikusan át fog konvertálódni, hiszen a textContent string, viszont nem árt, ha kiírjuk a toString() függvényt, hogy átláthatóbb legyen, hogy ott egy konverzió történik.

<!-- random numbers between 1 and 10 until duplicate value -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>random numbers between 1 and 10 until duplicate value</title>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      let numbers = [];
      let random_number = 0;
      while (numbers.filter(element => element == random_number).length != 2) {
        random_number = Math.round(Math.random() * (10 - 1) ) + 1;
        numbers.push(random_number);
      }

      numbers.sort((num1,num2) => num1 - num2);

      document.querySelector("p#random_numbers").textContent = numbers.toString();
    });
    </script>
  </head>
  <body>
    <h1>Random numbers between 1 and 10 until duplicate value</h1>
    <p id="random_numbers"></p>
  </body>
</html>

Szerény véleményem szerint a while ciklust nem illik arra használni, mint a for ciklust, hogy addig fut a ciklus, ameddig egy ciklusváltozó a ciklus egyes lépésenkénti növelésével el nem ér egy bizonyos értéket.
Persze mindenki arra használ egy ciklust, amire szeretne, de ha a kódban kell keresni, akkor szerintem jobb, ha a while ciklusra csak olyan találatok érkeznek, amik olyan eseteket fednek le, ahol nem lehet eldönteni előre, hogy egy ciklus hányszor fog lefutni.

6. példaprogram: do-while ciklus, egy tömb (C++-ban std::vector) elemszámának bekérése a felhasználótól

Logikus, hogyha egy tömb elemszámát kérjük be, az nem lehet negatív szám, bár a nullának sincs túl sok értelme, és talán az egynek sem. Tegyük fel, hogy azt ellenőrízzük, hogy a felhasználó kettőt, vagy annál nagyobb számot adott-e meg.

C++ nyelvben nem egyszerű egy olyan esetet kezelni, ha egy szám típusú változónak kérjük be a felhasználótól az értékét, de a felhasználó nem számot ad meg, hanem mondjuk egyéb karaktereket (pl. betűket, írásjeleket). Erre valók az std::cin.fail, std::cin.clear és std::cin.ignore tagfüggvények. Ezeknek a viszonylag részletesebb magyarázatát ebben a tananyagrészben írtam le, itt most nem írnám le mégegyszer.

//do-while loop, input validation example
#include <iostream>
#include <string>
#include <limits>

int main() {
  long int input_number = 0;

  bool error_flag = false;
  do {
    std::cout << "Enter a number which >= than 2:\n";
    std::cin >> input_number;
    error_flag = std::cin.fail() || input_number < 2;

    if (error_flag) {
      std::cout << "Invalid data!" << '\n';
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
  } while (error_flag);

  std::cout << "The input value: " << input_number << '\n';
}

Javascript nyelvben ennek a megfelelőjére nem találtam jó példát, mert ott az input validation megoldható do-while ciklus nélkül, például eseménykezelővel. Ekkor ha a felhasználó 2-nél kisebb értéket próbál beírni, az automatikusan visszaíródik 2-re. Persze fejlesztői eszközök segítségével ez is meghackelhető, viszont ezt már csak szerver oldalon szoktuk megoldani (pl. PHP-ban vagy nodeJS-ben), amiről ebben a tananyagban nem lesz szó.

<!-- input validation (without do-while) -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>input validation</title>
    <style>
      label, input { display: block; }
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      let dom_input_number = document.querySelector("input#number_input");
      dom_input_number.addEventListener("change", (event) => {
        let number_input = parseFloat(dom_input_number.value);
        if (Number.isNaN(number_input) || number_input < 2) {
          dom_input_number.value = 2;
        }
      });
    });
    </script>
  </head>
  <body>
    <h1>input validation</h1>
    <label for="number_input">Number input:</label>
    <input type="number" min="2" id="number_input" value="2">
  </body>
</html>

A C++ megoldáshoz technikailag ez hasonlít Javascriptben, de ezzel meg az a baj, hogy a prompt() függvény használata kerülendő.

<!-- input validation (with do-while) -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>input validation</title>
    <style>
      label, output { display: block; }
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      let input_number = 0;
      do {
        input_number = prompt("Please enter a number that is greater than 1");
      } while (Number.isNaN(input_number) || input_number < 2);
      document.querySelector("output#entered_number").value = input_number;
    });
    </script>
  </head>
  <body>
    <h1>input validation</h1>
    <label for="entered_number">Entered_number:</label>
    <output id="entered_number"></output>
  </body>
</html>

Függvények (functions)

itk_cpp_function_definition.png

A programozásban egy függvény (function) alapvetően úgy működik, hogy leírunk utasításokat, vagy akár egy utasítást, jelezzük, hogy ezek az utasítások egy függvényhez tartoznak, adunk a függvénynek egy nevet, és amikor ezt a nevet a programban a későbbiek során leírjuk, akkor a függvényben lévő utasításokat a program lefuttatja.
Ez azért jó, mert nem kell ugyanazt az utasítássorozatot a program kódjában többször is leírni, mert akkor ha módosítani akarnánk benne valamit, akkor azt az összes helyen át kéne írni, ahol az utasítássorozatot leírtuk, így pedig csak ott kell módosítani, ahol a függvényt definiáltuk (létrehoztuk).

A függvényeknek persze fontos része az, hogy megadhatunk nekik különböző paramétereket. Például képzeljük el, hogy egy programban sokszor kell számok átlagát kiszámítanunk. Akkor létrehozunk egy függvényt, ami átlagot számol, és ezt utána a programban lefuttathatjuk különböző számokkal, és akkor az eredménye is nyilván eltérő lesz. Az átlagszámítás persze csak egy példa a sok közül, szinte bármilyen feladat elvégzésére írhatunk függvényeket.

A függvényeknek nem csak az a célja, hogy egy utasítássorozatot ne kelljen több különböző helyen ismételten leírni a programkódban, hanem az is, hogy a hosszú programkódot feldaraboljuk részfeladatokra, akár abban az esetben is, ha egy függvényt csak egyszer használunk. Részfeladatokra feldarabolva a kód jobban átlátható, könnyebb benne visszakeresni dolgokat, illetve a hibák javításánál is könnyebb nyomon követni, hogy melyik részfeladatnál van a hiba.

Függvénydefiníció (function definition)

A függvény definiálásának nevezzük azt, amikor a függvényt létrehozzuk, vagyis amikor jelezzük a fordítónak/értelmezőnek, hogy a továbbiakban szeretnénk használni egy függvényt, és megadjuk, a bemenő paramétereit, illetve hogy milyen utasítássorozat hajtódjon végre, amikor a függvényt lefuttatjuk. A függvény definíciójában sok programnyelvben a függvény eredményének a típusát (az úgynevezett visszatérési típust) is meg kell adni.

A függvény meghívása (function call)

A függvény meghívásának nevezzük, amikor leírjuk a függvény nevét, ha vannak bemenő paraméterei, akkor megadjuk, hogy milyen értékekkel hívjuk meg a függvényt, és amikor a program futása eljut ehhez a kódsorhoz, akkor a függvénydefinícióban lévő utasításokat lefutttatja.

7. példaprogram: függvény (átlagszámítás példa)

C++ nyelven

Mivel a C++ nyelv erősen típusos nyelv, a függvény visszatérési típusát meg kell adni a függvénydefinícióban. Ez hasonlóképp van például C, C#, Java, Pascal nyelvekben.
A paraméterlistában is meg kell adni az egyes paraméterek típusát. A const típus& kifejezés azt jelenti, hogy nem szeretnénk módosítani az adott paraméteren. Ha módosítani szeretnénk, akkor típus&-t kell írni helyette.

Ebben a példában egy olyan függvényt tekintünk, aminek van visszatérési értéke. A return kulcsszóval jelezzük, hogy a visszatérési értéket visszaadjuk a függvény meghívásának a helyére. Ezt úgy kell elképzelni, hogy ahol a függvényt meghívtuk, oda behelyettesítődik a függvény által visszaadott érték, jelen példában az átlagszámítás eredménye.

//cpp function example: avg
#include <iostream>
#include <vector>

//function definition
  //return type: double
  //parameter1: const std::vector<double>& numbers
  //type of parameter 1: const std::vector<double>&
  //name of parameter 1: numbers
double avg_function (const std::vector<double>& numbers) {
  double avg_result = 0;

  for (const double& element : numbers) {
    avg_result += element;
  }
  avg_result /= numbers.size();

  return avg_result; //return value
} //end of function definition

int main() {
  std::vector<double> stdvec_example1 = {2, 5, 3.7, -6, 10};
  std::vector<double> stdvec_example2 = {9, 7, 1.2, -3, 1};

//function call: avg_function(arguments)
  std::cout << "avg example1: " << avg_function(stdvec_example1) << '\n';
  std::cout << "avg example2: " << avg_function(stdvec_example2) << '\n';
}
Javascript nyelven:

Mivel a Javascript gyengén típusos nyelv, így a függvény visszatérési típusát nem kell megadni a függvénydefinícióban. Helyette a function kulcsszót használjuk, ezzel jelezzük, hogy egy függvénydefinícióról van szó.
A paraméterek típusát sem kell megadni, ami egy kicsit átláthatatlanabbá teheti a kódot, érdemes olyan neveket adni a parmétereknek, amikből kiderül, hogy mi célt szolgálnak.

Ennek a függvénynek a blokkjában nem for ciklust használunk az átlagszámításban a tömb elemeinek az összeadásához, hanem a reduce tagfüggvényt, amit Javascriptben minden tömb esetén használhatunk. Az elnevezésekből viszonylag jól látható a működése.

Ennek a függvénynek szintén van visszatérési értéke, mint a C++-os példában.

<!-- js function example: avg -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>js function example: avg</title>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      //function definition
      function avg_function(numbers) {
        let avg_result = 0;

        const initial_value = 0;
        avg_result = numbers.reduce(
(sum, current_value) => sum + current_value, initial_value);
        avg_result /= numbers.length;

        return avg_result; //return value
      }
//end of function definition

      let array_example1 = [2, 5, 3.7, -6, 10];
      let array_example2 = [9, 7, 1.2, -3, 1];

//function call: avg_function(arguments)
      document.querySelector("div#avg_results").innerHTML = `
<p>avg example1: ${avg_function(array_example1)}</p>
<p>avg example2: ${avg_function(array_example2)}</p>
`;
    });
    </script>
  </head>
  <body>
    <h1>JS function example: avg</h1>
    <div id="avg_results"></div>
  </body>
</html>

Léteznek olyan függvények, amiknek nincs visszatérési értékük (C++-ban ezek a void visszatérési típusú függvények), egyes programozási nyelvekben (pl. Pascal) ezeket nem függvénynek, hanem eljárásnak (procedure) nevezik.

Egy ilyen függvényben nem adunk vissza értéket a return utasítással, hanem csak lefuttatunk egy utasítássorozatot.

Ebben az egyszerű példában C++ nyelvben egy std::vector elemeit íratjuk ki a függvény paraméterében megadott alsó indextől a felső indexig.
1-2 alapvető ellenőrzést is tartalmaz a függvény, például ha az alsó index értéke nagyobb, mint a felső indexé, akkor hibaüzenetet ír ki a függvény.

C++ nyelven
//cpp procedure example, print interval of std::vector
#include <iostream>
#include <string>
#include <vector>

void print_between(const std::vector<std::string>& stdvec, int low, int high) {
  if (low > high) {
    std::cout << "Lower index cannot be larger than higher index.\n";
  } else if (high > stdvec.size()-1) {
    std::cout << "Higher index cannot be larger than the size of std::vector.\n";
  } else {
    for (int i = low; i <= high-1; ++i) {
      std::cout << stdvec[i] << ", ";
    }
    std::cout << stdvec[high] << ".\n";
    std::cout.put('\n');
  }
}

int main () {
  std::vector<std::string> cities_example = {"Amsterdam", "Athens", "Belgrade", "Berlin", "Bratislava",
"Brussels", "Bucharest", "Budapest", "Copenhagen", "Dublin", "Helsinki", "Kiev", "Lisbon",
"Ljubljana", "London", "Luxembourg", "Madrid", "Minsk", "Moscow", "Oslo", "Paris", "Prague",
"Reykjavik", "Riga", "Rome", "Sarajevo", "Skopje", "Sofia", "Stockholm", "Tallinn", "Tirana",
"Vienna", "Vilnius", "Warsaw", "Zagreb"};

print_between(cities_example, 5, 20);
print_between(cities_example, 10, 5);
print_between(cities_example, 1, 100);
}
Javascript nyelven
<!-- js procedure example, print interval of array -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>js procedure example (interval of array)</title>
    <script>
    document.addEventListener("DOMContentLoaded", () => {

      function print_between(array, low, high) {
        let dom_output = document.querySelector("div#interval_of_array");

        if (low > high) {
          dom_output.innerHTML += "<p>Lower index cannot be larger than higher index.</p>";
        } else if (high > array.length-1) {
          dom_output.innerHTML += "<p>Higher index cannot be larger than the size of array.</p>";
        } else {
          dom_output.innerHTML += "<p>"
          for (let i = low; i <= high-1; ++i) {
            dom_output.innerHTML += array[i] + ", ";
          }
          dom_output.innerHTML +=  array[high] + ".</p>";
        }
      }

      const cities_example = ["Amsterdam", "Athens", "Belgrade", "Berlin", "Bratislava", "Brussels", "Bucharest", "Budapest", "Copenhagen", "Dublin", "Helsinki", "Kiev", "Lisbon","Ljubljana", "London", "Luxembourg", "Madrid", "Minsk", "Moscow", "Oslo", "Paris", "Prague","Reykjavik", "Riga", "Rome", "Sarajevo", "Skopje", "Sofia", "Stockholm", "Tallinn", "Tirana","Vienna", "Vilnius", "Warsaw", "Zagreb"];

      print_between(cities_example, 5, 20);
      print_between(cities_example, 10, 5);
      print_between(cities_example, 1, 100);
    });
    </script>
  </head>
  <body>
    <h1>js procedure example (interval of array)</h1>
    <div id="interval_of_array"></div>
  </body>
</html>

9. példaprogram, predicate function, higher order function (páros számok kiválogatása)

Ebben a példában két további függvénytípust veszünk át. Az egyik a predicate function, a másik a higher order function.

predicate function

Egy olyan függvény, ami egyetlen bemenő adatról eldönt valamit (pl. páros szám, negatív szám, nulla, prímszám), és egy igaz/hamis értéket ad vissza.

higher order function

A predicate függvényeket általában úgynevezett higher order function-öknek adjuk át, amik végiglépkednek egy jellemzően tömbszerű adatszerkezet elemein, és minden elemre lefuttatják a paraméterül kapott predicate functiont, és vagy egyetlen eredményt adnak vissza (pl. páros számok összege), vagy egy új tömbszerű adatszerkezetbe gyűjtik ki az eredményt (pl. a páros számokat).

C++ nyelvben

Ebben a példában az std::copy_if a higher order function, a predicate function pedig ez:

[](const int& number) { return number % 2 == 0; }

Ami egyben egy lambda függvény is, amit jellemzően arra használunk, ha nem akarunk külön létrehozni egy függvénydefiníciót, hanem ott, ahol paraméterben egy függvényt adhatunk meg, kifejtjük a konkrét függvényt.

//std::copy_if example
#include <iostream>
#include <vector>
#include <algorithm>

int main () {
  std::vector<int> input = {1,2,3,4,5,6,7,8,9,10};
  std::vector<int> output{};

  std::copy_if(input.cbegin(), input.cend(), std::back_inserter(output), [](const int& number) { return number % 2 == 0; });

  std::cout << "Even numbers:\n";
  for (const int& element : output) {
    std::cout << element << " ";
  }
  std::cout.put('\n');
}

A C++ nyelvben az úgynevezett STL-ben sok ehhez hasonló példa van:

Javascript nyelvben

Ebben a példában a filter a higher order function, a predicate function pedig ez:

(number) => number % 2 == 0;

Ami itt is egy lambda függvény, mint a C++-os példában.

<!-- js filter example -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>js filter example</title>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      const input = [1,2,3,4,5,6,7,8,9,10];
      let output = [];

      output = input.filter((number) => number % 2 == 0);

      document.querySelector("div#even_numbers").innerHTML = `
<p>${output.toString()}</p>
`;
    });
    </script>
  </head>
  <body>
    <h1>js filter example</h1>
    <div id="even_numbers"></div>
  </body>
</html>

Javascriptben higher order függvényekre több példa is van: filter, reduce, map, forEach

Több példa függvényekre, egyéb tudnivalók a függvényekről:

Osztályok, objektumok (classes, objects)

Az osztályokat/objektumokat alapvetően két dologra használjuk:

  • különböző típusú adatok, és a rajtuk végzett műveletek (függvények) összekapcsolása
  • adatszerkezetek létrehozása, például halmaz (set), prioritásos verem (priority stack), kétvégű sor (deque) és hasonlók

Ebben a tananyagban csak a felsőre nézünk példát, az alsóra egyébként érdemes olyan megoldásokat használni, amik már szerepelnek a nyelvben. Manapság minden programozási nyelvben lehet ilyesmi adatszerkezeteket használni, anélkül, hogy nekünk kelljen őket megvalósítani.

Egy osztályra tekintsünk úgy, mint egy típusra, egy objektumra pedig úgy, mint ebből a típusból létrehozott változóra.

10. példaprogram, személy adattípus

Ebben a példában egy egyszerű osztályt definiálunk, és az egyszerűség kedvéért a születési dátumból csak az évet tároljuk, de ha valaki esetleg két teljes dátum alapján akar életkor számolni, annak a segítségére lehet ez a két feladat (az utóbbi akkor, ha stringként adja meg a felhasználó a dátumot, és azt szeretnénk feldarabolni):

Az osztály definiálásakor először az osztály adattagjait hozzuk létre. Ezeket privátként hozzuk létre, ami azt jelenti, hogy csak az osztály függvényei, illetve C++-ban a friend függvények férnek hozzá.

A legtöbb nyelven, ahol osztályokat használunk, szokás getter, setter függvényeket írni minden adattaghoz. Például:

std::string get_name() const {
  return name;
}
void set_name(const std::string& p_name) {
  name = p_name;
}

A getter függvények arra jók, hogy külön-külön is lekérhessük az objektum egyes adattagjainak az értékét, a setter függvények pedig arra jók, hogy többször is meg lehessen változtatni egy adattag értékét. Például a név esetén ez nem biztos, hogy szükséges, de mondjuk a telefonszám esetén elképzelhető.

A konstruktor valójában arra való, hogy ellenőrzéseket végezzünk az osztály példányosításakor (amikor egy objektumot létrehozunk az osztályból) a paraméterben megadott adatokon. Például ha teljes dátumot kérnénk be, akkor ne lehessen mondjuk a hónapnak 13-at megadni.
Ebben a példában nem végzünk ellenőrzéseket a konstruktorban, csak értékül adjuk a példányosításkor paraméterben megadott adatokat az adattagoknak.

A konstruktor akkor fut le, amikor az osztályból létrehozunk egy példányt (egy objektumot). C++ nyelvben a konstruktornak nincs visszatérési típusa és az osztály nevével egyezik.

A count_age függvényben a lényeg, hogy lekérdezzük a jelenlegi dátumot, abból felhasználjuk az évet, és az évből kivonjuk a születési év adattagot. Ez persze nem egészen pontos, mert a hónap és a nap is számítana egy személy életkorának kiszámításakor, de ez túlságosan elbonyolítaná ezt a feladatot (főleg C++ nyelven).

Fontos, hogy azoknál a függvényeknél, amik nem végeznek módosítást az objektumok adattagjain, azoknak a paraméterlistája után írjunk egy const kulcsszót, mert a konstans objektumok esetén csak ekkor engedi a fordító használni az adott függvényt.

C++-ban ha ki akarjuk íratni egy osztály összes adattagját, akkor nem to_string függvényt definiálunk felül, mint a Javascriptben, hanem a kiírató operátort (operator<<) terheljük túl.

A túlterhelés és a felüldefiniálás között a különbség az, hogy a túlterhelés esetén a függvény neve azonos, de a paraméterlista különböző, a felüldefiniálás esetén pedig a paraméterlista is azonos. Felüldefiniálást viszont csak akkor lehet csinálni, ha van egy őse az adott osztálynak, és az ősosztályban szerepel az a függvény, amit felül szeretnénk definiálni. Javascriptben minden osztálynak van közös őse, ami tartalmazza a toString tagfüggvényt, tehát ott meg lehet ezt tenni. C++-ban viszont nincs az osztályoknak közös őse, tehát itt egy külső függvénnyel oldották meg az objektumok adattagjainak a kiíratását.

C++ sajátosság a friend függvény is. Ez csupán annyit jelent, hogy egy olyan függvény, ami nem az osztály tagfüggvénye, hanem úgynevezett free function, hozzáférhessen az osztály privát adattagjaihoz vagy esetleg privát tagfüggvényeihez. Persze ha írnánk getter függvényeket minden adattaghoz, akkor nem kellene az operator<<-t friend függvényként túlterhelni.

Maga a túlterhelés nem egy nagy ördöngősség, kezdőknek azt ajánlom, hogy magolják be, vagy pedig írják fel valahova. Amire különösen figyelni kell, az a visszatérési érték, ami ahhoz kell, hogy a kiíratás mindig az eddigi kiírt elemek után történjen.

Ami más programnyelvek szemszögéből furcsa lehet, C++-ban nem szokás nem operátort használni (csak konstruktorban, de akkor meg a destruktorban kell delete operátor), hanem egy osztályt példányosíthatunk úgy, mint egy alaptípusú változót.

Az operator<< túlterhelésének köszönhetően az osztályból létrehozott objektum adattagjait std::cout-al ki tudjuk íratni.

C++ nyelven
//cpp class and object example
#include <iostream>
#include <string>
#include <chrono>
#include <ctime>

class person {
private:
//data members
  std::string name;
  std::string phone;
  int birth_year;

public:
//constructor
  person (const std::string& p_name, const std::string& p_phone, int p_birth_year) {
    name = p_name;
    phone = p_phone;
    birth_year = p_birth_year;
  }

//member function
  int count_age() const {
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::time_t tt = std::chrono::system_clock::to_time_t(now);
    std::tm local_tm = *localtime(&tt);

    return (local_tm.tm_year + 1900) - birth_year;
  }

//friend member function
  friend std::ostream& operator<<(std::ostream& p_ostream, const person& p_person);
};

//similar to toSring
std::ostream& operator<<(std::ostream& p_ostream, const person& p_person) {
  p_ostream << "Name: " << p_person.name << '\n';
  p_ostream << "Phone: " << p_person.phone << '\n';
  p_ostream << "Age: " << p_person.count_age() << '\n';

  return p_ostream;
}

int main() {
//instantiate person class
  person person1{"Gordon Freeman", "0670123456", 1977};

  std::cout << "Data members of person1:\n";

  //print person1
  std::cout << person1 << '\n';
}
Javascript nyelven:

A Javascriptben is akad más programnyelvektől idegen megoldás. Például a privát tagok elé hashmark jelet rakunk, de nem csak akkor, amikor definiáljuk őket.

Fontos, hogy Javascriptben amikor hivatkozunk az osztály adattagjaira (a definíciót leszámítva) mindig ki kell írni a this kulcsszót. C++-ban erre csak akkor lenne szükség, ha például a konstruktorban a paraméterek nevei egyeznének az adattagok neveivel, mert akkor a paraméterek elfednék az adattagokat. 

Két további különbség a C++-hoz képest, hogy itt a toString() tagfüggvényt definiáljuk felül, illetve a példányosításkor new operátort használunk.

<!-- classes in javascript -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>classes in javascript</title>
    <script>
    document.addEventListener("DOMContentLoaded", () => {
      class person {
      //private data members
        #name;
        #phone;
        #birth_year;

        constructor (name, phone, birth_year) {
          this.#name = name;
          this.#phone = phone;
          this.#birth_year = birth_year;
        }

        count_age = () => {
          const date_now = new Date();
          return date_now.getFullYear() - this.#birth_year;
        }

        toString() {
          return `Name: ${this.#name}, Phone: ${this.#phone}, Age: ${this.count_age()}`;
        }
      }

      //instantiate class to object
      let person1 = new person("Gordon Freeman", "070123456", 1977);

      document.querySelector("div#output").innerHTML += `<p>${person1.toString()}</p>`;
    });
    </script>
  </head>
  <body>
    <h1>classes in javascript:</h1>
    <div id="output"><p>class toString():</p></div>
  </body>
</html>

Aki egy kicsit is foglalkozott már osztályokkal/objektumokkal, az biztosan tudja, hogy sokkal többet lehetne írni róluk. A C++-os tananyagomban ennél egy kicsit több szó esik róluk.

A bejegyzés trackback címe:

https://itkezdoknek.blog.hu/api/trackback/id/tr9218111464

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása