Gyakorlati alapok
Az állapotjelzők (flag)
A flag zászlót jelent, de programozás-technikai értelme általában valamilyen 2 állású állapottárolás. Működése talán jobban hasonlít a régi szemafor működéséhez...
...amelynek szintén 2 állása volt és ezzel 2 állapotot tudott felvenni. A szemafor kifejezés ismert a programozásban is: a fogalmat a zseniális holland Edsger Dijkstra (1930-2002) vezette be az osztott erőforrásokhoz való hozzáférések szabályozásához a többszálú (multithread) környezetekben. Ilyen tipikus környezet például maga az operációs rendszer, amely éppen ezt az egész Java-környezetet futtatja, az tehát működése során állandó és ideiglenes flag-ek egész tömegét használja fel.
Lényegét tekintve a szemafor és flag kifejezés programozás-technikailag ugyanazt jelenti: a 2 állású állapottárolás lehetőségét.
A módszertanon belül a következő, prímszámkereső fejezet mutat meg először egy klasszikus flag-felhasználást, amely során egy 2 állású, boolean típusú flag-et használunk fel a prímszámkeresés megkönnyítésére (boolean prim = true;):
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
int szam;
boolean prim = true;
Scanner in = new Scanner(System.in);
System.out.println("Kérem, hogy gépelje be a számot (0 és 1
nem prímszám)!");
szam = in.nextInt();
if (szam == 1 || szam == 0 || szam % 2 == 0){
System.out.println(szam + " nem
prímszám!");
prim = false;
}
else
for (int j = 2; j <= Math.sqrt(szam);
j++){
if (szam % j
== 0){
prim = false;
System.out.println(szam + " nem prímszám!");
break;
}
}
if(prim == true)
System.out.print(szam + " prímszám");
}
}
Végeredmény (például):
Kérem, hogy gépelje be a számot (0 és 1 nem prímszám)!
23
23 prímszám
Láthatjuk, hogy a flag értékét voltaképpen mi állítgatjuk a feltételeknek megfelelően. De más esetekben egy másik függvény, egy másik folyamat (process), egy távoli felhasználó vagy akár számítógéphez csatlakoztatott érzékelő is beavatkozhat flag-ek állításába.
Természetesen lehetséges olyan objektumokat létrehoznunk, amelyek flag-ek tömegét tárolja. Nézzünk erre egy viszonylag egyszerű példát!
Adott 1 véletlenszám-generátor, amelyik nem véletlenül 1 és 1000 között generál véletlenszámokat: ezeket egy 20 elemű tárolótömbbe helyezzük (int tomb[] = new int [20];). Ezután létrehozunk egy boolean típusú flag tömböt valamilyen tetszőleges állapot tárolására (boolean benneVan[] = new boolean [20];), és false értékekkel inicializáljuk:
for(int i = 0; i < benneVan.length; i++){
benneVan[i] = false;
}
A tetszőleges feltétel legyen mondjuk az, hogy a szám osztható-e 10-zel...
...de nyilvánvalóan bármilyen feltétel megfelelő, ha az képes reprezentálni a számok valamelyik tulajdonságát.
Ha a feltétel igaz, a flag tömb azonos indexű állapota true értékre lesz állítva. A végén az egészet kiírjuk a konzolra, okulásul az utókornak:
import java.util.Random;
public class Main {
public static void main(String[] args) {
int tomb[] = new int [20];
boolean benneVan[] = new boolean [20];
for(int i = 0; i < benneVan.length; i++){
benneVan[i] = false;
}
Random random = new Random();
for (int i = 0; i < tomb.length; i++){
tomb[i] = random.nextInt(1000) + 1;
}
for (int i = 0; i < tomb.length; i++){
if (tomb[i] % 10 == 0){
benneVan[i] =
true;
}
System.out.println
(i+1 + ".indexen lévő véletlenszám: " +
tomb[i] + ". Osztható 10-zel? " + benneVan[i]);
}
}
}
Végeredmény (például):
1.indexen lévő véletlenszám: 936. Osztható 10-zel? false
2.indexen lévő véletlenszám: 760. Osztható 10-zel? true
3.indexen lévő véletlenszám: 102. Osztható 10-zel? false
4.indexen lévő véletlenszám: 620. Osztható 10-zel? true
5.indexen lévő véletlenszám: 351. Osztható 10-zel? false
6.indexen lévő véletlenszám: 523. Osztható 10-zel? false
7.indexen lévő véletlenszám: 767. Osztható 10-zel? false
8.indexen lévő véletlenszám: 62. Osztható 10-zel? false
9.indexen lévő véletlenszám: 416. Osztható 10-zel? false
10.indexen lévő véletlenszám: 494. Osztható 10-zel? false
11.indexen lévő véletlenszám: 160. Osztható 10-zel? true
12.indexen lévő véletlenszám: 436. Osztható 10-zel? false
13.indexen lévő véletlenszám: 577. Osztható 10-zel? false
14.indexen lévő véletlenszám: 647. Osztható 10-zel? false
15.indexen lévő véletlenszám: 371. Osztható 10-zel? false
16.indexen lévő véletlenszám: 690. Osztható 10-zel? true
17.indexen lévő véletlenszám: 429. Osztható 10-zel? false
18.indexen lévő véletlenszám: 666. Osztható 10-zel? false
19.indexen lévő véletlenszám: 386. Osztható 10-zel? false
20.indexen lévő véletlenszám: 21. Osztható 10-zel? false
Észrevehetjük, hogy az index számozása 1-gyel kezdődik, de ne felejtsük el, hogy valójában mindig 0-val, csakis az egyértelmű kiírás miatt alakítottam át az i léptető értékét (i+1)!
Természetesen szinte bármelyik adattípus felhasználható flag-ként. Maradjunk az egyszerű adattípusoknál és nézzük meg a fenti prímszámkeresési algoritmust int típusú flag-gel (int prim = 1;):
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
int szam;
int prim = 1;
Scanner in = new Scanner(System.in);
System.out.println("Kérem, hogy gépelje be a számot (0 és 1
nem prímszám)!");
szam = in.nextInt();
if (szam == 1 || szam == 0 || szam % 2 == 0){
System.out.println(szam + " nem
prímszám!");
prim = 0;
}
else
for (int j = 2; j <= Math.sqrt(szam);
j++){
if (szam % j
== 0){
prim = 0;
System.out.println(szam + " nem prímszám!");
break;
}
}
if(prim == 1)
System.out.print(szam + " prímszám");
}
}
Végeredmény (például):
Kérem, hogy gépelje be a számot (0 és 1 nem prímszám)!
23
23 prímszám
Sőt, kissé mesterkélten, de működik string adattípussal is (String prim = "1";):
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
int szam;
String prim = "1";
Scanner in = new Scanner(System.in);
System.out.println("Kérem, hogy gépelje be a számot (0 és 1
nem prímszám)!");
szam = in.nextInt();
if (szam == 1 || szam == 0 || szam % 2 == 0){
System.out.println(szam + " nem
prímszám!");
prim = "0";
}
else
for (int j = 2; j <= Math.sqrt(szam);
j++){
if (szam % j
== 0){
prim = "0";
System.out.println(szam + " nem prímszám!");
break;
}
}
if(prim.equals("1")
System.out.print(szam + " prímszám");
}
}
Végeredmény (például):
Kérem, hogy gépelje be a számot (0 és 1 nem prímszám)!
23
23 prímszám
Igazából ekkor a prim értéke már bármilyen szóval, karakterszekvenciával behelyettesíthető. Alább visszatérünk a true-false pároshoz, de még mindig string-formátumban:
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
int szam;
String prim = "true";
Scanner in = new Scanner(System.in);
System.out.println("Kérem, hogy gépelje be a számot (0 és 1
nem prímszám)!");
szam = in.nextInt();
if (szam == 1 || szam == 0 || szam % 2 == 0){
System.out.println(szam + " nem
prímszám!");
prim = "false";
}
else
for (int j = 2; j <= Math.sqrt(szam);
j++){
if (szam % j
== 0){
prim = "false";
System.out.println(szam + " nem prímszám!");
break;
}
}
if(prim.equals("true")
System.out.print(szam + " prímszám");
}
}
Végeredmény (például):
Kérem, hogy gépelje be a számot (0 és 1 nem prímszám)!
23
23 prímszám
Programozás-technikai szempontból flag-ek esetében talán mégis a legelőnyösebb a 2 állású boolean adattípus használata.