Πανεπιστήμιο Πελοποννήσου - Τμήμα Ψηφιακών Συστημάτων

Μάθημα 7: Σύστημα Διαχείρισης Βαθμολογίας

Πολυδιάστατοι Πίνακες & Οργάνωση Κώδικα με Συναρτήσεις

Καθηγητής: Γιώργος Μπάρδης | Τμήμα: Ψηφιακών Συστημάτων

📚 Εισαγωγή

🎯 Στόχοι του Μαθήματος

Σε αυτό το μάθημα θα μάθουμε:

  • Πολυδιάστατους Πίνακες (2D arrays) για αποθήκευση strings
  • Οργάνωση κώδικα με συναρτήσεις για καλύτερη δομή
  • Διαχείριση δεδομένων (εισαγωγή, επεξεργασία, αναζήτηση)
  • Στατιστική ανάλυση (μέσος όρος, min, max, ταξινόμηση)
  • Χειρισμό strings χωρίς string.h (αυτόνομες λύσεις)
  • 🔬 Κλασικούς Αλγόριθμους (Bubble Sort, Linear Search, Find Min/Max)

💡 Το Πρόβλημα

Θέλουμε να δημιουργήσουμε ένα Σύστημα Διαχείρισης Βαθμολογίας για 5 μαθητές που θα:

  1. Αποθηκεύει ονόματα και βαθμούς μαθητών
  2. Υπολογίζει στατιστικά (μέσος όρος, min, max)
  3. Μετατρέπει βαθμούς σε γράμματα (A-F)
  4. Ταξινομεί βαθμούς
  5. Αναζητά μαθητές
  6. Υπολογίζει ποσοστό επιτυχίας
Πορεία Ανάπτυξης του Προγράμματος
Βήμα 1:
Βασικά
Βήμα 2:
Στατιστικά
Βήμα 3:
Βοηθητικές
Βήμα 4:
Πλήρης

🔷 ΒΗΜΑ 1: Βασικά Στοιχεία - Αρχικοποίηση & Εισαγωγή Δεδομένων

📖 Θεωρία: Πολυδιάστατοι Πίνακες Χαρακτήρων

Τι είναι ο Πολυδιάστατος Πίνακας;

Ένας πολυδιάστατος πίνακας είναι "πίνακας από πίνακες".

Για να αποθηκεύσουμε πολλά strings (π.χ. ονόματα μαθητών), χρειαζόμαστε:

char names[5][50];  // 5 strings, το καθένα 50 χαρακτήρες

Σημαίνει:

  • names[0] → Πρώτο string (πρώτος μαθητής)
  • names[1] → Δεύτερο string (δεύτερος μαθητής)
  • ...
  • names[4] → Πέμπτο string (πέμπτος μαθητής)

📊 Απεικόνιση στη Μνήμη

Πίνακας Ονομάτων: char names[5][50]

Δείκτης Περιεχόμενο (String) Μνήμη
names[0] "Γιάννης" → {'Γ','ι','ά','ν','ν','η','ς','\0',...} 50 bytes
names[1] "Μαρία" → {'Μ','α','ρ','ί','α','\0',...} 50 bytes
names[2] "Κώστας" → {'Κ','ώ','σ','τ','α','ς','\0',...} 50 bytes
names[3] "Ελένη" → {'Ε','λ','έ','ν','η','\0',...} 50 bytes
names[4] "Νίκος" → {'Ν','ί','κ','ο','ς','\0',...} 50 bytes
ΣΥΝΟΛΟ 250 bytes

📖 Θεωρία: Αρχικοποίηση Πινάκων

Γιατί Αρχικοποιούμε;

Οι πίνακες στη C δεν αρχικοποιούνται αυτόματα. Περιέχουν "σκουπίδια" (τυχαία δεδομένα από τη μνήμη).

Αρχικοποίηση Strings:

names[i][0] = '\0';  // Το string γίνεται κενό

Αρχικοποίηση Αριθμών:

grades[i] = 0;  // Ο βαθμός γίνεται 0
Βήμα 1.1

Πλήρης Κώδικας: Βασική Δομή με Μενού και Εισαγωγή

/*
================================================================================
    ΒΗΜΑ 1: ΒΑΣΙΚΗ ΔΟΜΗ - Αρχικοποίηση, Μενού, Εισαγωγή Δεδομένων
================================================================================
*/

#include <stdio.h>

#define NUM_STUDENTS 5

// Πρωτότυπα συναρτήσεων
void displayMenu();
void inputGrades(char names[][50], int grades[]);

/* ΣΗΜΕΙΩΣΗ: Στους πίνακες δύο διαστάσεων, μόνο η πρώτη διάσταση μπορεί να είναι 
   άγνωστη. Η δεύτερη (το μέγεθος κάθε string) πρέπει να είναι γνωστή στο compile time, 
   ώστε ο μεταγλωττιστής να ξέρει πόσα bytes χρειάζεται για κάθε γραμμή. */
