Εισαγωγή στην Java - κεφ. 5

...ασύγχρονα μαθήματα γλώσσας Java

Εισαγωγή στην Java - κεφ. 5

Δημοσίευσηαπό alkismavridis » 16 Μάιος 2012, 20:38

Προηγούμενο: Τελεστές
Επόμενο: Κλάσεις, Αντικείμενα και Μέθοδοι

Δομές Ελέγχου και Επανάληψης


Σκοπός αυτού του κεφαλαίου είναι να μάθετε να χρησιμοποιείτε τις δομές ελέγχου, και τις δομές επανάληψης. Θα καταλάβετε επιτέλους και τι χρησιμεύουν αυτές οι boolean...


Δομές ελέγχου
Με απλά λόγια μία δομή ελέγχου είναι ένα σύνολο άπο εντολές που μπορεί να εκτελεστούν.. μπορεί και όχι! Και αυτό το αποφασίζουμε εμείς.
Μην περιμένετε φυσικά ότι ο υπολογιστής θα σταματίσει και θα σας ρωτήσει. Υπάρχει απλώς ένας μηχανισμός που αποφασίζει αν οι εντολές θα εκτελεστούν ή όχι.
Υπάρχουν δύο κατηγορίες δομών ελέγχου: η if και η switch.


1. Απλή if
Θα παρουσιάσουμε αρχικά τη δομή if σε 3 στάδια, για να γίνει πιο εύκολα κατανοητή.
Στην απλούστερη περίπτωση, η δομή είναι:
Κώδικας: Επιλογή όλων
if (...μία boolean...) εντολή

Δηλαδή γράφουμε τη λέξη-κλειδί if, μία boolean εντός παρενθέσεων, και μία εντολή.
Πχ αν x ένας int μπορούμε να γράψουμε:

Κώδικας: Επιλογή όλων
boolean bl = x==2;
if (bl) System.out.print("ο x είναι 2!\n");

Φυσικά μπορούμε να γράψουμε και κατ ευθείαν
if (x==2) System.out.print("ο x είναι 2!\n");

Άλλωστε η έκφραση x==2 είναι boolean


Πως λειτουργεί:
Μόλις φτάνει στο σημείο της if, το πρόγραμμα ελέγχει αν η boolean εντός παρενθέσεων είναι true. Αν είναι, η εντολή θα εκτελεστεί. Αν όχι δε θα εκτελεστεί.

Μία δομή if ωστόσο μπορεί να περιέχει περισσότερες από μία εντολές! Σε αυτή την περίπτωση χρησιμοποιούμε τις αγκύλες {} για να "κλείσουμε" τις εντολές που θέλουμε:

Κώδικας: Επιλογή όλων
if (x==2) {
System.out.print("Ο x είναι 2!\n");
x=5;
System.out.print("Τώρα ο x έγινε 5!\n");
    //Αυτό δεν επηρεάζει το if-block. Η συνθήκη x==2 ελέγχεται μόνο μία φορά στην αρχή του if-block.
}//if


2. if - else if
Η δομή if έχει και άλλες δυνατότητες. Μπορούμε να πούμε στο πρόγραμμα: «αν ισχύει αυτή η συνθήκη κάνε αυτό, να δεν ισχύει, έλεγξε μία επόμενη συνθήκη, και αν ισχύει κάνε το άλλο κτλ». Πώς;
Χρησιμοποιότντας την λέξη κλειδί else if:

Κώδικας: Επιλογή όλων
if (...μία boolean...) {...εντολές...}
else if (...μία άλλη boolean...) {...εντολές...}
else if (... και τρίτη boolean...) {εντολές...}
...
... όσα else if θέλουμε!


Ας δούμε μερικά παραδείγματα:
Κώδικας: Επιλογή όλων
if (x<0) {
System.out.print("Αρνητικός\n");
}//if
else if (x>0) {
System.out.print("Θετικός\n");
}//else if

και ένα άλλο...

if (mera==7) {
System.out.print("Κυριακή\n");
//κάνε κάτι...
}//if
else if (mera==6) {
System.out.print("Σάββατο\n");
//κάνε κάτι...
}//else if
else if(mera<6 && mera>0) {
System.out.print("Καθημερινή\n");
}//else if

/*Οι boolean θα ελέγχονται μία-μία, από την πρώτη ώς την τελευταία, και όταν  κάποια βρεθεί να είναι true, το πρόγραμμα
θα εκτελέσει τις εντολές στις αντίστοιχες αγκύλες {} και θα εξέλθει από τη δομή if. Καμία άλλη boolean δε θα ελεγχθεί!*/


Προσέξτε ότι όταν χρησιμοποιούμε αυτή την πιο σύνθετη δομή, είναι υποχρεωτική η χρήση των αγκυλών {} στην if και σε κάθε else if, ακόμα και αν αυτές εσωκλείουν μόνο μία εντολή!
Οι συνθήκες των if και else if μπορεί να είναι οποιεσδήποτε boolean. Δεν μας πειράζει αν οι περιπτώσεις αλληλοκαλύπτονται, ή αν αφορούν τελείως διαφορετικά πράγματα.


