ΠΕΡΙΕΧΟΜΕΝΑ

 

§         ΕΙΣΟΔΟΣ – ΕΞΟΔΟΣ ΣΤΗ C

o       ΡΟΕΣ ΚΑΙ ΑΡΧΕΙΑ

o       STREAMS

o       CONSOLE I/O

o       FORMATED CONSOLE I/O

-         printf()

-         scanf()

 

 

 

 

 

 

 

 

 

 

ΚΕΦΑΛΑΙΟ 2Ο

ΕΙΣΟΔΟΣ – ΕΞΟΔΟΣ ΣΤΗ C

 

            Η είσοδος και η έξοδος στη C υποστηρίζεται από τη χρήση συναρτήσεων βιβλιοθήκης. Δεν υπάρχουν C keywords που να εκτελούν Ι/Ο διαδικασίες. Παρ’ όλ’ αυτά, το ANSI standard, το οποίο ακολουθείται από την Turbo C, ορίζει ένα ολοκληρωμένο σετ Ι/Ο συναρτήσεων (buffered file system).

 

            Το παλιό standard του UNIX ορίζει ένα δεύτερο σύστημα διαδικασιών χειρισμού Ι/Ο. Η Turbo C υποστηρίζει και τα δύο συστήματα δίνοντας όμως έμφαση στο ANSI (buffered I/O).

 

ΡΟΕΣ ΚΑΙ ΑΡΧΕΙΑ (STREAMS AND FILES)

 

            Βασικά πρέπει να κατανοηθεί η διαφορά μεταξύ των όρων streams και files. Το σύστημα Ι/Ο της C παρέχει ένα σύστημα στον προγραμματιστή το οποίο εξαρτάται από τη συσκευή η οποία προσπελαύνεται. Αυτό σημαίνει ότι οριοθετείται ένα επίπεδο απόστασης μεταξύ προγραμματιστή – συσκευής. Η απόσταση αυτή καλείται ροή, ενώ η συσκευή που προσπελαύνεται καλείται αρχείο.

 

STREAMS

 

            Το buffered file system σχεδιάστηκε για να εργάζεται με μία πληθώρα συσκευών όπως τερματικά, οδηγοί δισκετών και tape streamers. Ακόμα κι αν οι συσκευές αυτές είναι ανόμοιες το BFS μεταφέρει το καθένα από αυτά σε μία λογική συσκευή η οποία καλείται stream. Διακρίνουμε δύο είδη streams, τα text και τα binary.

 

i)                    Text Streams

Text stream είναι μία σειρά από χαρακτήρες οργανωμένοι σε γραμμές που τελειώνουν από ένα χαρακτήρα νέας γραμμής. Το προτεινόμενο ANSI standard ορίζει ότι ο χαρακτήρας της νέας γραμμής έγκειται επιλεκτικά στην εφαρμογή. Ο newline χαρακτήρας μπορεί να είναι το return ή το line feed.

 

ii)                   Binary Streams

Μία δυαδική ροή είναι μία σειρά από bytes τα οποία έχουν μία ένα προς ένα ανταπόκριση με αυτή που υπάρχουν στην εξωτερική συσκευή. Αυτό σημαίνει ότι δεν υπάρχει μετάφραση χαρακτήρων. Επίσης ο αριθμός των bytes που διαβάζονται ή γράφονται πρέπει να είναι ίδιος με τον αριθμό που βρίσκεται στην εξωτερική συσκευή.

 

CONSOLE I/O

 

            Η είσοδος / έξοδος κονσόλας αναφέρεται σε διαδικασίες οι οποίες λαμβάνουν χώρα στο πληκτρολόγιο ή την οθόνη του η/υ. Γενικότερα η Console I/O εκτελείται χρησιμοποιώντας ειδικές περιπτώσεις του BFS. Συνοπτικά πάντως δεχόμαστε ότι η κυρίως χρησιμοποιούμενη συσκευή για I/O είναι η οθόνη.

 

 

-          Συναρτήσεις getche ( ) και putchar ( )

 

Οι πιο απλές από την συναρτήσεις Console I/O είναι η getche ( ) η οποία διαβάζει ένα χαρακτήρα από το πληκτρολόγιο, και η putchar ( ) η οποία εμφανίζει στην οθόνη.

 

