College Compass

College Compass

Software Development · CN4001

Εβδομάδα 6: Βρόχοι και πίνακες

  • java
  • loops
  • break-continue
  • arrays

Σημειώσεις μελέτης βασισμένες στο «Learn Programming with Java – Lesson 3». Οι διαφάνειες, με τα διαγράμματα ροής, τα παραδείγματα και τις ασκήσεις τους, βρίσκονται στο Moodle.

Ένας βρόχος (loop) επαναλαμβάνει ένα κομμάτι κώδικα όσο ισχύει μια συνθήκη. Έτσι, αντί να γράψεις την ίδια εντολή δέκα φορές, τη γράφεις μία φορά και λες στον υπολογιστή πόσες φορές να την κάνει. Η Java έχει τέσσερα είδη βρόχων:

Βρόχος Πότε τον διαλέγεις
for όταν ξέρεις πόσες επαναλήψεις θέλεις
while όταν ο αριθμός των επαναλήψεων εξαρτάται από μια συνθήκη
do-while όπως ο while, αλλά το σώμα εκτελείται τουλάχιστον μία φορά
enhanced for για να περάσεις από όλα τα στοιχεία ενός πίνακα, χωρίς μετρητή

Ο βρόχος for

int sum = 0;
for (int i = 1; i <= 10; i++) {
    sum += i;
}
System.out.println("Άθροισμα: " + sum);   // Άθροισμα: 55

Η παρένθεση έχει τρία μέρη, χωρισμένα με ;:

  1. αρχικοποίηση (int i = 1): εκτελείται μία φορά, στην αρχή·
  2. συνθήκη (i <= 10): ελέγχεται πριν από κάθε επανάληψη· όταν γίνει false, ο βρόχος σταματά·
  3. ενημέρωση (i++): εκτελείται μετά από κάθε επανάληψη.

Το βήμα δεν είναι υποχρεωτικά 1. Για τους ζυγούς από το 2 έως το 20 γράφεις for (int i = 2; i <= 20; i += 2), και για αντίστροφη μέτρηση for (int i = 5; i > 0; i--).

Ένθετοι βρόχοι

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

for (int row = 1; row <= 3; row++) {
    for (int col = 1; col <= 3; col++) {
        System.out.print(row * col + "\t");
    }
    System.out.println();
}
1	2	3
2	4	6
3	6	9

Ο βρόχος while

Ο while ελέγχει τη συνθήκη πριν από κάθε επανάληψη. Είναι κατάλληλος όταν δεν ξέρεις από πριν πόσες επαναλήψεις θα χρειαστούν. Ένα κλασικό παράδειγμα είναι το άθροισμα των ψηφίων ενός αριθμού:

int number = 4096;
int digitSum = 0;

while (number > 0) {
    digitSum += number % 10;   // παίρνουμε το τελευταίο ψηφίο
    number /= 10;              // και το «κόβουμε»
}
System.out.println(digitSum);  // 4 + 0 + 9 + 6 = 19

Πρόσεξε ότι κάτι μέσα στον βρόχο πρέπει να αλλάζει τη συνθήκη (εδώ το number /= 10). Αλλιώς ο βρόχος δεν τελειώνει ποτέ.

Ο αλγόριθμος του Ευκλείδη για τον μέγιστο κοινό διαιρέτη (ΜΚΔ) είναι επίσης ένας while: όσο το b δεν είναι 0, υπολογίζεις το υπόλοιπο a % b, το a γίνεται b και το b γίνεται το υπόλοιπο. Όταν το b μηδενιστεί, το a είναι ο ΜΚΔ.

int a = 84, b = 36;
while (b != 0) {
    int remainder = a % b;
    a = b;
    b = remainder;
}
System.out.println("ΜΚΔ: " + a);   // ΜΚΔ: 12

Ο βρόχος do-while

Ο do-while εκτελεί πρώτα το σώμα και μετά ελέγχει τη συνθήκη, άρα τρέχει τουλάχιστον μία φορά. Είναι ιδανικός για μενού και για επανάληψη ενός προγράμματος «όσο ο χρήστης θέλει»:

Scanner input = new Scanner(System.in);
String again;