3. if-else if-else
Τέλος να πούμε ότι μπορούμε να δώσουμε μια εναλακτική στο πρόγραμμά μας, αν η boolean της if και όλες των else if βγουν false. Αυτή η εναλακτική δηλώνεται με την λέξη κλειδί else που θα έχει το δικό της block αγκυλών.
Η else μπαίνει τελευταία, μετά από την if και όλες τις else if. Εδώ να σημειώσουμε ότι η παρουσία των else if είναι προαιρετική. Μπορεί μια χαρά να υπάρχει ένα ζέυγος if-else, χωρίς καμία else if ανάμεσα.
Την else την γράφουμε ακριβώς όπως την else if, αλλά χωρίς παρενθέσεις και boolean.

Ακολουθούν παραδείγματα.
Κώδικας: Επιλογή όλων
απλό ζευγάρι if-else:
if (x!=0) {
System.out.print("Το x δεν είναι μηδέν, άρα έχει αντίστροφο, τον "+ 1./x+"\n");
}//if
else {
System.out.print("Το x είναι μηδέν, δεν έχει αντίστροφο!\n");
}//else

Επίσης, με else if:

if(mera==7) {
    System.out.print("Κυριακή\n");
    //κάνε κάτι
}//if
else if(mera==6) {
    System.out.print("Σάββατο\n");
    //κάνε κάτι
}//else if
else {
    System.out.print("Καθημερινή\n");
    //κάνε κάτι άλλο
}//else