Η getche ( ) περιμένει έως ότου ένας χαρακτήρας πληκτρολογηθεί (πατηθεί ένα πλήκτρο). Το πλήκτρο που πατήθηκε εμφανίζεται στην οθόνη (get character with echo). Το πρωτότυπό της είναι:

 

                                                                                                                                    int getche (void);         και βρίσκεται στο conio.h

 

Υπάρχουν δύο σημαντικές παραλλαγές της getche ( ) :

 

i)                    getchar ( )

Είναι μία original UNIXbased input συνάρτηση χαρακτήρων. Το πρόβλημά της είναι ότι περιμένει έως ότου πληκτρολογηθεί return. Αυτό γιατί στο UNIX πρέπει να πατηθεί return για να γίνει οποιαδήποτε ενέργεια. Πάντως αφήνει έναν ή περισσότερους χαρακτήρες στον buffer μετά την επιστροφή του. Το πρωτότυπό της είναι:

 

                                                                                       int getchar (void);      και βρίσκεται στο stdio.h

 

                                                                                                               Η χρήση της δε συνιστάται.

 

ii)                   getch ( )

Είναι ίδια με τη getche ( ) με μόνη διαφορά ότι δεν εμφανίζει το χαρακτήρα που δέχεται στην οθόνη. Το πρωτότυπό της βρίσκεται στο conio.h.

 

 

Η putchar ( ) εμφανίζει ένα χαρακτήρα στην οθόνη στην τρέχουσα θέση του κέρσορα. Το πρωτότυπό της είναι:

 

                                                                                                                                    int putchar (int ch);      και βρίσκεται στο stdio.h

 

Π.χ.

 

#include <conio.h>

#include <stdio.h>

main ( )                                            Εισάγει ένα χαρακτήρα από το

{                                                        πληκτρολόγιο και μετά τον

  char ch;                                          τυπώνει στην οθόνη.

  ch = getche ( );

  putchar (ch);

}

 

-          Συναρτήσεις gets ( ) και puts ( )

 

Είναι συναρτήσεις που επιτρέπουν το διάβασμα και το γράψιμο strings στην οθόνη.

 

Η gets ( ) διαβάζει ένα string από το πληκτρολόγιο και το τοποθετεί σε κάποια διεύθυνση μνήμης. Υπενθυμίζεται ότι στη C ένα string ουσιαστικά είναι array of characters. Μπορούμε να πληκτρολογούμε χαρακτήρες έως ότου πατηθεί enter. Το enter δε δίνεται μέρος του string. Στην πραγματικότητα είναι αδύνατο στο CR να αποτελεί μέρος του string (αντίθετα στην getchar ( ) αυτό γίνεται). Αν πληκτρολογηθούν λάθη μπορούν να σβηστούν και να διορθωθούν πριν πατηθεί enter. Το πρωτότυπό της είναι:

                                           char   *gets (char   *string);

όπου το string είναι ένα array of char και βρίσκεται το stdio.h.

            Η συνάρτηση gets( ) επιστρέφει έναν pointer στο string.

 

            Η puts( ) γράφει ένα string στην οθόνη ακολουθούμενο από νέα γραμμή. Αναγνωρίζει όλους τους backslash χαρακτήρες. Η puts( ) δέχεται μόνο χαρακτήρες και όχι αριθμούς. Μιας και πιάνει λιγότερο χώρο από την printf( ) και είναι ταχύτερη, χρησιμοποιείται περισσότερο όταν έχουμε μη φορμαρισμένες εμφανίσεις. Το πρωτότυπό της είναι:

                                                                                                char   *puts (char  *string);      βρίσκεται στο stdio.h

 

Π.χ.

              #include <stdio.h>

              main( )

              {

                char ch [80];

                puts ( “Δώσε όνομα \ n”);

                gets (ch);

                printf ( “Το όνομα είναι %s”, ch);

              }

 

 