do {
    System.out.print("Δώσε έναν αριθμό: ");
    int n = input.nextInt();
    System.out.println("Το τετράγωνό του είναι " + (n * n));

    System.out.print("Ξανά; (y/n): ");
    again = input.next();
} while (again.equalsIgnoreCase("y"));

break και continue

  • break: βγαίνει αμέσως από τον βρόχο.
  • continue: παραλείπει το υπόλοιπο της τρέχουσας επανάληψης και πάει στην επόμενη.
int sum = 0;
for (int i = 1; i <= 20; i++) {
    if (i % 4 == 0) continue;   // παραλείπει τα πολλαπλάσια του 4
    sum += i;
    if (sum > 30) break;        // σταματά μόλις το άθροισμα ξεπεράσει το 30
}
System.out.println(sum);        // 1+2+3+5+6+7+9 = 33

Πίνακες

Ένας πίνακας (array) κρατά πολλές τιμές του ίδιου τύπου κάτω από ένα όνομα. Κάθε τιμή έχει μια θέση, τον δείκτη (index), που ξεκινά από το 0.

int[] scores = {72, 85, 64, 90};      // πίνακας με 4 στοιχεία
double[] prices = new double[3];      // 3 θέσεις, όλες 0.0 στην αρχή

System.out.println(scores[0]);        // 72, το πρώτο στοιχείο
scores[2] = 70;                       // αλλάζει το τρίτο στοιχείο
System.out.println(scores.length);    // 4

Τρία πράγματα που πρέπει να θυμάσαι:

  • Ένας πίνακας είναι συγκεκριμένου τύπου. Σε έναν int[] δεν μπορείς να βάλεις "πενήντα": το πρόγραμμα δεν μεταγλωττίζεται καν.
  • Το μέγεθός του είναι σταθερό: αφού δημιουργηθεί, δεν μεγαλώνει.
  • Οι θέσεις πάνε από 0 έως length - 1. Το scores[4] σε πίνακα 4 στοιχείων προκαλεί, όταν τρέξει το πρόγραμμα, ArrayIndexOutOfBoundsException.

Για να περάσεις από όλα τα στοιχεία, χρησιμοποιείς έναν for με δείκτη:

double total = 0;
for (int i = 0; i < scores.length; i++) {
    total += scores[i];
}
System.out.printf("Μέσος όρος: %.2f%n", total / scores.length);

Ο enhanced for

Όταν θέλεις απλώς να «διαβάσεις» κάθε στοιχείο με τη σειρά, ο enhanced for (ή for-each) είναι πιο απλός, γιατί δεν χρειάζεται δείκτη:

int[] grades = {78, 91, 66, 84, 70};
int total = 0;

for (int grade : grades) {     // «για κάθε grade μέσα στο grades»
    total += grade;
}
System.out.printf("Σύνολο: %d, μέσος όρος: %.2f%n", total, (double) total / grades.length);
Σύνολο: 389, μέσος όρος: 77.80

Χρειάζεσαι όμως τον κλασικό for όταν θέλεις να αλλάξεις τα στοιχεία ή να ξέρεις σε ποια θέση βρίσκεσαι.

Πρόσεξε και το (double) total: χωρίς αυτό, το 389 / 5 θα ήταν διαίρεση ακεραίων και θα έδινε 77. Και όπως ο Scanner της Εβδομάδας 4, έτσι και το printf ακολουθεί τις ρυθμίσεις του υπολογιστή: με ελληνικές ρυθμίσεις τυπώνει 77,80 αντί για 77.80.

Ερωτήσεις αυτοαξιολόγησης

1. Πόσες φορές εκτελείται το σώμα του for (int i = 3; i < 15; i += 3);

Τέσσερις φορές, για i = 3, 6, 9 και 12. Μετά το i γίνεται 15, και η συνθήκη i < 15 είναι false.

2. Ποια είναι η βασική διαφορά ανάμεσα σε while και do-while;

Ο while ελέγχει τη συνθήκη πριν από κάθε επανάληψη, οπότε μπορεί να μην εκτελεστεί ποτέ. Ο do-while την ελέγχει μετά, οπότε το σώμα του εκτελείται τουλάχιστον μία φορά.