Όταν υπάρχει else, όπως και με τα else if, η χρήση των {} είναι υποχρεωτική, ακόμα και για μία εντολή. Τέλος να πούμε ότι από τη στιγμή που ανοίγουμε την αγκύλη { για να γράψουμε τις εντολές μας, μπορούμε να γράψουμε οτιδήποτε, ακόμα και άλλα μπλοκ if!

Από τα block if, else if και else μιας δομής if, μόνο ένα εκτελείται! Όταν αυτό εκτελεστεί, το πρόγραμμα συνεχίζει ΜΕΤΑ τη δομή if. Δε θα κοιτάξει καν τις άλλες boolean!!

Αυτό πρακτικά σημαίνει ότι ακόμα και αν περισσότερες από μία boolean είναι true, μόνο ένα block εντολών θα εκτελεστεί, αυτό που αντιστοιχεί στην πρώτη boolean που θα βγει true.

Πρόγραμμα για την εντολή if:
Κώδικας: Επιλογή όλων
//αρχείο IfTest.java
import java.util.Scanner;

public class IfTest {

public static void main (String[] args) {

    int i;
    Scanner sc = new Scanner(System.in);

    System.out.print("Δώσε έναν ακέραιο\n");
    i = sc.nextInt();

    if (i<0) {
    System.out.print("\nΟ αριθμός είναι αρνητικός\n");
    }//if
    else if (i < 10) {
    System.out.print("\nΟ αριθμός είναι μικρός\n");
    }//else if
    else if (i < 1000) {
    System.out.print("\nΟ αριθμός είναι μεγάλος\n");
    }//else if
    else {
    System.out.print("\nΟ αριθμός είναι πολύ μεγάλος!\n");
    }//else
}//main

}//class


Κώδικας: Επιλογή όλων
//αρχείο IfTest2.java
public class IfTest2 {

public static void main (String[] args) {

    System.out.print("Ακολουθεί ένα if block με ένα if και τρία else if.\n"+
    "Η συνθήκη της if είναι false, ενώ αυτές των else if είναι και οι τρείς true.\n"+
    "Κάθε else if τυπώνει ένα μύνημα στην οθόνη. Ποιά μηνύματα θα τυπωθούν άραγε;\n\n\n");

    if (5>6) {    //FALSE!
    System.out.print("Αυτή η εντολή δε θα εκτελεστεί ποτέ... το 5>6 είναι false!\n");
    }//if
    else if (5>4) {    //TRUE!
    System.out.print("Μπίκα στο πρώτο else if.\n");
    }//else if 1
    else if (10>5) {    //TRUE!
    System.out.print("Μπίκα στο δεύτερο else if.\n");
    }//else if 1
    else if (20>10) {    //TRUE!
    System.out.print("Μπίκα στο τρίτο else if.\n");
    }//else if 1
   
    System.out.print("Μόλις βγήκα από τη δομή if!\n");
}//main

}//class


Το δεύτερο πρόγραμμα θα σας δείξει ακριβώς πως δουλεύει η εντολή if όταν βρίσκει true, και πως όταν βρίσκει false.


Η δομή switch
Η δομή switch είναι μία επιπέον δομή ελέγχου. Στην ουσία δεν προσφέρει επιπέον δυνατότητες, καθώς (όπως θα διαπιστώσετε και μόνοι σας) ό,τι κάνει μπορείτε να το κάνετε και με την if. Παρ' όλα αυτά στις περιπτώσεις που χρησιμοποιούμε την switch, το κάνουμε γιατί κάνει τη δουλειά πιο εύκολα, με λιγότερο γράψιμο.

Η δομή της switch είναι η εξής:
Κώδικας: Επιλογή όλων
switch (...byte ή short ή char ή int...) {
case ...μία τιμή... :
...εντολές εντολές εντολές...

case ...μία άλλη τιμή...:
...άλλες εντολές...
υπ
...κτλ κτλ...

default:
...εντολές εντολές εντολές...
}//switch



Αρχικά λοιπόν γράφουμε τη λέξη switch και σε παρένθεση μία μεταβλητή byte, short, char ή int και ανοίγουμε ακγύλη {
Μετά ακολουθεί η λέξη κλειδί case, μία σταθερή έκφραση (ή final μεταβλητή) ίδιου τύπου με την μεταβλητή στην παρένθεση, το σύμβολο ':'
και ένα σύνολο εντολών.
Μετά ένα ξανά η case με μία άλλη τιμή και άλλες εντολές.
Η διαδικασία επαναλλαμβάνεται όσες φορές θέλουμε. Τέλος, προαιρετικά υπάρχει και η default: με το δικό της σύνολο εντολών. Παρατηρήστε ότι δε χρειάζεται η χρήση αγκυλών στις εντολές των case.

Ακολουθεί ένα παράδειγμα:

Κώδικας: Επιλογή όλων
char i='c';
switch (i) {

case 'a':
System.out.print("Ο χαρακτήσας είναι ο a...\n");
System.out.print("Βρίσκεσαι στο case 'a': Θα μπορούσαμε να έχουμε και άλλες πολλές εντολές\n");

case 'b':
System.out.print("Ο χαρακτήσας είναι ο b...\n");
System.out.print("Βρίσκεσαι στο case 'b': Θα μπορούσαμε να έχουμε και άλλες πολλές εντολές\n");

case 'c':
System.out.print("Ο χαρακτήσας είναι ο c...\n");
System.out.print("Βρίσκεσαι στο case 'c': Θα μπορούσαμε να έχουμε και άλλες πολλές εντολές\n");

case 'h':
System.out.print("Ο χαρακτήσας είναι ο h...\n");
System.out.print("Βρίσκεσαι στο case 'h': Θα μπορούσαμε να έχουμε και άλλες πολλές εντολές\n");

default:
System.out.print("Ο χαρακτήσας είναι κάποιος άλλος...\n");
System.out.print("Βρίσκεσαι στο default: Θα μπορούσαμε να έχουμε και άλλες πολλές εντολές\n");
}//switch



Ας δούμε τώρα πως λειτουργεί.
Το πρόγραμμα διαβάζει τη μεταβλητή εντός των παρενθέσεων και στη συνέχεια ελέγχει μία-μία τις τιμές των case μέχρι να βρει κάποια που είναι η τιμή της μεταβλητής. Αν βρεθεί αυτή η τιμή, το πρόγραμμα εκτελεί τις εντολές που βρίσκονται κάτω από την case, μέχρι το τέλος της δομής switch. Αυτό σημαίνει (σε αντίθεση με την if-else if) ότι θα εκτελεστούν και οι εντολές των άλλων case, ακόμα και αν οι τιμές τους δεν ταιριάζουν με αυτή της μεταβλητής μας.
Τέλος, η default παίζει το ρόλο της else στη δομή if. Είναι δηλαδή το σενάριο που θα εκτελεστεί ακόμα και αν καμία case δεν ταιριάξει. Αν πχ έχουμε 5 cases και την default, και η μεταβλητή μας ταιριάξει με την 4η case, θα εκτελεστούν οι εντολές της 4ης, της 5ης και της default.
Σημειώστε ότι (αντίθετα με την if -else if) οι τιμές των case πρέπει να εμφανίζοτναι μόνο μία φορά (δηλαδή οι περιπτώσεις να μην αλληλοεπικαλύπτονται).

Αν θέλουμε δύο ή περισσότερες περιπτώσεις για τη μεταβλητή να αντιστοιχούν στις ίδιες εντολές τότε γράφουμε τις case όλες μαζί:

Κώδικας: Επιλογή όλων
int i;
//...δώσε μία τιμή στο i
switch (i) {
case 1: case3: case 5:
System.out.print("μονός αριθμός\n");

case 2: case4: case 6:
System.out.print("ζυγός αριθμός\n");
}//switch


Η εντολή break
Υπάρχει η δυνατότητα οποιαδήποτε στιγμή θέλουμε να «ανακόψουμε» την εκτέλεση μίας δομής switch, και να πούμε στο πρόγραμμα να εξέλθει από αυτή. Απλώς γράφοντας τη λέξη-κλειδί break. Αυτό χρησιμοποιείται πολύ συχνά όταν δε θέλουμε η εκτέλεση του προγράμματος να συνεχίσει στα άλλα case.
Ας δούμε ένα παράδειγμα. Γράψτε και τρέψτε το ακόλουθο προπγραμμα:

Κώδικας: Επιλογή όλων
//αρχείο SwitchTest.java
import java.util.Scanner;

public class SwitchTest {
public static void main(String s[]) {

   int day;
   boolean work=true;
   Scanner sc = new Scanner(System.in);

   System.out.print("Δώσε ένα ακέραιο από 1 εώς 7\n");
   day = sc.nextInt();

   switch (day) {
   case 1:
   System.out.print("Δευτέρα\n");
   work = true;
   break;

   case 2:
   System.out.print("Τρίτη\n");
   work = true;
   break;

   case 3:
   System.out.print("Τετάρτη\n");
   work = true;
   break;

   case 4:
   System.out.print("Πέμπτη\n");
   work = true;
   break;

   case 5:
   System.out.print("Παρασκευή\n");
   work = true;
   break;

   case 6:
   System.out.print("Σάββατο\n");
   work = false; //λέμε τώρα...
   break;

   case 7:
   System.out.print("Κυριακή\n");
   work = false;
   break;

   default:
   System.out.print("Δεν υπάρχει "+day+"η μέρα\n");
   work=false;
   break;
   }//switch

   if (work) System.out.print("Σήμερα δουλεύω...\n");

}//main
}//class

Παίξτε με αυτό το πρόγραμμα: τρέξτε το δίνοντας διάφορες τιμές, τροποποιείστε το σβήνοντας μερικές break και δείτε τι συμβαίνει!


Δομές επανάληψης
Ας πούμε ότι θέλετε φτιάξετε ένα πρόγραμμα που εμφανίζει στην οθόνη τους αριθμούς από το 1 εώς το 1000.
Με τις γνώσεις μας ως τώρα μάλλον θα γράφαμε κάτι σαν
Κώδικας: Επιλογή όλων
System.out.print(1);
System.out.print(2);
System.out.print(3);
System.out.print(4);
//... ... ... Χίλιες φορές!! ... ... ...


Σωστά;
Νομίζω θα συμφωνίσετε ότι θα ήταν εντελώς χαζό αν αυτή ήταν η μοναδική λύση στον προγραμματισμό! Ευτυχώς δεν είναι, γιατί υπάρχουν οι δομές επανάληψης. Αυτές είναι σύνολα εντολών που εκτελούνται πολλές φορές. Στην πραγματικότητα εκτελούνται ασταμάτητα, μέχρι να πούμε στο πρόγραμμα να σταματήσει. Υπάρχουν τρία είδη δομών επανάληψης: η for, η while και η do-while.


1. Η δομή for
Θα αρχίσουμε με την πιο συχνά χρησιμοποιούμενη, και ίσως πιο περίπλοκη: τη δομή for.

Η γράφεται ως εξής:
Κώδικας: Επιλογή όλων
for (έντολή 1; μία boolean; εντολή 2) κύρια εντολή

ή, όπως και στην περίπτωση της if:

for (έντολή 1; μία boolean; εντολή 2) {
...Πολλές εντολές...
}


Ας δούμε τώρα τι κάνουν όλα αυτά: οι εντολές 1 και 3 στην παρένθεση μπορούν να είναι οποιεσδήποτε εντολές. Η boolean ανάμεσά τους καθορίζει αν το block εντολών θα εκτελεστεί ή όχι.
Η διαδικασία που ακολουθεί το πρόγραμμα είναι η εξής:

1. Όταν το πρόγραμμα φτάσει στη θέση της for, εκτελεί την εντολή 1, αυτή που γράφουμε πρώτη στην παρένθεση.
2. Ελέγχει την boolean. Αν είναι false εξέρχεται της δομής for και συνεχίζει το υπόλοιπο πρόγραμμα. Αν είναι true προχωράμε στο βήμα 3.
3. Εκτελεί την κύρια εντολή (αυτή μετά την παρένθεση), ή τις εντολές που βρίσκονται μέσα στις αγκύλες {}.
4. Εκτελεί την εντολή 2 εντός της παρένθεσης
5. Επιστρέφει στο βήμα 2. Η διαδικασία θα επαναλαμβάνεται όσο ο έλεγχος στο βήμα 2 δώσει true.

Παρατηρήσεις: η boolean θα ελέγχεται κάθε φορα που περνάμε από το βήμα 2. Οι εντολές 1 και 3 εντός των παρενθέσεων είναι για δική μας ευκολία. Θα μπορούσαν απλώς να εμφανίζονται η πρώτη ακριβώς πριν το for και η δεύτερη ως τελευταία εντολή πριν την αγκύλη }.

Συνηθέστερη χρήση της for είναι κάτι σαν αυτό:
Κώδικας: Επιλογή όλων
for (int i=1; i<3; ++i) System.out.print(i+"\n");


Αυτή η εντολή θα κένει τα εξής:
1. Δημιουργεί την μεταβλητή i και της δίνει την τιμή 1.
2. Ελέγχει αν η i<3, βρίσκει ότι είναι.
3. Εκτελεί την εντολή System.out.print(i+"\n") Η οποία τυπώνει το 1 στην οθόνη (αφού προς το παρόν i=1)
4. Εκτελεί την εντολή i++, το i είναι τώρα 2
5. Ελέγχει αν i<3. Είναι!
6. Εκτελεί ξανά την System.out.print(i+"\n") και τυπώνει στην οθόνη το 2 αυτή τη φορά.
7. Εκτελεί την i++, τώρα i=3
8. Ελέγχει αν i<3. Βρίσκει false και εξέρχεται από την for για να συνεχίσει με ό,τι άλλο υπάρχει μετά.

Οποιαδήποτε από τις οι τρείς εκφράσεις μέσα στην παρένθεση (ακόμα και όλες!) μπορεί να είναι κενές! Σε αυτή την περίπτωση οι εντολές 1 και 2 απλώς δε θα κάνουν τίποτα, και η boolean θα θεωρηθεί αυτομάτως true.
Σε κάθε περίπτωση όμως πρέπει να εμφανίζονται δύο ερωτηματικά ';'

Ας δούμε μερικά παραδείγματα:
Κώδικας: Επιλογή όλων
for (i=0; i<=1000; ++i) System.out.print(i+"\n");

i=10;
for (;i>0 ;) {// εδώ η 1η και 3η εντολή είναι κενές
i--;
System.out.print(i*i+"\n");
}//for


//αυτή η εντολή θα τυπώνει για πάντα τελείες στη οθόνη.. Μη γράψετε κάτι τέτοιο σε πρόγραμμα, δε θα μπορείτε να το σταματήσετε!!
for (; ;) System.out.print(".");


Παράδειγμα πραγράμματος:
Κώδικας: Επιλογή όλων
//αρχείο ForTest.java
import java.util.Scanner;

public class ForTest {

public static void main(String s[]) {

   int i=0;
   for (i=0; i<1000; i+=2;) System.out.print(i+"\n");

}//main
}//class


Πειραματιστείτε με το παραπάνω πρόγραμμα. Αλλάξτε τις εντολές εντός των παρενθέσεων, αφήστε τις κενές ακόμα! αλλάξτε την εντολή που επαναλαμβάνεται, προσθέστε περισσότερες αν θέλετε και γενικά κάντε οτιδήποτε! Μόνο προσέξτε η συνθήση booleean να γίνεται κάποτε false. Αν πχ σβήσετε το i+=1 (και δε το αντικαταστείσετε με κάτι αντίστοιχο), θα είναι πάντα i<1000 και άρα δε θα βγείτε ποτέ από τη for :(
Ώς έμπειροι προγραμματιστές που έχετε αρχίσει να γίνεστε, θα πρέπει να προσέχετε τι γράφετε!

Αν φτάσετε στο σημείο που περιγράφω παραπάνω, για να σταματήσετε το πρόγραμμα απλώς πατήστε Ctrl+C. Αυτό λέει στο τερματικό να σταματήσει ό,τι κάνει αυτή τη στιγμή.




2. Η δομή while
Αν έχετε καταλάβει καλά τη δομή for, η while θα σας φανεί πολύ εύκολη. Γράφεται παρόμοια με την if: παίρνει σε παρένεση μία boolean, και μετά μία εντολή, ή ένα block εντολών. Κάπως έτσι δηλαδή:

Κώδικας: Επιλογή όλων
while (...μία boolean...) εντολή;

ή

while (...μία boolean...)
{
Εντολές
}


Τί κάνει; Ελέγχει κάθε φορά τη boolean, και όσο τη βρίσκει true θα εκτελεί την εντολή ή το block εντολών. Κάνει δηλαδή ό,τι και η for, όμως με την εντολή 1 και εντολή 3 κενές. Με λίγα λόγια οι εκφράσεις
Κώδικας: Επιλογή όλων
for ( ; ...μία boolean... ; )
και
while (...η ίδια boolean...)

είναι πανομοιότυπες. Από αυτή την άποψη η while είναι απλώς μία ειδική περίπτωση της for, θα λέγαμε μία πιο εκλεπτισμένη γραφή της.

Ακολουθεί ενδεικτικά ένα παράδειγμα:

Κώδικας: Επιλογή όλων
//αρχείο WhileTest.java
import java.util.Scanner;

public class WhileTest {
public static void main(String args[]) {


   Scanner sc = new Scanner(System.in);
   final long j=1000;
   long i=1;

   System.out.print("Καλωσήλθατε στο παιχνίδι πρόσθεσης!!\n"+
   "Δίνετε αριθμούς, θετικούς ή αρνητικούς, και μπαίνουν όλοι σε ένα σάκο.\n"+
   "σκοπός είναι να μαζέψετε ακριβώς 1000!\n");

   while (i!=j) {
   System.out.print("\nΈχουμε "+i+" στο σάκο.\nΠροσθέστε κάτι: ");
   i = i + sc.nextLong(); // μη σας μπερδεύει αυτή η έκφραση! το sc.nextLong() συμβολίζει ένα απλό long! Περισσότερα στο επόμενο κεφάλαιο...
   }//while

   System.out.print("Μπράβο! Νικήσατε!\nΕυχαριστούμε πολύ που παίξατε!\n"); // Πάντα γράφουμε ευγενικά προγράμματα :)

}//main
}//class



3. Η δομή do-while

Είναι σχεδόν ίδια με την while. Η διαφορά έγκειται στο γεγονός ότι η συνθήση boolean ελέγχεται μετά την εκτέλεση του block εντολών, και όχι πριν όπως με την while. Αυτό πρακτικά σημαίνει ότι το block εντολών θα εκτελεστεί τουλάχιστον μία φορά. Η ορθογραφία της δομής είναι η εξής:

Κώδικας: Επιλογή όλων
do εντολή
while (...μία boolean...);

ή

do {
...εντολές...
}//do
while(...μία boolean...);


Προσέξτε το ';' μετά την παρένθεση με τη boolean!

Ας δούμε ένα παράδειγμα:

Κώδικας: Επιλογή όλων
//αρχείο DoWhileTest.java
public class DoWhileTest {
public static void main(String args[]) {
   int i=0;
   do System.out.print((i++)+"\n");
   while (i<10);
   
   System.out.print("\nΤέλος\n");
}//main
}//class



Οι εντολές break και continue - δομές επανάληψης με label

Την εντολή break τη συναντήσαμε και στη δομή switch. Αυτό που έκανε είναι να εξέρχεται του block. Ακριβώς με τον ίδιο τρόπο δουλέυει και σε ένα block for, while ή do-while. Το τερματίζει, και συνεχίζει τη ροή του προγράμματος με ό,τι ακολουθεί.

Πολύ χρήσιμη επίσης είναι η εντολή continue. Αυτό που κάνει είναι να ξαναπηγαίνει (άμεσα) στην αρχή του block, παρακάμπτοντας ό,τι ακολουθεί.
Πιο αναλυτικά θα λέγαμε:
Σε μία δομή for (i) εκτελεί την εντολή 2 εντός των παρενθέσεων, (ii) ελέγχει την boolean και συνεχίζει κατά τα γνωστά: αν είναι true εκτελεί το block, αν όχι τερματίζει την for.
Σε μία while ή do-while απλώς ελέγχει την boolean και συνςχίζει κατά τα γνωστά.
Ας δούμε δύο παραδείγματα:

Κώδικας: Επιλογή όλων
//αρχείο BreakFor.java
import java.util.Scanner;

public class BreakFor {
public static void main(String[] s) {

   Scanner sc = new Scanner(System.in);
   int msg=1;

   while (true) {// η while (true) είναι μια δομή που δεν τερματίζει ποτέ από μόνη της...

   System.out.print("\nΔώσε έναν ακέραιο, ή -1 για να τερματίσεις το πρόγραμμα\n");
   msg = sc.nextInt();

   if(msg==-1){break;}
   else {System.out.print("έγραψες "+msg);}
   }//for

   System.out.print("Γειά σας!\n");

}//main
}//class


Κώδικας: Επιλογή όλων
//αρχείο ContinueFor.java
import java.util.Scanner;

public class ContinueFor {
public static void main(String[] s) {
   //Αυτό το πρόγραμμα τυπώνει όλους τους αριθμούς από το 1 εώς το 20, εκτώς από ένα!
   Scanner sc = new Scanner(System.in);
   int i,j;

   System.out.print("Δώσε έναν ακέραιο από το 1 εώς το 20, και εγώ θα σου πώ τους υπόλοιπους...\n");
   j = sc.nextInt();
   
   if (j<20 && j>0) {
   System.out.print("Ορίστε οι υπόλοιποι:\n\n");
   
   for(i=1; i<20; i++) {

   if (i==j) continue; //όταν το i==j, η επόμενη εντολή δε θα εκτελεστεί!
   System.out.print(i+"\n");
   }//for
   
   }//if
   else {
   System.out.print("Ο αριθμός που  δώσατε δεν είναι μεταξύ 0 και 20...\n");
   }//else
   

}//main
}//class


Όπως έχουμε ήδη πει (και φαίνεται στο παραπάνω πρόγραμμα), μπορεί κάλλιστα να υπάρχουν δομές επανάληψης μέσα σε άλλες δομές επανάληψης, δομές ελέγχου μέσα σε δομές επανάληψης, και ότι άλλο συνδιασμό μπορείτε να φανταστείτε! Όταν ανοίγετε την αγκύλη {, μπορείτε να γράψετε οτιδήποτε μέσα.
Στην περίπτωση που υπάρχει μία δομή (ας την πούμε Β) μέσα σε μία άλλη (την Α), μπορεί να υπάρξει ένα μπέρδεμα με τις εντολές break και continue, αν εμφανίζονται στην εσωτερική, δηλαδή στην Β. Ας δούμε το ακόλουθο παράδειγμα:

Κώδικας: Επιλογή όλων
int i=0;j=0;

for (;i<=5;++i) {
System.out.print("\nείμαι η εξωτερική δομη: i= "+i+"\n");
for (j=0;j<=5;++j) {

if (j==3) continue;
System.out.print("είμαι η εσωτερική δομη: ij= "+(i*10+j)+"\n");

}//for j
}//for i

System.out.print("τέλος\n");


Προσέξτε καλά τον παραπάνω κώδικα και σκεφτήτε τι κάνει η continue.. Κανονικά ξαναρχίζει να εκτελεί ένα block. Αλλά... ποιό;; Το block του εξωτερικόυ for (αυτού με το i) ή του εσωτερικού (αυτού με το j);

Σας προτρέπω να γράψετε το παραπάνω σε ένα πρόγραμμα, και αφού σκεφτείτε καλά τι θα τύπωνε στη μία περίπτωση και τι στην άλλη, να το τρέξετε για να διαπιστώσετε μόνοι σας!
Η απάντηση όπως θα δείτε είναι ότι η continue ξαναρχίζει το εσωτιρικό block. Το ίδιο θα συνέβαινε και με την εντολή break. Υπάρχει όμως η δυνατότητα να πούμε στο πρόγραμμα το αντίθετο! Πως;
Απλούστατα δίνουμε ένα όνομα στα block, και λέμε στην break ή στην continue ποιό block να διακόψουν ή να ξαναξεκινήσουν! Θεωρητικά μπορούμε να δίνουμε ονόματα σε όσα block θέλουμε, όμως στην πράξη το κάνουμε μόνο όταν χρειάζεται (κάτι που συμβαίνει πολύ σπάνεια).
Ας δούμε πως γίνεται: θα γράψω το προηγούμενο παράδειγμα δίνοντας όνομα και στις δύο for, και λέγοντας στο πρόγραμμα να κάνει continue την εσωτερική:

Κώδικας: Επιλογή όλων
int i=0;j=0;

prwto: for (;i<=5;++i) {
System.out.print("\nείμαι η εξωτερική δομη: i= "+i+"\n");
deytero: for (j=0;j<=5;++j) {

if (j==3) continue prwto;
System.out.print("είμαι η εσωτερική δομη: ij= "+(i*10+j)+"\n");

}//for j
}//for i

System.out.print("τέλος\n");


Δηλαδή γράφουμε το όνομα, το σύμβολο ':' και συνεχίζουμε κανονικά. Έτσι έχουμε "βαφτίσει" τη δομή επανάλληψης (ή τη switch) μας. Έπειτα γράφουμε
Κώδικας: Επιλογή όλων
break όνομα;
ή
continue όνομα;

Με τον ίδιο ακριβώς τρόπο βαφτίζουμε και τις δομές while κα do-while. Να προσθέσουνε ότι δε μπορούμε να βαφτίζουμε δομές if, γιατί αυτές δεν «συνεργάζονται» με τις εντολές break και continue. Στην περίπτωση που βαφτίζουμε μία δομή switch, μπορούμε να χρησιμοποιήσουμε μόνο την break με το όνομά της.


Περί αγκύλων και εμβέλειας μεταβλητών

Κλείνοντας αυτό το τεράστιο κεφάλαιο θα αναφέρουμε κάποια πράγματα περί μεταβλητών, και πόσο αυτές «ζούν».

i. Μπορούμε να δηλώνουμε μεταβλητές παντού. Ακόμα και μέσα σε ένα block εντολών. Στην περίπτωση που το block αυτό είναι μία δομή επανάλληψης, αυτό που θα γίνει είναι (φυσικά) όχι να δηλώνεται κάθε φορά που το block επαναλλαμβάνεται, αλλά μόνο την πρώτη! Είναι αρκετά συνηθισμένο επισης να δηλώνουμε μεταβλητές στην πρώτη εντολή εντός παρενθέσεων μίας δομής for:

Κώδικας: Επιλογή όλων
for (int i=0; i<100; ++i) ... ... ...


ii. Μαθαινοντας τόσες δομές σε αυτό το κεφάλαιο είναι λογικό ότι στα προγράμματά σας θα χρησιμοποιείτε πολλά block (δηλαδή κομμάτια κώδικα που οριοθετούνται από αγκύλες {}...)
Προσέξτε τώρα αυτό το σημείο: όταν μέσα σε ένα block δηλώνουμε μία μεταβλητή (γεννιέται μία μεταβλητή), αυτή θα ζεί μέχρι να κλείσει αυτό το block! Έξω από το block παύει να υπάρχει! Αυτό σημαίνει ότι δεν μπορούμε να τη χρησιμοποιήσουμε, αλλά μπορούμε κάλλιστα να χρησιμοποιήσουμε το ίδιο όνομά για να δηλώσουμε μία άλλη μεταβλητή. Ορίστε ένα παράδειγμα.

Κώδικας: Επιλογή όλων
if (i<50) {
int add = 50; //ορίζουμε την μεταβλητή add ΜΕΣΑ στο block

//γράφουμε άλλες εντολές... η add υπάρχει και μπορεί να χρησιμοποιηθεί

}//if  <-- Εδώ κλείνει το block

//To block έκλεισε. Η add δεν υπάρχει πια... Αν προσπαθήσετε να τη χρησιμοποιήσετε, ο compiler θα σας πεταξει error!

//Η add δεν υπάρχει... άρα το όνομα 'add' είναι ελεύθερο να ξαναχρησιμοποιηθεί για μια άλλη μεταβλητή!!
boolean add = false;


Με λίγα λόγια: κάθε φορά που μία αγκύλη } κλείνει ένα block, μαζί του χάνονται όλες οι μεταβλητές που «γεννήθηκαν» μέσα του.

Γενικά όσο πιο «τοπική» είναι μία μεταβλητή, τόσο πιο γρήγορη είναι η προσπέλασή της από το πρόγραμμα. Κρατήστε αυτή την πρόταση αν σας ενδιαφέρουν πιο αποδοτικά προγράμματα.
Υπό αυτή την έννοια έχει νόημα να ανοίγουμε και να κλείνουμε αγκύλες μέσα στο πρόγραμμά μας, χωρίς κανένα άλλο λόγο. Χωρίς καμία if ή for ή οτιδήποτε άλλο. Πχ:

Κώδικας: Επιλογή όλων
/αρχείο BrTest.java

public class BrTest {
public static void main(String[] args) {

   {
   int i=9;
   System.out.print("Μέσα σε block: "+i+"\n");
   }

   System.out.print("Έξω από το block\n");
   {
   boolean i=9;
        System.out.print("Μέσα σε άλλο block: "+i+"\n");
   }
   // προσέξτε ότι με μία μεταβλητή, την i σε διαφορετικά στάδια του προγράμματος εκφράσαμε μία int ΚΑΙ μία boolean!
}//main
}//class



Προηγούμενο: Τελεστές
Επόμενο: Κλάσεις, Αντικείμενα και Μέθοδοι

Creative Commons License
Η εργασία υπάγεται στην άδεια Creative Commons Αναφορά-Παρόμοια διανομή 3.0 Ελλάδα
Τελευταία επεξεργασία από alkismavridis και 19 Μάιος 2012, 17:17, έχει επεξεργασθεί 1 φορά/ες συνολικά
Γνώσεις ⇛ Linux: Μέτριο┃ Προγραμματισμός: Java, Assembly, Fortran, μαθαίνω C/X11┃ Αγγλικά: Μέτρια
Λειτουργικό σε Η/Υ ϰ μοντέλο: Ubuntu 14.04 64-bit ┃ Τρόπος εγκατάστασης: Live USB
Προδιαγραφές ⇛ Desktop: Intel i5 2320 3.00GHz.┃ MotherBoard: Asus p8h61 -m pro
Προδιαγραφές ⇛ RAM: 4GB ┃ Τροφοδοτικό Corsair CX430

GPU: Intel 2nd Generation Core Processor Family Integrated Graphics Controller [8086:0102] {i915}
5 eth0: Realtek RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 06) ⋮ wlan0: 0b05:1723 ASUS WL-167G v2 802.11g Adapter [Ralink RT2571W]
Οθόνη Schaub Lorenz (Tv)
alkismavridis
punkTUX
punkTUX
 
Δημοσιεύσεις: 273
Εγγραφή: 18 Μαρ 2009, 18:46
Εκτύπωση

Re: Εισαγωγή στην Java - κεφ. 5

Δημοσίευσηαπό alkismavridis » 16 Μάιος 2012, 20:42

ορίστε το 5ο κεφάλαιο..
Περιμένω τα σχόλια και τις διορθώσεις σας!

(Συγγνώμη για την καθυστέρηση)
Γνώσεις ⇛ Linux: Μέτριο┃ Προγραμματισμός: Java, Assembly, Fortran, μαθαίνω C/X11┃ Αγγλικά: Μέτρια
Λειτουργικό σε Η/Υ ϰ μοντέλο: Ubuntu 14.04 64-bit ┃ Τρόπος εγκατάστασης: Live USB
Προδιαγραφές ⇛ Desktop: Intel i5 2320 3.00GHz.┃ MotherBoard: Asus p8h61 -m pro
Προδιαγραφές ⇛ RAM: 4GB ┃ Τροφοδοτικό Corsair CX430

GPU: Intel 2nd Generation Core Processor Family Integrated Graphics Controller [8086:0102] {i915}
5 eth0: Realtek RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 06) ⋮ wlan0: 0b05:1723 ASUS WL-167G v2 802.11g Adapter [Ralink RT2571W]
Οθόνη Schaub Lorenz (Tv)
alkismavridis
punkTUX
punkTUX
 
Δημοσιεύσεις: 273
Εγγραφή: 18 Μαρ 2009, 18:46
Εκτύπωση


  • ΣΧΕΤΙΚΑ ΘΕΜΑΤΑ
    ΑΠΑΝΤΗΣΕΙΣ
    ΠΡΟΒΟΛΕΣ
    ΣΥΓΓΡΑΦΕΑΣ

Επιστροφή στο Μαθήματα Java