C Αρχεία I/O: Δημιουργία, Άνοιγμα, Ανάγνωση, Εγγραφή και Κλείσιμο αρχείου

⚡ Έξυπνη Σύνοψη

Η διαχείριση αρχείων σε C αποθηκεύει μόνιμα δεδομένα στον δίσκο μέσω της βιβλιοθήκης stdio, η οποία ανοίγει ένα αρχείο με το fopen, γράφει με fputc, fputs ή fprintf, διαβάζει με fgetc, fgets ή fscanf και το κλείνει χρησιμοποιώντας το fclose.

  • 📁 Λειτουργίες αρχείου: Η συμβολοσειρά λειτουργίας που διαβιβάζεται στο fopen — r, w, a, r+, w+ ή a+ — αποφασίζει εάν ένα αρχείο θα διαβαστεί, θα αντικατασταθεί ή θα προστεθεί.
  • ✍️ Δεδομένα εγγραφής: Η fputc γράφει έναν χαρακτήρα, η fputs γράφει μια συμβολοσειρά και η fprintf γράφει μορφοποιημένο κείμενο στον δείκτη του αρχείου.
  • 📖 Ανάγνωση δεδομένων: Το fgetc διαβάζει έναν χαρακτήρα, το fgets διαβάζει μια γραμμή σε ένα buffer και το fscanf αναλύει μορφοποιημένα tokens από το αρχείο.
  • 🔒 Κλείσιμο αρχείων: Η εντολή fclose εκκαθαρίζει τα δεδομένα που έχουν αποθηκευτεί στο buffer και απελευθερώνει το αρχείο, επιστρέφοντας 0 σε περίπτωση επιτυχίας και EOF σε περίπτωση αποτυχίας.
  • 🔁 Διαδραστική είσοδος/έξοδος: Οι getc και putc χειρίζονται έναν μόνο χαρακτήρα κάθε φορά, μετακινώντας την είσοδο απευθείας σε ένα αρχείο και επιστρέφοντας ξανά.
  • 🤖 Βοήθεια AI: Το GitHub Copilot και οι βοηθοί τεχνητής νοημοσύνης (AI) υποστηρίζουν τις ρουτίνες fopen, fprintf και fgets και επισημαίνουν ελέγχους NULL που λείπουν ή μη κλειστά αρχεία.

C Αρχεία I/O

C Διαχείριση αρχείων

Ένα αρχείο μπορεί να χρησιμοποιηθεί για την αποθήκευση μεγάλου όγκου μόνιμων δεδομένων. Όπως πολλές άλλες γλώσσες, η 'C' παρέχει την ακόλουθη διαχείριση αρχείων: λειτουργίες,

  1. Δημιουργία αρχείου
  2. Άνοιγμα αρχείου
  3. Διαβάζοντας ένα αρχείο
  4. Εγγραφή σε αρχείο
  5. Κλείσιμο αρχείου

Ακολουθούν οι πιο σημαντικές λειτουργίες διαχείρισης αρχείων που είναι διαθέσιμες στο 'C,'

λειτουργία σκοπός
ανοίγω () Δημιουργία αρχείου ή άνοιγμα υπάρχοντος αρχείου
fclose () Κλείσιμο αρχείου
fprintf() Εγγραφή ενός μπλοκ δεδομένων σε ένα αρχείο
fscanf () Ανάγνωση δεδομένων μπλοκ από αρχείο
getc () Διαβάζει έναν χαρακτήρα από ένα αρχείο
putc () Γράφει έναν χαρακτήρα σε ένα αρχείο
πάρε () Διαβάζει έναν ακέραιο από ένα αρχείο
putw () Γράφοντας έναν ακέραιο σε ένα αρχείο
fseek () Ορίζει τη θέση ενός δείκτη αρχείου σε μια καθορισμένη θέση
ftell () Επιστρέφει την τρέχουσα θέση ενός δείκτη αρχείου
επανατύλιξη () Ορίζει τον δείκτη του αρχείου στην αρχή ενός αρχείου

Πώς να δημιουργήσετε ένα αρχείο

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