FORMATED CONSOLE I/O (ΜΟΡΦΟΠΟΙΗΜΕΝΗ Ι/Ο)

 

              Συμπληρωματικά στις απλές Ι/Ο συναρτήσεις η ενσωματωμένη βιβλιοθήκη της TC περιέχει δύο συναρτήσεις οι οποίες εκτελούν μορφοποιημένη είσοδο και έξοδο στους ενσωματωμένους τύπους δεδομένων. Αυτές είναι οι printf( ) και η scanf(). Ο όρος μορφοποιημένη αναφέρεται στο γεγονός ότι αυτές οι συναρτήσεις μπορούν να διαβάσουν και να γράψουν δεδομένα σε διάφορες μορφές κάτω από τον έλεγχο του προγραμματιστή. Οι δύο αυτές συναρτήσεις μπορούν να διαχειριστούν οποιοδήποτε τύπο δεδομένων (characters, string, numbers, κλπ).

 

-          printf( )

Η συνάρτηση αυτή χρησιμοποιείται ως εξής:

 

                                                                              printf( “control string”, argument list”);

 

              Το control string εννοεί δύο τύπους πραγμάτων. Το πρώτο περιέχει χαρακτήρες οι οποίοι πρέπει να τυπωθούν στην οθόνη. Ο δεύτερος τύπος περιέχει εντολές μορφοποίησης οι οποίες ορίζουν τον τρόπο με τον οποίο θα τυπώνονται τα ορίσματα. Μία εντολή μορφοποίησης ξεκινά με το % και ακολουθείται από τον κωδικό μορφοποίησης. Σημειώνεται ότι τα ορίσματα που ακολουθούν πρέπει να είναι ακριβώς ίδια στον αριθμό με τις εντολές μορφοποίησης. Π.χ.:

 

                                      printf( “Hi %c %d %s”, ‘c’, 10, “There”);

 

 

                                              Θα εμφανιστεί: Hi c10 There


Οι κωδικοί μορφοποίησης είναι οι ακόλουθοι:

 

ΚΩΔΙΚΟΣ

 

%c

%d

%i

%e

%f

%g

%o

%s

%u

%x

%%

%p

%n

ΕΝΝΟΙΑ

 

Ένας απλός χαρακτήρας

Δεκαδικός (ακέραιος) αριθμός

Δεκαδικός (ακέραιος) αριθμός

Floating point αριθμός σε εκθετική μορφή

Αριθμός κινητής υποδιαστολής

Κάτι ανάλογο με το %e και το %f

Οκταδικός αριθμός

String χαρακτήρων

Unsigned αριθμός

Δεξαεξαδικός

Τυπώνει %

Pointer

Ακέραιος Pointer χαρακτήρων 

 

 

Οι εντολές μορφοποίησης διαθέτουν τροποποιητές οι οποίοι ορίζουν το μήκος του πεδίου, τον αριθμό των δεκαδικών σημείων και τη leftjustification flag.

 

Ένας ακέραιος μεταξύ του % και της εντολής μορφοποίησης δρα σαν καθαριστής μήκους. Αυτό γεμίζει με 0 ή κενά το αποτέλεσμα για να σιγουρέψει το μέγεθος. Αν θέλουμε να γεμίσουμε με 0 θα τοποθετήσουμε το 0 πριν τον καθοριστή του πεδίου. Π.χ. %05d θα ορίσει έναν αριθμό 5 ψηφίων με μηδενικά μπροστά του.

 

Για να ορίσουμε ένα συγκεκριμένο αριθμό δεκαδικών ψηφίων τοποθετούμε το δεκαδικό σημείο μετά τον καθοριστή μήκους και έπειτα τον αριθμό που θα ορίζει τα δεκαδικά σημεία. Π.χ. %10.4f θα ορίσει έναν αριθμό με 10 ακέραια και 4 δεκαδικά ψηφία.

 

Όταν όμως αυτό συμβαίνει σε string ή ακεραίους οι δύο αριθμοί ορίζουν το μικρότερο και το μεγαλύτερο μέγεθος. Π.χ. %5.7s θα ορίσει ένα string το οποίο δε θα είναι μικρότερο από 5 αλλά και δε θα είναι μεγαλύτερο από 7. Το string θα στρογγυλοποιηθεί προς το τέλος.

 