3. Τι υπολογίζει ο αλγόριθμος του Ευκλείδη για a = 30 και b = 12;

30 % 12 = 6 → (12, 6)· 12 % 6 = 0 → (6, 0). Το b μηδενίστηκε, άρα ο ΜΚΔ είναι 6.

4. Σε έναν πίνακα int[] data = new int[5]; ποια είναι η τελευταία έγκυρη θέση;

Η data[4]. Οι θέσεις πάνε από 0 έως length - 1, δηλαδή από 0 έως 4.

5. Πότε προτιμάς τον κλασικό for από τον enhanced for;

Όταν χρειάζεσαι τον δείκτη: για να αλλάξεις τα στοιχεία του πίνακα, να διαβάσεις δύο πίνακες μαζί, ή να ξέρεις σε ποια θέση βρίσκεσαι.


Πηγές: «Learn Programming with Java – Lesson 3» του μαθήματος· Oracle Java Tutorials.

Ασκήσεις της εβδομάδας

Άσκηση

6th Weekly Task

Προθεσμία
Χωρίς προθεσμία — για εξάσκηση

Κλιμακωτός φόρος εισοδήματος με έλεγχο εισόδου και επανάληψη.

Εκφώνηση

Καλείστε να δώσετε κώδικα για την υλοποίηση μιας εφαρμογής υπολογισμού του φόρου του ετήσιου εισοδήματος. Προκειμένου να υπολογίσετε τον φόρο, καλείστε να κάνετε υπολογισμούς ώστε να υπολογίσετε το ποσό με χρήση κλιμακωτής φορολόγησης.

Η κλίμακα φορολόγησης είναι η εξής. Για ετήσιο εισόδημα:

  • έως 10.000 ο φόρος είναι 0%.
  • μεταξύ 10.000 και 20.000 ο φόρος είναι 9%.
  • μεταξύ 20.000 και 30.000 ο φόρος είναι 17%.
  • μεταξύ 30.000 και 40.000 ο φόρος είναι 24%.
  • από 40.000 και πάνω, ο φόρος είναι 36%.