Για τη δημιουργία ενός αρχείου σε ένα πρόγραμμα «C» χρησιμοποιείται η ακόλουθη σύνταξη,

FILE *fp;
fp = fopen ("file_name", "mode");

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

Το fopen είναι μια τυπική συνάρτηση που χρησιμοποιείται για το άνοιγμα ενός αρχείου.

  • Εάν το αρχείο δεν υπάρχει στο σύστημα, τότε δημιουργείται και στη συνέχεια ανοίγει.
  • Εάν ένα αρχείο υπάρχει ήδη στο σύστημα, τότε ανοίγει απευθείας χρησιμοποιώντας αυτήν τη συνάρτηση.

Το fp είναι ένα αρχείο δείκτης το οποίο δείχνει στο αρχείο τύπου.

Κάθε φορά που ανοίγετε ή δημιουργείτε ένα αρχείο, πρέπει να προσδιορίζετε τι πρόκειται να κάνετε με το αρχείο. Ένα αρχείο στον προγραμματισμό «C» μπορεί να δημιουργηθεί ή να ανοίξει για λόγους ανάγνωσης/εγγραφής. Μια λειτουργία χρησιμοποιείται για να καθορίσετε εάν θέλετε να ανοίξετε ένα αρχείο για οποιονδήποτε από τους παρακάτω σκοπούς. Ακολουθούν οι διαφορετικοί τύποι λειτουργιών στον προγραμματισμό «C» που μπορούν να χρησιμοποιηθούν κατά την εργασία με ένα αρχείο.

Λειτουργία αρχείου Περιγραφή
r Ανοίξτε ένα αρχείο για ανάγνωση. Εάν ένα αρχείο βρίσκεται σε λειτουργία ανάγνωσης, τότε δεν διαγράφονται δεδομένα εάν ένα αρχείο υπάρχει ήδη σε ένα σύστημα.
w Ανοίξτε ένα αρχείο για εγγραφή. Εάν ένα αρχείο βρίσκεται σε λειτουργία εγγραφής, τότε δημιουργείται ένα νέο αρχείο εάν δεν υπάρχει καθόλου αρχείο. Εάν ένα αρχείο υπάρχει ήδη σε ένα σύστημα, τότε όλα τα δεδομένα μέσα στο αρχείο περικόπτονται και ανοίγουν για λόγους εγγραφής.
a Άνοιγμα αρχείου σε λειτουργία προσάρτησης. Εάν ένα αρχείο βρίσκεται σε λειτουργία προσάρτησης, τότε το αρχείο ανοίγει. Το περιεχόμενο του αρχείου δεν αλλάζει.
r+ ανοιχτό για ανάγνωση και γραφή από την αρχή
w+ ανοιχτό για ανάγνωση και γραφή, αντικατάσταση αρχείου
a+ ανοιχτό για ανάγνωση και γραφή, προσάρτηση στο αρχείο

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

Για παράδειγμα:

#include <stdio.h>
int main() {
FILE *fp;
fp  = fopen ("data.txt", "w");
}

Παραγωγή:

Το αρχείο δημιουργείται στον ίδιο φάκελο όπου έχετε αποθηκεύσει τον κωδικό σας.

Δημιουργήστε ένα αρχείο σε έξοδο προγράμματος C

Μπορείτε να καθορίσετε τη διαδρομή στην οποία θέλετε να δημιουργήσετε το αρχείο σας

#include <stdio.h>
int main() {
FILE *fp;
fp  = fopen ("D://data.txt", "w");
}

Δημιουργήστε ένα αρχείο με μια καθορισμένη διαδρομή σε C

Πώς να κλείσετε ένα αρχείο

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

Το 'C' παρέχει τη λειτουργία fclose για την εκτέλεση της λειτουργίας κλεισίματος αρχείων. Η σύνταξη του fclose είναι η εξής:

fclose (file_pointer);

Για παράδειγμα:

FILE *fp;
fp  = fopen ("data.txt", "r");
fclose (fp);

Η συνάρτηση fclose δέχεται έναν δείκτη αρχείου ως όρισμα. Το αρχείο που σχετίζεται με τον δείκτη αρχείου κλείνει στη συνέχεια με τη βοήθεια της συνάρτησης fclose. Επιστρέφει 0 εάν το κλείσιμο ήταν επιτυχές και EOF (τέλος αρχείου) εάν έχει παρουσιαστεί σφάλμα κατά το κλείσιμο του αρχείου.