/*
================================================================================
    ΚΥΡΙΑ ΣΥΝΑΡΤΗΣΗ - MAIN
================================================================================
*/
int main() {
    // Δήλωση πινάκων για ονόματα και βαθμούς
    char names[NUM_STUDENTS][50];  // 5 ονόματα × 50 χαρακτήρες
    int grades[NUM_STUDENTS];           // 5 βαθμοί
    int choice;                         // Επιλογή χρήστη
    int dataEntered = 0;                // Flag: έχουν εισαχθεί δεδομένα;

    // ΑΡΧΙΚΟΠΟΙΗΣΗ ΠΙΝΑΚΩΝ
    for(int i = 0; i < NUM_STUDENTS; i++) {
        names[i][0] = '\0';  // Κενό string
                           // Άρα τι κάνει το names[i][0] = '\0'; ;
                           // Βάζει το '\0' στην πρώτη θέση του string. Αυτό σημαίνει:
                           // Το string είναι άδειο.
        grades[i] = 0;           // Βαθμός 0
    }

    // ΚΥΡΙΟΣ ΒΡΟΧΟΣ ΠΡΟΓΡΑΜΜΑΤΟΣ
    do {
        displayMenu();
        printf("Επιλέξτε λειτουργία (1-2): ");
        scanf("%d", &choice);
        getchar(); // Καθαρισμός buffer

        switch(choice) {
            case 1:
                // Εισαγωγή βαθμών
                inputGrades(names, grades);
                dataEntered = 1;
                break;
            
            case 2:
                // Έξοδος
                printf("\nΕυχαριστούμε! Το πρόγραμμα τερματίστηκε.\n");
                break;
            
            default:
                printf("\n❌ Μη έγκυρη επιλογή!\n\n");
        }

    } while(choice != 2);

    return 0;
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: displayMenu
    Περιγραφή: Εμφανίζει το κύριο μενού του προγράμματος
    Παράμετροι: Καμία
    Επιστρέφει: void (τίποτα)
================================================================================
*/
void displayMenu() {
    printf("\n====================================\n");
    printf("  ΣΥΣΤΗΜΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΘΜΟΛΟΓΙΑΣ  \n");
    printf("====================================\n");
    printf("\n--- ΜΕΝΟΥ ---\n");
    printf("1. Εισαγωγή βαθμών\n");
    printf("2. Έξοδος\n");
    printf("\n");
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: inputGrades
    Περιγραφή: Διαβάζει τα ονόματα και τους βαθμούς των μαθητών
    Παράμετροι: 
        - names[][50]: Πίνακας για ονόματα (2D array)
        - grades[]: Πίνακας για βαθμούς (1D array)
    Επιστρέφει: void (τίποτα)
    Σημείωση: Τροποποιεί τους πίνακες που περνάνε ως παράμετροι
================================================================================
*/
void inputGrades(char names[][50], int grades[]) {
    printf("\n====================================\n");
    printf("       ΕΙΣΑΓΩΓΗ ΒΑΘΜΩΝ             \n");
    printf("====================================\n\n");

    for(int i = 0; i < NUM_STUDENTS; i++) {
        // Εισαγωγή ονόματος
        printf("Εισάγετε όνομα μαθητή %d: ", i + 1);
        scanf("%s", &names[i][0]);  // Διάβασμα string
                                   // Το &names[i][0] είναι η διεύθυνση του πρώτου χαρακτήρα, 
                                   // δηλαδή η αρχή της μνήμης του string.

        // Εισαγωγή βαθμού με έλεγχο ορίων (0-100)
        do {
            printf("Εισάγετε βαθμό (0-100): ");
            scanf("%d", &grades[i]);
            getchar(); // Καθαρισμός buffer

            if(grades[i] < 0 || grades[i] > 100) {
                printf("❌ Μη έγκυρος βαθμός! Πρέπει να είναι 0-100.\n");
            }
        } while(grades[i] < 0 || grades[i] > 100);

        printf("\n");
    }

    printf("✅ Οι βαθμοί αποθηκεύτηκαν επιτυχώς!\n");
}

/*
================================================================================
    ΤΕΛΟΣ ΒΗΜΑΤΟΣ 1
================================================================================
*/

🖥️ Παράδειγμα Εκτέλεσης

====================================
ΣΥΣΤΗΜΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΘΜΟΛΟΓΙΑΣ
====================================
--- ΜΕΝΟΥ ---
1. Εισαγωγή βαθμών
2. Έξοδος
Επιλέξτε λειτουργία (1-2): 1
====================================
ΕΙΣΑΓΩΓΗ ΒΑΘΜΩΝ
====================================
Εισάγετε όνομα μαθητή 1: Γιάννης
Εισάγετε βαθμό (0-100): 85
Εισάγετε όνομα μαθητή 2: Μαρία
Εισάγετε βαθμό (0-100): 92
...
✅ Οι βαθμοί αποθηκεύτηκαν επιτυχώς!

⚠️ Σημαντικά Σημεία

  • scanf("%s", &names[i][0]) - Διαβάζουμε string από τον πρώτο χαρακτήρα
  • getchar() - Καθαρίζει το '\n' που αφήνει το scanf
  • Έλεγχος ορίων - Ο βαθμός πρέπει να είναι 0-100
  • Flag dataEntered - Ελέγχει αν έχουν εισαχθεί δεδομένα

🔷 ΒΗΜΑ 2: Προσθήκη Στατιστικών

📖 Θεωρία: Στατιστική Ανάλυση Δεδομένων

Τι Χρειαζόμαστε;

Για να εμφανίσουμε πλήρη στατιστικά, χρειαζόμαστε:

  1. Μέσο Όρο - Άθροισμα βαθμών / Πλήθος μαθητών
  2. Μέγιστο - Ο μεγαλύτερος βαθμός
  3. Ελάχιστο - Ο μικρότερος βαθμός
  4. Επιτυχόντες - Όσοι έχουν βαθμό ≥ 50
  5. Ταξινόμηση - Βαθμοί σε αύξουσα σειρά

Γιατί Χρησιμοποιούμε Συναρτήσεις;

  • Οργάνωση - Κάθε συνάρτηση κάνει ΕΝΑ πράγμα καλά
  • Επαναχρησιμοποίηση - Μπορούμε να καλέσουμε τη συνάρτηση πολλές φορές
  • Ευκολία συντήρησης - Αλλαγές σε ένα σημείο, όχι παντού
  • Αναγνωσιμότητα - Ο κώδικας γίνεται πιο κατανοητός
Βήμα 2.1

Προσθήκη της Συνάρτησης displayStatistics

Τώρα θα προσθέσουμε τη δυνατότητα εμφάνισης στατιστικών. Η συνάρτηση displayStatistics θα:

  • Εμφανίζει όλους τους μαθητές με τους βαθμούς τους
  • Υπολογίζει και εμφανίζει γενικά στατιστικά
  • Δείχνει τους επιτυχόντες
  • Εμφανίζει ταξινομημένους βαθμούς
/*
================================================================================
    ΒΗΜΑ 2: ΠΡΟΣΘΗΚΗ ΣΤΑΤΙΣΤΙΚΩΝ
    Προσθέτουμε: displayStatistics, calculateAverage, findMinMax, 
                 countPassed, sortGrades
================================================================================
*/

#include <stdio.h>

#define NUM_STUDENTS 5

// Πρωτότυπα συναρτήσεων
void displayMenu();
void inputGrades(char names[][50], int grades[]);
void displayStatistics(char names[][50], int grades[]);
float calculateAverage(int grades[]);
void findMinMax(int grades[], int results[2], char names[][50],
                char minName[], char maxName[]);
int countPassed(int grades[]);
void sortGrades(int grades[], int sorted[]);

/*
================================================================================
    ΚΥΡΙΑ ΣΥΝΑΡΤΗΣΗ - MAIN (με προσθήκη επιλογής στατιστικών)
================================================================================
*/
int main() {
    char names[NUM_STUDENTS][50];
    int grades[NUM_STUDENTS];
    int choice;
    int dataEntered = 0;

    // Αρχικοποίηση
    for(int i = 0; i < NUM_STUDENTS; i++) {
        names[i][0] = '\0';
        grades[i] = 0;
    }

    do {
        displayMenu();
        printf("Επιλέξτε λειτουργία (1-3): ");
        scanf("%d", &choice);
        getchar();

        switch(choice) {
            case 1:
                inputGrades(names, grades);
                dataEntered = 1;
                break;
            
            case 2:
                // ΝΕΑ ΕΠΙΛΟΓΗ: Εμφάνιση Στατιστικών
                if(dataEntered) {
                    displayStatistics(names, grades);
                } else {
                    printf("\n⚠️  Εισάγετε πρώτα τους βαθμούς!\n\n");
                }
                break;
            
            case 3:
                printf("\nΕυχαριστούμε!\n");
                break;
            
            default:
                printf("\n❌ Μη έγκυρη επιλογή!\n\n");
        }
    } while(choice != 3);

    return 0;
}

/* displayMenu - ΕΝΗΜΕΡΩΜΕΝΟ */
void displayMenu() {
    printf("\n====================================\n");
    printf("  ΣΥΣΤΗΜΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΘΜΟΛΟΓΙΑΣ  \n");
    printf("====================================\n");
    printf("\n--- ΜΕΝΟΥ ---\n");
    printf("1. Εισαγωγή βαθμών\n");
    printf("2. Εμφάνιση στατιστικών\n");  // ΝΕΟ
    printf("3. Έξοδος\n");
    printf("\n");
}

/* inputGrades - ΙΔΙΑ ΜΕ ΠΡΙΝ */
void inputGrades(char names[][50], int grades[]) {
    printf("\n====================================\n");
    printf("       ΕΙΣΑΓΩΓΗ ΒΑΘΜΩΝ             \n");
    printf("====================================\n\n");

    for(int i = 0; i < NUM_STUDENTS; i++) {
        printf("Εισάγετε όνομα μαθητή %d: ", i + 1);
        scanf("%s", &names[i][0]);

        do {
            printf("Εισάγετε βαθμό (0-100): ");
            scanf("%d", &grades[i]);
            getchar();

            if(grades[i] < 0 || grades[i] > 100) {
                printf("❌ Μη έγκυρος βαθμός!\n");
            }
        } while(grades[i] < 0 || grades[i] > 100);

        printf("\n");
    }

    printf("✅ Οι βαθμοί αποθηκεύτηκαν επιτυχώς!\n");
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: displayStatistics (ΝΕΑ!)
    Περιγραφή: Εμφανίζει πλήρη στατιστικά για τους βαθμούς
    Παράμετροι:
        - names[][50]: Πίνακας ονομάτων
        - grades[]: Πίνακας βαθμών
    Επιστρέφει: void
================================================================================
*/
void displayStatistics(char names[][50], int grades[]) {
    float average;
    int min, max;
    char minName[50], maxName[50];
    int passed;
    float passRate;
    int sortedGrades[NUM_STUDENTS];
    int results[2]; // results[0]=min, results[1]=max

    printf("\n====================================\n");
    printf("      ΣΤΑΤΙΣΤΙΚΑ ΒΑΘΜΟΛΟΓΙΑΣ       \n");
    printf("====================================\n\n");

    // 1. ΛΙΣΤΑ ΜΑΘΗΤΩΝ
    printf("📊 ΛΙΣΤΑ ΜΑΘΗΤΩΝ:\n");
    printf("------------------------------------\n");
    /* Τι είναι το names[i][0];
       Το names[i][0] είναι ο πρώτος χαρακτήρας του ονόματος. 
       Το &names[i][0] είναι η διεύθυνσή του, δηλαδή ένας δείκτης (pointer) 
       στη θέση που ξεκινά η συμβολοσειρά. */
    for(int i = 0; i < NUM_STUDENTS; i++) {
        printf("%d. %-15s : %3d\n", 
               i + 1, &names[i][0], grades[i]);
    }

    // 2. ΓΕΝΙΚΑ ΣΤΑΤΙΣΤΙΚΑ
    printf("\n📈 ΓΕΝΙΚΑ ΣΤΑΤΙΣΤΙΚΑ:\n");
    printf("------------------------------------\n");
    
    // Υπολογισμός μέσου όρου
    average = calculateAverage(grades);
    printf("Μέσος όρος     : %.2f\n", average);

    // Εύρεση min και max ΧΩΡΙΣ pointers
    findMinMax(grades, results, names, minName, maxName);
    min = results[0];
    max = results[1];

    printf("Μέγιστος βαθμός: %d - %s\n", max, maxName);
    printf("Ελάχιστος βαθμός: %d - %s\n", min, minName);

    // 3. ΕΠΙΤΥΧΟΝΤΕΣ
    printf("\n✅ ΕΠΙΤΥΧΟΝΤΕΣ:\n");
    printf("------------------------------------\n");
    passed = countPassed(grades);
    passRate = ((float)passed / NUM_STUDENTS) * 100;
    printf("Αριθμός επιτυχόντων: %d/%d μαθητές\n", 
           passed, NUM_STUDENTS);
    printf("Ποσοστό επιτυχίας  : %.2f%%\n", passRate);

    // 4. ΤΑΞΙΝΟΜΗΜΕΝΟΙ ΒΑΘΜΟΙ
    printf("\n📋 ΤΑΞΙΝΟΜΗΜΕΝΟΙ ΒΑΘΜΟΙ:\n");
    printf("------------------------------------\n");
    sortGrades(grades, sortedGrades);
    for(int i = 0; i < NUM_STUDENTS; i++) {
        printf("%d", sortedGrades[i]);
        if(i < NUM_STUDENTS - 1) {
            printf(", ");
        }
    }
    printf("\n");
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: calculateAverage (ΝΕΑ!)
    Περιγραφή: Υπολογίζει τον μέσο όρο των βαθμών
    Παράμετροι: grades[] - Πίνακας βαθμών
    Επιστρέφει: float - Ο μέσος όρος
================================================================================
*/
float calculateAverage(int grades[]) {
    int sum = 0;
    
    // Άθροισμα όλων των βαθμών
    for(int i = 0; i < NUM_STUDENTS; i++) {
        sum += grades[i];
    }
    
    // Διαίρεση με το πλήθος (προσοχή: float!)
    return (float)sum / NUM_STUDENTS;
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: findMinMax (ΝΕΑ!)
    Περιγραφή: Βρίσκει τον μέγιστο και ελάχιστο βαθμό + ονόματα
               ΧΩΡΙΣ pointers - χρησιμοποιεί πίνακα results[2]
    Παράμετροι:
        - grades[]: Πίνακας βαθμών
        - results[2]: Πίνακας για επιστροφή (0=min, 1=max)
        - names[][50]: Πίνακας ονομάτων
        - minName[]: String για όνομα ελάχιστου
        - maxName[]: String για όνομα μέγιστου
    Επιστρέφει: void (τα αποτελέσματα στους πίνακες)
================================================================================
*/
void findMinMax(int grades[], int results[2], char names[][50],
                char minName[], char maxName[]) {
    // Αρχικοποίηση με τον πρώτο βαθμό
    results[0] = grades[0]; // min
    results[1] = grades[0]; // max
    
    // Αντιγραφή πρώτου ονόματος σε minName και maxName
    int k = 0;                                 // Μεταβλητή για να διαβάζουμε χαρακτήρα-χαρακτήρα
    while(names[0][k] != '\0') {               // Όσο ο k-οστός χαρακτήρας του ονόματος δεν είναι '\0' (δηλαδή δεν τελείωσε το string)
        minName[k] = names[0][k];              // Αντιγράφουμε τον χαρακτήρα στο minName
        maxName[k] = names[0][k];              // Αντιγράφουμε τον ίδιο χαρακτήρα και στο maxName
        k++;                                   // Πάμε στον επόμενο χαρακτήρα
    }
    minName[k] = '\0';                         // Βάζουμε τερματικό χαρακτήρα στο τέλος του minName (τέλος string)
    maxName[k] = '\0';                         // Βάζουμε τερματικό χαρακτήρα στο τέλος του maxName (τέλος string)

    // Αναζήτηση min και max
    for(int i = 1; i < NUM_STUDENTS; i++) {    // Από τον δεύτερο μαθητή (i = 1) μέχρι τον τελευταίο
        if(grades[i] < results[0]) {           // Εάν ο βαθμός του μαθητή i είναι μικρότερος από το τωρινό min
            results[0] = grades[i];            // Τότε ο νέος min βαθμός είναι αυτός
            // Αντιγραφή ονόματος μαθητή με ελάχιστο βαθμό
            int j = 0;                         // j = 0 για να αντιγράψουμε χαρακτήρα-χαρακτήρα
            while(names[i][j] != '\0') {       // Διαβάζουμε το όνομα του μαθητή i μέχρι να βρούμε το '\0'
                minName[j] = names[i][j];      // Αντιγράφουμε κάθε χαρακτήρα στο minName
                j++;                           // Προχωράμε στον επόμενο χαρακτήρα
            }
            minName[j] = '\0';                 // Βάζουμε '\0' στο τέλος του minName (τέλος string)
        }
        if(grades[i] > results[1]) {           // Εάν ο βαθμός του μαθητή i είναι μεγαλύτερος από το τωρινό max
            results[1] = grades[i];            // Τότε ο νέος max βαθμός είναι αυτός
            // Αντιγραφή ονόματος μαθητή με μέγιστο βαθμό
            int j = 0;                         // j = 0 για να αντιγράψουμε χαρακτήρα-χαρακτήρα
            while(names[i][j] != '\0') {       // Διαβάζουμε το όνομα του μαθητή i μέχρι να βρούμε το '\0'
                maxName[j] = names[i][j];      // Αντιγράφουμε κάθε χαρακτήρα στο maxName
                j++;                           // Προχωράμε στον επόμενο χαρακτήρα
            }
            maxName[j] = '\0';                 // Βάζουμε '\0' στο τέλος του maxName (τέλος string)
        }
    }
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: countPassed (ΝΕΑ!)
    Περιγραφή: Μετράει πόσοι μαθητές πέρασαν (βαθμός >= 50)
    Παράμετροι: grades[] - Πίνακας βαθμών
    Επιστρέφει: int - Πλήθος επιτυχόντων
================================================================================
*/
int countPassed(int grades[]) {
    int count = 0;
    
    for(int i = 0; i < NUM_STUDENTS; i++) {
        if(grades[i] >= 50) {
            count++;
        }
    }
    
    return count;
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: sortGrades (ΝΕΑ!)
    Περιγραφή: Ταξινομεί τους βαθμούς (Bubble Sort)
    Παράμετροι:
        - grades[]: Αρχικός πίνακας (δεν αλλάζει)
        - sorted[]: Πίνακας για ταξινομημένους βαθμούς
    Επιστρέφει: void (το αποτέλεσμα στον sorted[])
================================================================================
*/
void sortGrades(int grades[], int sorted[]) {
    // Αντιγραφή πίνακα
    for(int i = 0; i < NUM_STUDENTS; i++) {   // Για κάθε θέση μέχρι τον αριθμό μαθητών
        sorted[i] = grades[i];                // Αντιγράφουμε την τιμή από τον grades στον sorted (ώστε να μην αλλάξει ο αρχικός πίνακας)
    }

    // Bubble Sort (αύξουσα σειρά)
    for(int i = 0; i < NUM_STUDENTS - 1; i++) {      // Εξωτερικός βρόχος (περνάει πολλές φορές τον πίνακα)
        for(int j = 0; j < NUM_STUDENTS - i - 1; j++) { // Εσωτερικός βρόχος (συγκρίνει γειτονικά στοιχεία κάθε φορά)
            if(sorted[j] > sorted[j + 1]) {           // Αν το τρέχον στοιχείο είναι μεγαλύτερο από το επόμενο...
                
                // Swap (αντιστροφή τιμών)
                int temp = sorted[j];                 // Αποθηκεύουμε προσωρινά την τιμή sorted[j]
                sorted[j] = sorted[j + 1];            // Βάζουμε στο sorted[j] την μικρότερη τιμή
                sorted[j + 1] = temp;                 // Βάζουμε στο sorted[j+1] την παλιά μεγαλύτερη τιμή
            }
        }
    }
}

/*
================================================================================
    ΤΕΛΟΣ ΒΗΜΑΤΟΣ 2
================================================================================
*/

🖥️ Παράδειγμα Εκτέλεσης - Στατιστικά

====================================
ΣΤΑΤΙΣΤΙΚΑ ΒΑΘΜΟΛΟΓΙΑΣ
====================================
📊 ΛΙΣΤΑ ΜΑΘΗΤΩΝ:
------------------------------------
1. Γιάννης : 85
2. Μαρία : 92
3. Κώστας : 78
4. Ελένη : 95
5. Νίκος : 45
📈 ΓΕΝΙΚΑ ΣΤΑΤΙΣΤΙΚΑ:
------------------------------------
Μέσος όρος : 79.00
Μέγιστος βαθμός: 95 - Ελένη
Ελάχιστος βαθμός: 45 - Νίκος
✅ ΕΠΙΤΥΧΟΝΤΕΣ:
------------------------------------
Αριθμός επιτυχόντων: 4/5 μαθητές
Ποσοστό επιτυχίας : 80.00%
📋 ΤΑΞΙΝΟΜΗΜΕΝΟΙ ΒΑΘΜΟΙ:
------------------------------------
45, 78, 85, 92, 95

🔍 Επεξήγηση Βασικών Τεχνικών

1. Αντιγραφή Strings ΧΩΡΙΣ string.h:

int j = 0;
while(names[i][j] != '\0') {
    minName[j] = names[i][j];
    j++;
}
minName[j] = '\0';  // Τερματισμός string

2. Επιστροφή Πολλαπλών Τιμών με Πίνακα:

int results[2];
findMinMax(grades, results, ...);
min = results[0];  // Πρώτη τιμή
max = results[1];  // Δεύτερη τιμή

3. Bubble Sort - Ταξινόμηση:

Συγκρίνει γειτονικά στοιχεία και τα ανταλλάσσει αν είναι λάθος σειρά.

🔷 ΒΗΜΑ 3: Βοηθητικές Συναρτήσεις

📖 Θεωρία: Μετατροπή Βαθμών & Αναζήτηση

Μετατροπή Βαθμών σε Γράμματα (Grading Scale)

Στα εκπαιδευτικά συστήματα, οι βαθμοί συχνά μετατρέπονται σε γράμματα:

Βαθμός Γράμμα Αξιολόγηση
90-100 A Άριστα
80-89 B Πολύ Καλά
70-79 C Καλά
60-69 D Μέτρια
0-59 F Αποτυχία

Γραμμική Αναζήτηση σε Strings

Για να βρούμε έναν μαθητή, πρέπει να συγκρίνουμε strings χαρακτήρα-χαρακτήρα.

Βήμα 3.1

Προσθήκη: gradeToLetter & findStudent

/*
================================================================================
    ΒΗΜΑ 3: ΒΟΗΘΗΤΙΚΕΣ ΣΥΝΑΡΤΗΣΕΙΣ
    Προσθέτουμε: gradeToLetter, findStudent
================================================================================
*/

/* ... (όλες οι προηγούμενες συναρτήσεις) ... */

// Προσθήκη στα πρωτότυπα:
char gradeToLetter(int grade);
void findStudent(char names[][50], int grades[]);

/* Στο main(), προσθήκη case 3: */
case 3:
    if(dataEntered) {
        findStudent(names, grades);
    } else {
        printf("\n⚠️  Εισάγετε πρώτα τους βαθμούς!\n\n");
    }
    break;

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: gradeToLetter (ΝΕΑ!)
    Περιγραφή: Μετατρέπει αριθμητικό βαθμό σε γράμμα (A-F)
    Παράμετροι: grade - Ο βαθμός (0-100)
    Επιστρέφει: char - Το γράμμα (A, B, C, D ή F)
    Λογική: Χρησιμοποιεί if-else if για διαστήματα τιμών
================================================================================
*/
char gradeToLetter(int grade) {
    if(grade >= 90 && grade <= 100) {
        return 'A';  // Άριστα
    } else if(grade >= 80 && grade < 90) {
        return 'B';  // Πολύ Καλά
    } else if(grade >= 70 && grade < 80) {
        return 'C';  // Καλά
    } else if(grade >= 60 && grade < 70) {
        return 'D';  // Μέτρια
    } else {
        return 'F';  // Αποτυχία
    }
}

/*
================================================================================
    ΣΥΝΑΡΤΗΣΗ: findStudent (ΝΕΑ!)
    Περιγραφή: Αναζητά μαθητή με βάση το όνομά του (γραμμική αναζήτηση)
    Παράμετροι:
        - names[][50]: Πίνακας ονομάτων
        - grades[]: Πίνακας βαθμών
    Επιστρέφει: void
    Λογική: Σύγκριση strings χαρακτήρα-χαρακτήρα ΧΩΡΙΣ strcmp
================================================================================
*/
void findStudent(char names[][50], int grades[]) {
    char searchName[50];     // Το όνομα που θα πληκτρολογήσει ο χρήστης για αναζήτηση
    int found = 0;           // Σημαία (0 = δεν βρέθηκε, 1 = βρέθηκε)

    printf("\n====================================\n");
    printf("       ΑΝΑΖΗΤΗΣΗ ΜΑΘΗΤΗ            \n");
    printf("====================================\n\n");

    printf("Εισάγετε όνομα μαθητή: ");
    scanf("%s", searchName);             // Το όνομα διαβάζεται πριν από την αναζήτηση

    // LINEAR SEARCH - Γραμμική Αναζήτηση
    for(int i = 0; i < NUM_STUDENTS; i++) {   // Περνάμε έναν-έναν όλους τους μαθητές
        // Σύγκριση strings χαρακτήρα-χαρακτήρα
        int j = 0;             // Μετρητής για σύγκριση κάθε χαρακτήρα
        int isEqual = 1;       // Υποθέτουμε αρχικά ότι τα δύο ονόματα είναι ίδια (1 = true)
        
        // Όσο και τα δύο ονόματα δεν έφτασαν στο τέλος τους ('\0')
        while(names[i][j] != '\0' && searchName[j] != '\0') {
            if(names[i][j] != searchName[j]) {   // Αν ένας χαρακτήρας δεν ταιριάζει...
                isEqual = 0;                     // ...δεν είναι ίδιο όνομα
                break;                           // Σταματάμε τη σύγκριση
            }
            j++;                                  // Πήγαινε στον επόμενο χαρακτήρα
        }
        
        // Έλεγχος αν τελικά έχουμε πλήρη ταύτιση ονομάτων
        if(isEqual && names[i][j] == '\0' && searchName[j] == '\0') {
            found = 1;            // Το όνομα βρέθηκε!
            char letter = gradeToLetter(grades[i]);

            printf("\n✓ Μαθητής βρέθηκε!\n");
            printf("------------------------------------\n");
            printf("Όνομα: %s\n", &names[i][0]);
            printf("Βαθμός: %d\n", grades[i]);
            printf("Αξιολόγηση: %c (", letter);
            
            switch(letter) {
                case 'A': printf("Άριστα)\n"); break;
                case 'B': printf("Πολύ Καλά)\n"); break;
                case 'C': printf("Καλά)\n"); break;
                case 'D': printf("Μέτρια)\n"); break;
                case 'F': printf("Αποτυχία)\n"); break;
            }
            break;  // ΣΤΑΜΑΤΑ! Βρέθηκε, δεν χρειάζεται να συνεχίσουμε!
        }
    }

    if(!found) {
        printf("\n❌ Ο μαθητής '%s' δεν βρέθηκε.\n", searchName);
    }
}

/*
================================================================================
    ΤΕΛΟΣ ΒΗΜΑΤΟΣ 3
================================================================================
*/

🔍 Λογική Σύγκρισης Strings

Βήμα-βήμα διαδικασία:

  1. Ξεκινάμε από τον πρώτο χαρακτήρα (j=0)
  2. Συγκρίνουμε names[i][j] με searchName[j]
  3. Αν διαφορετικοί → isEqual = 0, σταμάτα
  4. Αν ίδιοι → προχωράμε στον επόμενο χαρακτήρα (j++)
  5. Συνεχίζουμε μέχρι να βρούμε '\0' (τέλος string)
  6. Αν και τα δύο strings τελείωσαν μαζί → ίδια!

Παράδειγμα:

Αναζήτηση: "Μαρία"
names[1] = "Μαρία"

j=0: 'Μ' == 'Μ' ✓
j=1: 'α' == 'α' ✓
j=2: 'ρ' == 'ρ' ✓
j=3: 'ί' == 'ί' ✓
j=4: 'α' == 'α' ✓
j=5: '\0' == '\0' ✓ → ΒΡΕΘΗΚΕ!

🖥️ Παράδειγμα Εκτέλεσης - Αναζήτηση

====================================
ΑΝΑΖΗΤΗΣΗ ΜΑΘΗΤΗ
====================================
Εισάγετε όνομα μαθητή: Μαρία
✓ Μαθητής βρέθηκε!
------------------------------------
Όνομα: Μαρία
Βαθμός: 92
Αξιολόγηση: A (Άριστα)

🔷 ΒΗΜΑ 4: Πλήρης Λύση - Ολοκληρωμένο Σύστημα

🎯 Τελική Έκδοση

Στην τελική έκδοση, ενοποιούμε όλες τις λειτουργίες και προσθέτουμε:

  • Ολοκληρωμένο μενού με 4 επιλογές
  • Βελτιωμένη εμφάνιση στατιστικών (με γράμματα A-F)
  • Όλες τις βοηθητικές συναρτήσεις
  • Πλήρη έλεγχο λαθών
Βήμα 4.1

Πλήρης Κώδικας - Τελική Λύση

/*
================================================================================
    ΠΛΗΡΗΣ ΛΥΣΗ - ΣΥΣΤΗΜΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΘΜΟΛΟΓΙΑΣ
    Όλες οι λειτουργίες ενοποιημένες
================================================================================
*/

#include <stdio.h>

#define NUM_STUDENTS 5

// Πρωτότυπα συναρτήσεων
void displayMenu();
void inputGrades(char names[][50], int grades[]);
void displayStatistics(char names[][50], int grades[]);
char gradeToLetter(int grade);
void findStudent(char names[][50], int grades[]);
void sortGrades(int grades[], int sorted[]);
float calculateAverage(int grades[]);
void findMinMax(int grades[], int results[2], char names[][50],
                char minName[], char maxName[]);
int countPassed(int grades[]);

// MAIN με όλες τις επιλογές
int main() {
    char names[NUM_STUDENTS][50];
    int grades[NUM_STUDENTS];
    int choice;
    int dataEntered = 0;

    // Αρχικοποίηση
    for(int i = 0; i < NUM_STUDENTS; i++) {
        names[i][0] = '\0';
        grades[i] = 0;
    }

    // Κύριος βρόχος
    do {
        displayMenu();
        printf("Επιλέξτε λειτουργία (1-4): ");
        scanf("%d", &choice);
        getchar();

        switch(choice) {
            case 1:
                inputGrades(names, grades);
                dataEntered = 1;
                break;
            case 2:
                if(dataEntered) {
                    displayStatistics(names, grades);
                } else {
                    printf("\n⚠️  Εισάγετε πρώτα βαθμούς!\n\n");
                }
                break;
            case 3:
                if(dataEntered) {
                    findStudent(names, grades);
                } else {
                    printf("\n⚠️  Εισάγετε πρώτα βαθμούς!\n\n");
                }
                break;
            case 4:
                printf("\nΕυχαριστούμε!\n");
                break;
            default:
                printf("\n❌ Μη έγκυρη επιλογή!\n\n");
        }
    } while(choice != 4);

    return 0;
}

/* displayMenu */
void displayMenu() {
    printf("\n====================================\n");
    printf("  ΣΥΣΤΗΜΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΘΜΟΛΟΓΙΑΣ  \n");
    printf("====================================\n");
    printf("\n--- ΜΕΝΟΥ ---\n");
    printf("1. Εισαγωγή βαθμών\n");
    printf("2. Εμφάνιση στατιστικών\n");
    printf("3. Αναζήτηση μαθητή\n");
    printf("4. Έξοδος\n\n");
}

/* ... (Όλες οι άλλες συναρτήσεις όπως στα προηγούμενα βήματα) ... */

/*
================================================================================
    ΤΕΛΟΣ ΠΡΟΓΡΑΜΜΑΤΟΣ
================================================================================
*/

⚡ Σημαντικές Παρατηρήσεις

  • Modularity - Κάθε συνάρτηση έχει συγκεκριμένο ρόλο
  • Reusability - Οι συναρτήσεις μπορούν να χρησιμοποιηθούν ξανά
  • No Pointers - Χρησιμοποιούμε πίνακες για επιστροφή τιμών
  • No string.h - Όλες οι string operations γίνονται χειροκίνητα
  • Error Checking - Έλεγχος αν έχουν εισαχθεί δεδομένα

📊 Συνολική Αποτίμηση & Μαθησιακά Αποτελέσματα

✅ Τι Μάθαμε

Έννοια Περιγραφή
Πολυδιάστατοι Πίνακες char names[5][50] - Πίνακας από strings
Αρχικοποίηση names[i][0] = '\0', grades[i] = 0
Οργάνωση με Συναρτήσεις displayMenu(), inputGrades(), displayStatistics()
Στατιστική Ανάλυση Μέσος όρος, min/max, ταξινόμηση
String Handling Χειροκίνητη σύγκριση και αντιγραφή
Grading System Μετατροπή βαθμών σε γράμματα (A-F)
🔬 Bubble Sort Αλγόριθμος ταξινόμησης
🔬 Linear Search Αλγόριθμος αναζήτησης
🔬 Find Min/Max Αλγόριθμος εύρεσης ακραίων
🔬 String Comparison Αλγόριθμος σύγκρισης

💡 Σημαντικό: Μάθαμε να αναγνωρίζουμε και να υλοποιούμε κλασικούς αλγόριθμους της επιστήμης υπολογιστών! Αυτοί οι αλγόριθμοι χρησιμοποιούνται παντού στον προγραμματισμό.

🎓 Δομή Συναρτήσεων

Κατηγοριοποίηση συναρτήσεων ανά σκοπό:

1. Διεπαφή Χρήστη:

  • displayMenu() - Εμφάνιση μενού
  • inputGrades() - Εισαγωγή δεδομένων
  • displayStatistics() - Εμφάνιση αποτελεσμάτων
  • findStudent() - Αναζήτηση και εμφάνιση

2. Επεξεργασία Δεδομένων:

  • calculateAverage() - Υπολογισμός μέσου όρου
  • findMinMax() - Εύρεση ακραίων τιμών
  • countPassed() - Μέτρηση επιτυχόντων
  • sortGrades() - Ταξινόμηση

3. Βοηθητικές:

  • gradeToLetter() - Μετατροπή βαθμού

💡 Καλές Πρακτικές που Ακολουθήσαμε

  1. Σαφή Ονοματοδοσία - displayMenu, inputGrades (περιγραφικά ονόματα)
  2. Σχόλια - Εξήγηση κάθε συνάρτησης και βασικών τμημάτων
  3. Modularity - Κάθε συνάρτηση κάνει ένα πράγμα
  4. Έλεγχος Λαθών - Έλεγχος ορίων βαθμών, έλεγχος αν έχουν εισαχθεί δεδομένα
  5. Ευκολία Συντήρησης - Αλλαγή σε ένα σημείο αντικατοπτρίζεται παντού
  6. Σταθερές #define - NUM_STUDENTS για εύκολη αλλαγή

🔬 Γνωστοί Αλγόριθμοι που Χρησιμοποιούμε

Στο πρόγραμμά μας χρησιμοποιούμε κλασικούς αλγόριθμους της επιστήμης των υπολογιστών. Είναι σημαντικό να τους αναγνωρίζετε και να καταλαβαίνετε πότε και πώς εφαρμόζονται!

Αλγόριθμος 1

🔄 Bubble Sort (Ταξινόμηση Φυσαλίδας)

📌 Που το Χρησιμοποιούμε:

Στη συνάρτηση sortGrades() για να ταξινομήσουμε τους βαθμούς.

📖 Περιγραφή:

Ο Bubble Sort είναι ένας απλός αλγόριθμος ταξινόμησης που:

  • Συγκρίνει γειτονικά στοιχεία
  • Αν είναι σε λάθος σειρά, τα ανταλλάσσει (swap)
  • Επαναλαμβάνει τη διαδικασία μέχρι να ταξινομηθούν όλα

✅ Πλεονεκτήματα:

  • Πολύ απλός στην υλοποίηση
  • Καλός για μικρά datasets
  • Δεν χρειάζεται επιπλέον μνήμη

❌ Μειονεκτήματα:

  • Αργός για μεγάλα datasets
  • Υπάρχουν πολύ πιο γρήγοροι αλγόριθμοι (Quick Sort, Merge Sort)

🔍 Οπτική Αναπαράσταση Bubble Sort

Ας δούμε πώς ταξινομεί τους βαθμούς: [92, 45, 85, 78, 95]

Πέρασμα Κατάσταση Πίνακα Ενέργεια
Αρχική [92, 45, 85, 78, 95] -
Πέρασμα 1.1 [45, 92, 85, 78, 95] Swap: 92 > 45
Πέρασμα 1.2 [45, 85, 92, 78, 95] Swap: 92 > 85
Πέρασμα 1.3 [45, 85, 78, 92, 95] Swap: 92 > 78
Πέρασμα 1.4 [45, 85, 78, 92, 95] Όχι swap: 92 < 95
Το 95 βρίσκεται στη σωστή θέση!
Πέρασμα 2.1 [45, 78, 85, 92, 95] Swap: 85 > 78
...
Τελικό [45, 78, 85, 92, 95] ✅ Ταξινομημένο!

💻 Ο Κώδικάς μας:

void sortGrades(int grades[], int sorted[]) {
    // Αντιγραφή πίνακα
    for(int i = 0; i < NUM_STUDENTS; i++) {
        sorted[i] = grades[i];
    }

    // BUBBLE SORT - Ταξινόμηση Φυσαλίδας
    for(int i = 0; i < NUM_STUDENTS - 1; i++) {           // Εξωτερικός βρόχος
        for(int j = 0; j < NUM_STUDENTS - i - 1; j++) {  // Εσωτερικός βρόχος
            if(sorted[j] > sorted[j + 1]) {              // Σύγκριση γειτονικών
                // Swap (Ανταλλαγή)
                int temp = sorted[j];
                sorted[j] = sorted[j + 1];
                sorted[j + 1] = temp;
            }
        }
    }
}
Αλγόριθμος 2

🔍 Linear Search (Γραμμική Αναζήτηση)

📌 Που το Χρησιμοποιούμε:

Στη συνάρτηση findStudent() για να βρούμε έναν μαθητή από το όνομά του.

📖 Περιγραφή:

Η Γραμμική Αναζήτηση είναι ο πιο απλός αλγόριθμος αναζήτησης:

  • Ελέγχει κάθε στοιχείο του πίνακα ένα-ένα
  • Συγκρίνει το κάθε στοιχείο με την τιμή που ψάχνουμε
  • Σταματά όταν βρει το στοιχείο ή φτάσει στο τέλος

✅ Πλεονεκτήματα:

  • Πολύ απλός στην υλοποίηση
  • Λειτουργεί σε μη ταξινομημένους πίνακες
  • Καλός για μικρά datasets

❌ Μειονεκτήματα:

  • Αργός για μεγάλους πίνακες
  • Σε ταξινομημένους πίνακες, η Binary Search είναι πολύ πιο γρήγορη (O(log n))

🔍 Οπτική Αναπαράσταση Linear Search

Αναζητούμε το όνομα: "Κώστας"

Βήμα Έλεγχος Αποτέλεσμα
1 names[0] = "Γιάννης" ❌ Διαφορετικό
2 names[1] = "Μαρία" ❌ Διαφορετικό
3 names[2] = "Κώστας" ✅ ΒΡΕΘΗΚΕ!
Η αναζήτηση σταματά εδώ

Σημείωση: Στη δική μας υλοποίηση, κάνουμε και σύγκριση strings χαρακτήρα-χαρακτήρα, που είναι επίσης μια γραμμική αναζήτηση μέσα σε κάθε string!

💻 Ο Κώδικάς μας:

void findStudent(char names[][50], int grades[]) {
    char searchName[50];
    int found = 0;

    // ... (εισαγωγή ονόματος προς αναζήτηση)

    // LINEAR SEARCH - Γραμμική Αναζήτηση
    for(int i = 0; i < NUM_STUDENTS; i++) {  // Ελέγχουμε κάθε μαθητή
        // Σύγκριση strings χαρακτήρα-χαρακτήρα
        int j = 0;
        int isEqual = 1;
        
        while(names[i][j] != '\0' && searchName[j] != '\0') {
            if(names[i][j] != searchName[j]) {
                isEqual = 0;
                break;
            }
            j++;
        }
        
        if(isEqual && names[i][j] == '\0' && searchName[j] == '\0') {
            found = 1;
            // ... (εμφάνιση αποτελεσμάτων)
            break;  // ΣΤΑΜΑΤΑ! Βρέθηκε!
        }
    }
}
Αλγόριθμος 3

📊 Find Min/Max (Εύρεση Ελάχιστου & Μέγιστου)

📌 Που το Χρησιμοποιούμε:

Στη συνάρτηση findMinMax() για να βρούμε τον μικρότερο και μεγαλύτερο βαθμό.

📖 Περιγραφή:

Αυτός ο αλγόριθμος:

  • Αρχικοποιεί min και max με την πρώτη τιμή
  • Διατρέχει όλα τα στοιχεία του πίνακα
  • Ενημερώνει το min αν βρει μικρότερη τιμή
  • Ενημερώνει το max αν βρει μεγαλύτερη τιμή

💡 Ειδικότητα στον Κώδικά μας:

Στη δική μας υλοποίηση, επιστρέφουμε ΧΩΡΙΣ pointers χρησιμοποιώντας έναν πίνακα results[2]!

🔍 Οπτική Αναπαράσταση Find Min/Max

Βαθμοί: [85, 92, 78, 95, 45]

Βήμα Τρέχουσα Τιμή Min Max Ενέργεια
Αρχή 85 85 85 Αρχικοποίηση
1 92 85 92 92 > 85 → Νέο Max
2 78 85 92 Καμία αλλαγή
3 95 85 95 95 > 92 → Νέο Max
4 45 45 95 45 < 85 → Νέο Min
Τελικό 45 ✅ 95 ✅ Ολοκληρώθηκε!

💻 Ο Κώδικάς μας:

void findMinMax(int grades[], int results[2], ...) {
    // FIND MIN/MAX - Εύρεση Ελάχιστου & Μέγιστου
    
    // Αρχικοποίηση με την πρώτη τιμή
    results[0] = grades[0]; // min
    results[1] = grades[0]; // max

    // Διάσχιση του πίνακα
    for(int i = 1; i < NUM_STUDENTS; i++) {
        if(grades[i] < results[0]) {  // Νέο ελάχιστο;
            results[0] = grades[i];
            // ... (αντιγραφή ονόματος)
        }
        if(grades[i] > results[1]) {  // Νέο μέγιστο;
            results[1] = grades[i];
            // ... (αντιγραφή ονόματος)
        }
    }
}
Αλγόριθμος 4

📝 String Comparison (Σύγκριση Strings)

📌 Που το Χρησιμοποιούμε:

Στη συνάρτηση findStudent() για να συγκρίνουμε ονόματα.

📖 Περιγραφή:

Η σύγκριση strings χαρακτήρα-χαρακτήρα:

  • Συγκρίνει κάθε χαρακτήρα ξεχωριστά
  • Σταματά αν βρει διαφορά
  • Επιτυχία μόνο αν ΟΛΑ τα γράμματα ταιριάζουν ΚΑΙ τα δύο strings τελειώνουν μαζί

💡 Γιατί δεν χρησιμοποιούμε strcmp();

Για εκπαιδευτικούς λόγους! Έτσι μαθαίνουμε πώς λειτουργούν οι strings "από μέσα".

🔍 Σύγκριση: "Μαρία" με "Μαρία"

Θέση (j) String 1 String 2 Σύγκριση
0 'Μ' 'Μ' ✅ Ίδια
1 'α' 'α' ✅ Ίδια
2 'ρ' 'ρ' ✅ Ίδια
3 'ί' 'ί' ✅ Ίδια
4 'α' 'α' ✅ Ίδια
5 '\0' '\0' ✅ ΚΑΙ ΤΑ ΔΥΟ ΤΕΛΕΙΩΣΑΝ!

→ Αποτέλεσμα: ΤΑ STRINGS ΕΙΝΑΙ ΙΔΙΑ!

🔍 Σύγκριση: "Μαρία" με "Μαρίνα"

Θέση (j) String 1 String 2 Σύγκριση
0 'Μ' 'Μ' ✅ Ίδια
1 'α' 'α' ✅ Ίδια
2 'ρ' 'ρ' ✅ Ίδια
3 'ί' 'ί' ✅ Ίδια
4 'α' 'ν' ❌ ΔΙΑΦΟΡΕΤΙΚΑ!
Η σύγκριση σταματά εδώ (break)

→ Αποτέλεσμα: ΤΑ STRINGS ΕΙΝΑΙ ΔΙΑΦΟΡΕΤΙΚΑ!

🎯 Σύνοψη Αλγορίθμων

Αλγόριθμος Χρήση Συνάρτηση
Bubble Sort Ταξινόμηση sortGrades()
Linear Search Αναζήτηση findStudent()
Find Min/Max Στατιστικά findMinMax()
String Comparison Σύγκριση findStudent()

Σημείωση: Για μεγάλα datasets, θα χρησιμοποιούσαμε πιο αποδοτικούς αλγόριθμους (Quick Sort για ταξινόμηση, Binary Search για αναζήτηση σε ταξινομημένους πίνακες).

📝 Ασκήσεις Εξάσκησης

Άσκηση 1

Προσθήκη Νέας Λειτουργίας

Προσθέστε μια νέα συνάρτηση displayTopStudents() που:

  • Βρίσκει τους 3 καλύτερους μαθητές
  • Τους εμφανίζει με σειρά (1ος, 2ος, 3ος)
  • Δείχνει το όνομα και τον βαθμό τους
Άσκηση 2

Βελτίωση Αναζήτησης

Τροποποιήστε τη findStudent() ώστε:

  • Να μην κάνει διάκριση πεζών-κεφαλαίων
  • Να αναζητά με μερική αντιστοίχιση (π.χ. "Γιάν" να βρίσκει "Γιάννης")
Άσκηση 3

Στατιστικά ανά Κατηγορία

Δημιουργήστε συνάρτηση displayByGrade() που:

  • Ομαδοποιεί μαθητές ανά γράμμα (A, B, C, D, F)
  • Εμφανίζει πόσοι μαθητές έχουν κάθε γράμμα
  • Δείχνει ποσοστά (π.χ. 40% έχουν A)
Άσκηση 4

Επέκταση Συστήματος

Τροποποιήστε το πρόγραμμα ώστε:

  • Να δέχεται δυναμικό αριθμό μαθητών (input από χρήστη)
  • Να αποθηκεύει πολλούς βαθμούς ανά μαθητή (π.χ. 3 εξετάσεις)
  • Να υπολογίζει τον μέσο όρο ανά μαθητή
Άσκηση 5

🔬 Σύγκριση Αλγορίθμων Ταξινόμησης

Υλοποιήστε τον αλγόριθμο Selection Sort και συγκρίνετε τον με το Bubble Sort:

  • Δημιουργήστε συνάρτηση selectionSort()
  • Μετρήστε πόσες συγκρίσεις κάνει κάθε αλγόριθμος
  • Μετρήστε πόσες ανταλλαγές (swaps) κάνει κάθε αλγόριθμος
  • Συγκρίνετε τα αποτελέσματα

Υπόδειξη: Ο Selection Sort βρίσκει το ελάχιστο στοιχείο και το τοποθετεί στην αρχή κάθε φορά.

Άσκηση 6

🔬 Binary Search

Μετά την ταξινόμηση, υλοποιήστε Binary Search για αναζήτηση βαθμών:

  • Δημιουργήστε συνάρτηση binarySearchGrade()
  • Η αναζήτηση να γίνεται σε ταξινομημένο πίνακα βαθμών
  • Συγκρίνετε την απόδοση με τη Linear Search
  • Εμφανίστε πόσα βήματα χρειάστηκαν για την αναζήτηση