Εξ ορισμού όλες οι έξοδοι είναι rightjustified. Αν το μήκος του πεδίου είναι μεγαλύτερο από τα δεδομένα, τότε αυτά θα τοποθετηθούν στη δεξιά άκρη του πεδίου. Φυσικά μπορούμε να αλλάξουμε τις πληροφορίες σε leftjustified τοποθετώντας το αμέσως μετά το %. Π.χ. %-10.2f θα ορίσει ένα fp αριθμό με 2 δεκαδικά και 10 ακεραίους ο οποίος θα είναι lj.

 

Υπάρχουν δύο τροποποιητές εντολών μορφοποίησης οι οποίοι επιτρέπουν στην printf( ) να τυπώνει long και short integers. Οι τροποποιητές αυτοί τοποθετούνται στους καθοριστές d, i, o, u, και x.

 

-          Ο τροποποιητής l λέει στην printf( ) ότι ακολουθούν δεδομένα τύπου long. Π.χ. %ld σημαίνει ότι ακολουθεί long int.

-          Ο τροποποιητής h λέει στην printf( ) ότι ακολουθούν δεδομένα τύπου short. Π.χ. %hu σημαίνει ότι ακολουθούν δεδομένα τύπου unsigned short int.

 

Επίσης ο τροποποιητής l χρησιμοποιείται και με τις εντολές floating point e, f και g για να δείξει ότι ένας double ακολουθεί.

 

Παραδείγματα της printf( )

 


printf( ) statement                                           output

 

(“% -5.2f”, 123.234)                                        123.23

(“%5.2f”, 3.234)                                                  3.23

(“%10s”, “hello”)                                                          hello

(“%-10s”, “hello”)                                                   hello

 

 

-          scanf( )

 

Είναι μία συνάρτηση εισόδου γενικών καθηκόντων. Διαβάζει όλους τους ενσωματωμένους τύπους δεδομένων και αυτομάτως τροποποιεί αριθμούς στο ανάλογο format. Είναι κάτι σαν το αντίγραφο της printf( ). Η γενική της φόρμα είναι:

                  Sscanf(“control string”, argument list);

 

Το control string χρησιμοποιεί τις παρακάτω εντολές:

 

 

ΚΩΔΙΚΟΣ

 

%c

%d

%Ii

%e

%f

%h

%o

%s

%x

%p

%n

 

ΕΝΝΟΙΑ

 

Εισαγωγή ενός μόνο χαρακτήρα

Εισαγωγή δεκαδικού (ακέραιου) αριθμού

Εισαγωγή δεκαδικού (ακέραιου) αριθμού

Εισαγωγή floating point αριθμού

Εισαγωγή floating point αριθμού

Εισαγωγή short integer

Εισαγωγή οκταδικού αριθμού

Εισαγωγή αλφαριθμητικού

 Εισαγωγή δεκαεξαδικού αριθμού

Εισαγωγή pointer