Μετά το κλείσιμο του αρχείου, ο ίδιος δείκτης αρχείου μπορεί να χρησιμοποιηθεί και με άλλα αρχεία.

Στον προγραμματισμό 'C', τα αρχεία κλείνουν αυτόματα όταν τερματίζεται το πρόγραμμα. Το χειροκίνητο κλείσιμο ενός αρχείου γράφοντας τη συνάρτηση fclose είναι μια καλή πρακτική προγραμματισμού.

Γράφοντας σε ένα αρχείο

Στο C, όταν γράφετε σε ένα αρχείο, οι χαρακτήρες νέας γραμμής '\n' πρέπει να προστίθενται ρητά.

Η βιβλιοθήκη stdio προσφέρει τις απαραίτητες λειτουργίες για εγγραφή σε ένα αρχείο:

  • fputc(char, file_pointer): Γράφει έναν χαρακτήρα στο αρχείο στο οποίο υποδεικνύεται από το file_pointer.
  • fputs(str, file_pointer): Γράφει μια συμβολοσειρά στο αρχείο στο οποίο υποδεικνύεται από το file_pointer.
  • fprintf(file_pointer, str, variable_lists): Εκτυπώνει μια συμβολοσειρά στο αρχείο στο οποίο υποδεικνύεται ο file_pointer. Η συμβολοσειρά μπορεί προαιρετικά να περιλαμβάνει προσδιοριστές μορφής και μια λίστα μεταβλητών variable_lists.

Το παρακάτω πρόγραμμα δείχνει πώς να εκτελέσετε την εγγραφή σε ένα αρχείο:

Λειτουργία fputc():

#include <stdio.h>
int main() {
        int i;
        FILE * fptr;
        char fn[50];
        char str[] = "Guru99 Rocks\n";
        fptr = fopen("fputc_test.txt", "w"); // "w" defines "writing mode"
        for (i = 0; str[i] != '\n'; i++) {
            /* write to file using fputc() function */
            fputc(str[i], fptr);
        }
        fclose(fptr);
        return 0;
    }

Παραγωγή:

έξοδος συνάρτησης fputc() σε C

Το παραπάνω πρόγραμμα γράφει έναν μόνο χαρακτήρα στο αρχείο fputc_test.txt μέχρι να φτάσει στο σύμβολο της επόμενης γραμμής "\n", το οποίο υποδεικνύει ότι η πρόταση γράφτηκε με επιτυχία. Η διαδικασία είναι να πάρουμε κάθε χαρακτήρα του πίνακα και να τον γράψουμε στο αρχείο.

περιεχόμενο αρχείου fputc_test.txt γραμμένο σε C

  1. Στο παραπάνω πρόγραμμα, δημιουργήσαμε και ανοίξαμε ένα αρχείο με το όνομα fputc_test.txt σε λειτουργία εγγραφής και δηλώνουμε τη συμβολοσειρά μας που θα γραφτεί στο αρχείο.
  2. Κάνουμε μια λειτουργία εγγραφής χαρακτήρα προς χαρακτήρα χρησιμοποιώντας το βρόχο for και βάζουμε κάθε χαρακτήρα στο αρχείο μας μέχρι να εμφανιστεί ο χαρακτήρας "\n" και στη συνέχεια το αρχείο κλείνει χρησιμοποιώντας τη συνάρτηση fclose.

fputs () Συνάρτηση:

#include <stdio.h>
int main() {
        FILE * fp;
        fp = fopen("fputs_test.txt", "w+");
        fputs("This is Guru99 Tutorial on fputs,", fp);
        fputs("We don't need to use for loop\n", fp);
        fputs("Easier than fputc function\n", fp);
        fclose(fp);
        return (0);
    }

Παραγωγή:

έξοδος συνάρτησης fputs() σε C