Για παράδειγμα, για ετήσιο εισόδημα 12.000 ο φόρος υπολογίζεται και είναι 180 (τα πρώτα 10.000 έχουν φόρο 0% και τα υπόλοιπα 2000 που απομένουν έχουν φόρο 9%). Όμοια. για ετήσιο εισόδημα 50.000, ο φόρος υπολογίζεται και είναι 8.600 (τα πρώτα 10.000 έχουν 0% φόρο, τα επόμενα 10.000, που είναι στη δεύτερη κατηγορία, έχουν φόρο 9%, τα επόμενα 10.000, που βρίσκονται στη 2η κατηγορία, έχουν 17% φόρο και τα επόμενα 10.000, που ανήκουν στην 3η κατηγορία, έχουν φόρο 24%. Τέλος, το ποσό που υπολείπεται από τα 40.000 και πάνω ανήκει στη τελευταία κατηγορία και έχει φόρο 36%.

Το ετήσιο εισόσημα δίνεται ώς είσοδος από το χρήστη. Καλείστε να ελέγξεται την ορθότητα της εισόδου ώς εξής!

  • Αν ο χρήστης δώσει αρνητικό αριθμό, πρέπει να τον ενημερώσετε με κατάλληλο μήνυμα ότι η είσοδός του δεν είναι αποδεκτή ώς αρνητικός αριθμός.
  • Αν ο χρήστης δώσει τον αριθμό 0, τυπώστε ότι δεν έχετε να υπολογίσετε κάτι.
  • Τέλος, αν ο χρήστης δώσει θετικό αριθμό αλλά αυτός είναι κάτω από 3000 (τεκμαρτό) τότε τον ενημερώνετε ότι δεν είναι αποδεκτό το πόσό που έδωσε γιατί είναι κατώτερο του τεκμαρτού.

Σε περίπτωση αποδεκτής εισόδου από το χρήστη, υπολογίζετε το φόρο και τυπώνετε με μήνυμα το φόρο για το εισόγημα που έδωσε ώς είσοδο. Σε περίπτωση μη αποδεκτής εισ΄όδου, ο χρήστης υποχρεούτε να δώσει έγκυρη είσοδο ΄έως αυτή πληρεί τα κριτήρια παραπάνω.

ΠΡΟΣΟΧΗ: Όλη η παραπάνω ακολουθία βημάτων θα μπορεί να επανεκτελεστεί από το χρήστη για άλλο ετήσιο εισόδημα. Στο τέλος της ακολουθίας βημάτων, και αφού έχετε τυπώσει τον υπολογισθέντα φόρο, ρωτάτε το χρήστη αν επιθυμεί να επαναλάβει τους υπολογισμούς για κάποια άλλη είσοδο.

Αν ο χρήστης πληκτόλογήσει “Yes” (ή 1 αν θέλετε να δουλέψετε με ακέραιο), τότε θα ζητάει η εφαρμογής σας εκ νέου είσοδο για το εισόδημα και θα υπολογίζει το νέο φόρο. Αν ο χρήστης πληκτρολογήσει “Νο” (ή τον αριθμό 0 κατα αντιστοιχία), τότε η εφαρμογή σας θα τερματίζει.

Άσκηση

6th Weekly Task 2

Προθεσμία
Χωρίς προθεσμία — για εξάσκηση

Πέντε υπολογιστές (ρεύμα, έκπτωση, καύσιμα, δάνειο, ΦΠΑ) με while και do-while.

Εκφώνηση

Ερώτημα 1

Ένα πρόγραμμα που υπολογίζει το κόστος της ηλεκτρικής ενέργειας για έναν οικιακό πελάτη. Ο χρήστης πρέπει να εισάγει την κατανάλωση ρεύματος σε κιλοβατώρες (kWh) και την τιμή ανά kWh. Το πρόγραμμα πρέπει να αποδέχεται μόνο θετικές τιμές για την κατανάλωση και την τιμή. Στη συνέχεια, υπολογίζει το συνολικό κόστος και το εμφανίζει στην οθόνη. Ο χρήστης θα ερωτηθεί αν θέλει να επαναλάβει το πρόγραμμα.

Οδηγίες:

  • Δημιουργήστε μια κλάση με όνομα: ElectricityBillApp.
  • Χρησιμοποιήστε ένα while loop:
    • Για να διασφαλίσετε ότι ο χρήστης θα εισάγει θετικές τιμές για την κατανάλωση ρεύματος και την τιμή ανά kWh.
  • Χρησιμοποιήστε ένα do-while loop:
    • Για να επαναλαμβάνεται το πρόγραμμα, αν ο χρήστης εισάγει το γράμμα ‘y’ όταν ερωτηθεί αν θέλει να το επαναλάβει.
  • Προβάλλετε το συνολικό κόστος με δύο δεκαδικά ψηφία.

Ερώτημα 2

Ένα πρόγραμμα που υπολογίζει την τελική τιμή ενός προϊόντος μετά από έκπτωση. Ο χρήστης πρέπει να εισάγει την αρχική τιμή του προϊόντος και το ποσοστό έκπτωσης. Το πρόγραμμα πρέπει να αποδέχεται μόνο θετικές τιμές για την αρχική τιμή και το ποσοστό έκπτωσης. Στη συνέχεια, υπολογίζει την τελική τιμή του προϊόντος και την εμφανίζει στην οθόνη. Ο χρήστης θα ερωτηθεί αν θέλει να επαναλάβει το πρόγραμμα.

Οδηγίες:

  • Δημιουργήστε μια κλάση με όνομα: DiscountCalculatorApp.
  • Χρησιμοποιήστε ένα while loop:
    • Για να διασφαλίσετε ότι ο χρήστης θα εισάγει θετικές τιμές για την αρχική τιμή και το ποσοστό έκπτωσης.
  • Χρησιμοποιήστε ένα do-while loop:
    • Για να επαναλαμβάνεται το πρόγραμμα, αν ο χρήστης εισάγει το γράμμα ‘y’ όταν ερωτηθεί αν θέλει να το επαναλάβει.
  • Προβάλλετε την τελική τιμή με δύο δεκαδικά ψηφία.

Ερώτημα 3

Ένα πρόγραμμα που υπολογίζει το συνολικό κόστος καυσίμων για ένα ταξίδι. Ο χρήστης πρέπει να εισάγει την ποσότητα καυσίμου σε λίτρα και την τιμή ανά λίτρο. Το πρόγραμμα πρέπει να αποδέχεται μόνο θετικές τιμές για την ποσότητα καυσίμου και την τιμή ανά λίτρο. Στη συνέχεια, υπολογίζει το συνολικό κόστος καυσίμου και το εμφανίζει στην οθόνη. Ο χρήστης θα ερωτηθεί αν θέλει να επαναλάβει το πρόγραμμα.

Οδηγίες:

  • Δημιουργήστε μια κλάση με όνομα: FuelCostApp.
  • Χρησιμοποιήστε ένα while loop:
    • Για να διασφαλίσετε ότι ο χρήστης θα εισάγει θετικές τιμές για την ποσότητα καυσίμου και την τιμή ανά λίτρο.
  • Χρησιμοποιήστε ένα do-while loop:
    • Για να επαναλαμβάνεται το πρόγραμμα, αν ο χρήστης εισάγει το γράμμα ‘y’ όταν ερωτηθεί αν θέλει να το επαναλάβει.
  • Προβάλλετε το συνολικό κόστος καυσίμου με δύο δεκαδικά ψηφία.

Ερώτημα 4

Ένα πρόγραμμα που υπολογίζει το συνολικό ποσό που πρέπει να πληρωθεί για ένα δάνειο, συμπεριλαμβανομένου του τόκου. Ο χρήστης πρέπει να εισάγει το ποσό του δανείου και το ετήσιο επιτόκιο. Το πρόγραμμα πρέπει να αποδέχεται μόνο θετικές τιμές για το ποσό και το επιτόκιο. Στη συνέχεια, υπολογίζει και εμφανίζει το συνολικό ποσό που πρέπει να επιστραφεί μετά από 1 έτος. Ο χρήστης θα ερωτηθεί αν θέλει να επαναλάβει το πρόγραμμα.

Οδηγίες:

  • Δημιουργήστε μια κλάση με όνομα: LoanCalculatorApp.
  • Χρησιμοποιήστε ένα while loop:
    • Για να διασφαλίσετε ότι ο χρήστης θα εισάγει θετικές τιμές για το ποσό του δανείου και το επιτόκιο.
  • Χρησιμοποιήστε ένα do-while loop:
    • Για να επαναλαμβάνεται το πρόγραμμα, αν ο χρήστης εισάγει το γράμμα ‘y’ όταν ερωτηθεί αν θέλει να το επαναλάβει.
  • Προβάλλετε το συνολικό ποσό με δύο δεκαδικά ψηφία.

Ερώτημα 5

Ένα πρόγραμμα που υπολογίζει την τελική τιμή ενός προϊόντος λαμβάνοντας υπόψη το ΦΠΑ και μια έκπτωση. Ο χρήστης πρέπει να εισάγει την αρχική τιμή του προϊόντος, το ποσοστό ΦΠΑ και το ποσοστό έκπτωσης. Το πρόγραμμα πρέπει να αποδέχεται μόνο θετικές τιμές για την τιμή, το ΦΠΑ και την έκπτωση. Στη συνέχεια, υπολογίζει την τελική τιμή του προϊόντος και την εμφανίζει στην οθόνη. Ο χρήστης θα ερωτηθεί αν θέλει να επαναλάβει το πρόγραμμα.

Οδηγίες:

  • Δημιουργήστε μια κλάση με όνομα: PriceCalculatorApp.
  • Χρησιμοποιήστε ένα while loop:
    • Για να διασφαλίσετε ότι ο χρήστης θα εισάγει θετικές τιμές για την αρχική τιμή, το ποσοστό ΦΠΑ και το ποσοστό έκπτωσης.
  • Χρησιμοποιήστε ένα do-while loop:
    • Για να επαναλαμβάνεται το πρόγραμμα, αν ο χρήστης εισάγει το γράμμα ‘y’ όταν ερωτηθεί αν θέλει να το επαναλάβει.
  • Προβάλλετε την τελική τιμή με δύο δεκαδικά ψηφία.