Λήψη μίας ακέραιας τιμής ίσης με το νούμερο των χαρακτήρων που διαβάζονται

 


 

            Οι καθοριστές μορφοποίησης εισόδου ορίζονται με ένα % και λένε στην scanf( ) τι είδους δεδομένα θα διαβαστούν. Π.χ. το %s ορίζει ένα string ενώ το %d ένα integer.

 

            Ένας χαρακτήρας κενού στο control string προκαλεί την scanf( ) να αγνοήσει έναν ή περισσότερους χαρακτήρες κενού στην είσοδο. Ένας χαρακτήρας κενού μπορεί να είναι space, ή νέα γραμμή. Στην ουσία ένας χαρακτήρας κενού στο control string οδηγεί τη scanf( ) να διαβάσει, αλλά όχι και να αποθηκεύσει, κάθε αριθμό (και το μηδέν) white-space χαρακτήρων έως ότου συναντηθεί non-white space character.

 

            Ένας non-white space character προκαλεί τη scanf( )  να διαβάσει και να απορρίψει ένα χαρακτήρα. Π.χ. “%d,%d” λέει στην scanf( ) να διαβάσει έναν ακέραιο, να διαβάσει και να αγνοήσει ένα κόμμα και τέλος να διαβάσει έναν άλλο ακέραιο. Αν ο χαρακτήρας αυτός δεν ανιχνευτεί η scanf( ) τερματίζεται.

 

            Όλες οι μεταβλητές που χρησιμοποιούνται για να αποθηκεύσουν τιμές μέσω της scanf( ) πρέπει να περνιούνται μέσω των διευθύνσεών τους. Αυτό σημαίνει ότι όλα τα ορίσματα που χρησιμοποιούνται πρέπει να είναι δείκτες στις μεταβλητές χρησιμοποιούμενοι σαν ορίσματα. Αυτό λέγεται «κλήση με αναφορά» και επιτρέπει στη συνάρτηση να αλλάξει τα περιεχόμενα μίας μεταβλητής. Π.χ. αν θέλουμε να διαβάσουμε έναν ακέραιο μέσα στη μεταβλητή count θα γράψουμε:

                                    scanf(“%d”, &count);

 

            Τα string διαβάζονται σαν array of char και στη C, το όνομα ενός πίνακα χωρίς δείκτες, είναι η διεύθυνση του πρώτου στοιχείου του πίνακα. Έτσι για να διαβάσουμε ένα string μέσω της scanf( ) θα γράψουμε:

                                   

                                    scanf(“s”,pinakas);

 

            Σ’ αυτή την περίπτωση το pinakas είναι ένας πίνακας χαρακτήρων. Το pinakas μέσα στη scanf( ) είναι ήδη ένας δείκτης και δεν υπάρχει λόγος για χρήση του τελεστή &.

 

            Τα δεδομένα που θα δίνουμε κατά την εκτέλεση scanf( ) πρέπει να ακολουθούνται από spaces, tabs ή newlines. Έτσι έχουμε:

 

                                    scanf( “%d%d”, &r, &c);

 

            Στο παράδειγμα αυτό μία είσοδος τύπου 10 20 είναι αποδεκτή ενώ μία είσοδος τύπου 10,20 όχι.

 

            Οι εντολές μορφοποίησης μπορούν να ορίσουν έναν καθοριστή μέγιστου μεγέθους πεδίου. Αυτός είναι ένας ακέραιος αριθμός ο οποίος οριοθετείται μεταξύ του % και του καθοριστή και ορίζει το ακόλουθο όριο χαρακτήρων για ένα πεδίο. Π.χ. αν θέλουμε να διαβάσουμε έως 20 χαρακτήρες στη μεταβλητή str θα γράψουμε:

 

                                                scanf( “%20s”, str”);

 

            Εάν η είσοδος είναι μεγαλύτερη από 20 χαρακτήρες μία υπό – κλήση αρχίζει να ενεργοποιείται για τους χαρακτήρες που απέμειναν. Π.χ. αν στην παραπάνω scanf( ) δοθούν οι χαρακτήρες από Α – Ζ, στην str θα τοποθετηθούν οι χαρακτήρες από Α – Τ. Οι υπόλοιποι UZ δεν έχουν χρησιμοποιηθεί ακόμη. Σε μία άλλη εκτίμηση της scanf( ) π.χ. scanf(“%s, str); οι χαρακτήρες που απέμειναν θα τοποθετηθούν στην str.

 

            Η είσοδος σ’ ένα πεδίο πρέπει να τερματίζεται πριν γεμίσει το πεδίο. Σ’ αυτή την περίπτωση η scanf( ) προχωράει στο επόμενο πεδίο (αν υπάρχει).

 

ΠΡΟΣΟΧΗ: Εάν υπάρχουν χαρακτήρες στο control string περιλαμβάνοντας κενά, tab, κλπ αυτοί οι χαρακτήρες ορίζουν και απορρίπτουν χαρακτήρες από το input stream. Όποιος χαρακτήρας ορίζεται απορρίπτεται.

 

                        Π.χ.      scanf(“%s t %s”, &x, &y );

 

            Αν δοθεί 10t20, το t θα απορριφθεί μιας και έχει οριστεί στο control string, ενώ η x = “10” και y = “20”. Π.χ. scanf ( “%s”, name); δε θα επιστρέψει προτού πληκτρολογηθεί ένα κενό και μετά το enter. Αυτό συμβαίνει γιατί το κενό μετά το %s λέει στη scanf( ) να διαβάσει ή να απορρίψει τα κενά.

 

            H scanf( ) δεν πρέπει να χρησιμοποιείται για την εμφάνιση μηνυμάτων.