περιεχόμενο αρχείου fputs_test.txt σε C

  1. Στο παραπάνω πρόγραμμα, δημιουργήσαμε και ανοίξαμε ένα αρχείο που ονομάζεται fputs_test.txt σε κατάσταση εγγραφής.
  2. Αφού εκτελέσουμε μια λειτουργία εγγραφής χρησιμοποιώντας τη συνάρτηση fputs() γράφοντας τρεις διαφορετικές συμβολοσειρές
  3. Στη συνέχεια, το αρχείο κλείνει χρησιμοποιώντας τη συνάρτηση fclose.

Λειτουργία fprintf():

#include <stdio.h>
    int main() {
        FILE *fptr;
        fptr = fopen("fprintf_test.txt", "w"); // "w" defines "writing mode"
        /* write to file */
        fprintf(fptr, "Learning C with Guru99\n");
        fclose(fptr);
        return 0;
    }

Παραγωγή:

έξοδος συνάρτησης fprintf() σε C

Περιεχόμενο αρχείου fprintf_test.txt σε C

  1. Στο παραπάνω πρόγραμμα έχουμε δημιουργήσει και ανοίξει ένα αρχείο που ονομάζεται fprintf_test.txt σε λειτουργία εγγραφής.
  2. Αφού εκτελεστεί μια λειτουργία εγγραφής χρησιμοποιώντας τη συνάρτηση fprintf() γράφοντας μια συμβολοσειρά, τότε το αρχείο κλείνει χρησιμοποιώντας τη συνάρτηση fclose.

Ανάγνωση δεδομένων από ένα αρχείο

Υπάρχουν τρεις διαφορετικές λειτουργίες αφιερωμένες στην ανάγνωση δεδομένων από ένα αρχείο

  • fgetc(file_pointer): Επιστρέφει τον επόμενο χαρακτήρα από το αρχείο που δείχνει ο δείκτης αρχείου. Όταν επιτευχθεί το τέλος του αρχείου, το EOF αποστέλλεται πίσω.
  • fgets(buffer, n, file_pointer): Διαβάζει n-1 χαρακτήρες από το αρχείο και αποθηκεύει τη συμβολοσειρά σε ένα buffer στο οποίο προστίθεται ο NULL χαρακτήρας '\0' ως τελευταίος χαρακτήρας.
  • fscanf(file_pointer, conversion_specifiers, variable_adresses): Χρησιμοποιείται για την ανάλυση και ανάλυση δεδομένων. Διαβάζει χαρακτήρες από το αρχείο και αντιστοιχίζει την είσοδο σε μια λίστα δεικτών μεταβλητών variable_adresses χρησιμοποιώντας προσδιοριστές μετατροπής. Λάβετε υπόψη ότι όπως και με το scanf, το fscanf σταματά να διαβάζει μια συμβολοσειρά όταν συναντάται κενό ή νέα γραμμή.

Το παρακάτω πρόγραμμα δείχνει την ανάγνωση από το αρχείο fputs_test.txt χρησιμοποιώντας τις συναρτήσεις fgets(),fscanf() και fgetc () αντίστοιχα:

#include <stdio.h>
int main() {
        FILE * file_pointer;
        char buffer[30], c;

        file_pointer = fopen("fprintf_test.txt", "r");
        printf("----read a line----\n");
        fgets(buffer, 50, file_pointer);
        printf("%s\n", buffer);

        printf("----read and parse data----\n");
        file_pointer = fopen("fprintf_test.txt", "r"); //reset the pointer
        char str1[10], str2[2], str3[20], str4[2];
        fscanf(file_pointer, "%s %s %s %s", str1, str2, str3, str4);
        printf("Read String1 |%s|\n", str1);
        printf("Read String2 |%s|\n", str2);
        printf("Read String3 |%s|\n", str3);
        printf("Read String4 |%s|\n", str4);

        printf("----read the entire file----\n");

        file_pointer = fopen("fprintf_test.txt", "r"); //reset the pointer
        while ((c = getc(file_pointer)) != EOF) printf("%c", c);

        fclose(file_pointer);
        return 0;
    }

Αποτέλεσμα:

----read a line----
Learning C with Guru99

----read and parse data----
Read String1 |Learning|
Read String2 |C|
Read String3 |with|
Read String4 |Guru99|
----read the entire file----
Learning C with Guru99

Ανάγνωση δεδομένων από ένα αρχείο σε έξοδο C

  1. Στο παραπάνω πρόγραμμα, ανοίξαμε το αρχείο με όνομα "fprintf_test.txt", το οποίο είχε γραφτεί προηγουμένως χρησιμοποιώντας τη συνάρτηση fprintf(), και περιέχει το "Learning C with GuruΣυμβολοσειρά 99”. Την διαβάζουμε χρησιμοποιώντας τη συνάρτηση fgets() η οποία διαβάζει γραμμή προς γραμμή, όπου το μέγεθος του buffer πρέπει να είναι αρκετό για να χειριστεί ολόκληρη τη γραμμή.
  2. Ανοίγουμε ξανά το αρχείο για να επαναφέρουμε το αρχείο δείκτη ώστε να δείχνει στην αρχή του αρχείου. Δημιουργούμε διάφορες μεταβλητές συμβολοσειρών για να χειριζόμαστε κάθε λέξη ξεχωριστά. Εκτυπώνουμε τις μεταβλητές για να βλέπουμε το περιεχόμενό τους. Η συνάρτηση fscanf() χρησιμοποιείται κυρίως για την εξαγωγήtract και αναλύστε δεδομένα από ένα αρχείο.
  3. Ανοίξτε ξανά το αρχείο για να επαναφέρετε το αρχείο δείκτη στην αρχή του αρχείου. Διαβάστε τα δεδομένα και εκτυπώστε τα από το αρχείο χαρακτήρα προς χαρακτήρα χρησιμοποιώντας τη συνάρτηση getc() μέχρι να εμφανιστεί η δήλωση EOF
  4. Αφού εκτελέσαμε ένα αρχείο λειτουργίας ανάγνωσης χρησιμοποιώντας διαφορετικές παραλλαγές, κλείσαμε ξανά το αρχείο χρησιμοποιώντας τη συνάρτηση fclose.

Διαδραστικό αρχείο Ανάγνωση και εγγραφή με getc και putc

Αυτές είναι οι απλούστερες λειτουργίες αρχείων. Το Getc σημαίνει get character και το putc σημαίνει put character. Αυτές οι δύο λειτουργίες χρησιμοποιούνται για τον χειρισμό μόνο ενός χαρακτήρα κάθε φορά.

Το παρακάτω πρόγραμμα δείχνει τις λειτουργίες χειρισμού αρχείων στον προγραμματισμό «C»:

#include <stdio.h>
int main() {
        FILE * fp;
        char c;
        printf("File Handling\n");
        //open a file
        fp = fopen("demo.txt", "w");
        //writing operation
        while ((c = getchar()) != EOF) {
            putc(c, fp);
        }
        //close file
        fclose(fp);
        printf("Data Entered:\n");
        //reading
        fp = fopen("demo.txt", "r");
        while ((c = getc(fp)) != EOF) {
            printf("%c", c);
        }
        fclose(fp);
        return 0;
    }

Παραγωγή:

Διαδραστική ανάγνωση και εγγραφή αρχείου σε έξοδο C

επεξεργασία εξόδου αρχείων getc και putc σε C

  1. Στο παραπάνω πρόγραμμα έχουμε δημιουργήσει και ανοίξει ένα αρχείο που ονομάζεται demo σε λειτουργία εγγραφής.
  2. Αφού εκτελεστεί μια λειτουργία εγγραφής, τότε το αρχείο κλείνει χρησιμοποιώντας τη συνάρτηση fclose.
  3. Ανοίξαμε ξανά ένα αρχείο που τώρα περιέχει δεδομένα σε λειτουργία ανάγνωσης. Ένας βρόχος while θα εκτελεστεί μέχρι να βρεθεί το eof. Μόλις βρεθεί το τέλος του αρχείου, η λειτουργία θα τερματιστεί και τα δεδομένα θα εμφανιστούν χρησιμοποιώντας τη λειτουργία printf.
  4. Μετά την εκτέλεση μιας λειτουργίας ανάγνωσης, το αρχείο κλείνει ξανά χρησιμοποιώντας τη συνάρτηση fclose.

Συχνές Ερωτήσεις

Η λειτουργία κειμένου μεταφράζει τους χαρακτήρες νέας γραμμής ώστε να ταιριάζουν με το λειτουργικό σύστημα, ενώ η δυαδική λειτουργία, που ανοίγει με "rb" ή "wb", γράφει τα byte ακριβώς όπως είναι. Χρησιμοποιήστε τη δυαδική λειτουργία για εικόνες, ήχο ή οποιαδήποτε δεδομένα όπου πρέπει να διατηρηθεί η ακριβής διάταξη byte.

Η συνάρτηση fopen επιστρέφει NULL όταν ένα αρχείο δεν μπορεί να ανοιχτεί, όπως όταν λείπει ένα αρχείο, δεν έχει επιτραπεί η πρόσβαση ή ο δίσκος είναι γεμάτος. Πάντα να ελέγχετε τον δείκτη που επιστρέφεται για NULL πριν από την ανάγνωση ή την εγγραφή, διαφορετικά το πρόγραμμα χρησιμοποιεί έναν μη έγκυρο δείκτη και συνήθως παρουσιάζει σφάλμα.

Η λειτουργία εγγραφής "w" περικόπτει ένα υπάρχον αρχείο, διαγράφοντας το περιεχόμενό του πριν από την εγγραφή και δημιουργεί το αρχείο όταν αυτό απουσιάζει. Η λειτουργία προσθήκης "a" διατηρεί τα υπάρχοντα δεδομένα και προσθέτει νέο περιεχόμενο στο τέλος, επομένως τίποτα από τα ήδη αποθηκευμένα δεν χάνεται.

Η εντολή fseek μετακινεί τον δείκτη του αρχείου σε μια μετατόπιση byte που μετράται από SEEK_SET, SEEK_CUR ή SEEK_END. Η εντολή ftell επιστρέφει την τρέχουσα θέση byte του δείκτη και η εντολή rewind την στέλνει πίσω στην αρχή του αρχείου. Μαζί παρέχουν τυχαία πρόσβαση αντί για διαδοχική ανάγνωση.

Το fgets διαβάζει μια ολόκληρη γραμμή, σταμάταping σε νέα γραμμή ή μετά από n-1 χαρακτήρες, επομένως σέβεται το μέγεθος του buffer. Το fscanf διαβάζει μορφοποιημένα, διαχωρισμένα με κενά σημεία tokens και μπορεί να υπερχειλίσει έναν μικρό πίνακα. Για την ασφαλή ανάγνωση πλήρων γραμμών, το fgets είναι η καλύτερη επιλογή.

Η τιμή EOF είναι μια σταθερά, συνήθως -1, που σηματοδοτεί το τέλος ενός αρχείου. Συναρτήσεις ανάγνωσης όπως οι getc, fgetc και fscanf επιστρέφουν EOF όταν δεν υπάρχουν άλλα δεδομένα, γι' αυτό και οι βρόχοι συγκρίνουν το αποτέλεσμά τους με την τιμή EOF για να σταματήσουν την ανάγνωση.

Ναι. Ένας βοηθός κωδικοποίησης τεχνητής νοημοσύνης μπορεί να δημιουργήσει ρουτίνες fopen, fprintf και fgets από μια απλή προτροπή, να εξηγήσει κάθε λειτουργία αρχείου και να εντοπίσει σφάλματα, όπως έναν έλεγχο NULL που λείπει ή ένα μη κλειστό αρχείο. Να μεταγλωττίζετε και να δοκιμάζετε πάντα τον κώδικα που προτείνεται από την τεχνητή νοημοσύνη πριν τον εμπιστευτείτε.

GitHub Copilot γράφει κώδικα χειρισμού αρχείων C, προτείνοντας πλήρη μπλοκ fopen, fputs και fscanf από ένα σύντομο σχόλιο ή όνομα συνάρτησης. Συχνά προσθέτει την αντίστοιχη κλήση fclose και έναν έλεγχο σφάλματος, αν και θα πρέπει να ελέγξετε τη δημιουργημένη λογική.

Συνοψίστε αυτήν την ανάρτηση με: