ΠΕΡΙΕΧΟΜΕΝΑ
o STREAMS
-
printf()
-
scanf()
ΕΙΣΟΔΟΣ – ΕΞΟΔΟΣ ΣΤΗ 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 παρέχει ένα σύστημα στον προγραμματιστή το οποίο εξαρτάται
από τη συσκευή η οποία προσπελαύνεται. Αυτό σημαίνει ότι οριοθετείται ένα
επίπεδο απόστασης μεταξύ προγραμματιστή – συσκευής. Η απόσταση αυτή καλείται
ροή, ενώ η συσκευή που προσπελαύνεται καλείται αρχείο.
Το 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 εκτελείται χρησιμοποιώντας ειδικές περιπτώσεις του BFS. Συνοπτικά πάντως δεχόμαστε ότι η κυρίως
χρησιμοποιούμενη συσκευή για I/O είναι η οθόνη.
-
Συναρτήσεις getche ( ) και putchar ( )
Οι πιο απλές από την συναρτήσεις Console I/O είναι η getche ( ) η οποία διαβάζει ένα χαρακτήρα από το
πληκτρολόγιο, και η putchar
( ) η οποία εμφανίζει στην οθόνη.
Η getche ( ) περιμένει
έως ότου ένας χαρακτήρας πληκτρολογηθεί (πατηθεί ένα πλήκτρο). Το πλήκτρο που
πατήθηκε εμφανίζεται στην οθόνη (get
character with echo). Το πρωτότυπό της είναι:
int getche (void); και βρίσκεται στο conio.h
Υπάρχουν δύο σημαντικές παραλλαγές της getche ( ) :
i)
getchar ( )
Είναι μία original UNIX – based
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( “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
χαρακτήρων |
Οι εντολές
μορφοποίησης διαθέτουν τροποποιητές οι οποίοι ορίζουν το μήκος του πεδίου, τον
αριθμό των δεκαδικών σημείων και τη left – justification flag.
Ένας
ακέραιος μεταξύ του % και της εντολής μορφοποίησης δρα σαν καθαριστής μήκους.
Αυτό γεμίζει με 0 ή κενά το αποτέλεσμα για να σιγουρέψει το μέγεθος. Αν θέλουμε
να γεμίσουμε με 0 θα τοποθετήσουμε το 0 πριν τον καθοριστή του πεδίου. Π.χ. %05d θα ορίσει έναν αριθμό 5 ψηφίων με μηδενικά μπροστά
του.
Για να
ορίσουμε ένα συγκεκριμένο αριθμό δεκαδικών ψηφίων τοποθετούμε το δεκαδικό
σημείο μετά τον καθοριστή μήκους και έπειτα τον αριθμό που θα ορίζει τα
δεκαδικά σημεία. Π.χ. %10.4f
θα ορίσει έναν αριθμό με 10 ακέραια και 4 δεκαδικά ψηφία.
Όταν όμως
αυτό συμβαίνει σε string ή
ακεραίους οι δύο αριθμοί ορίζουν το μικρότερο και το μεγαλύτερο μέγεθος. Π.χ. %5.7s θα ορίσει ένα string το οποίο δε θα είναι μικρότερο από 5 αλλά και δε θα είναι
μεγαλύτερο από 7. Το string θα
στρογγυλοποιηθεί προς το τέλος.
Εξ ορισμού
όλες οι έξοδοι είναι right – justified. Αν το μήκος του πεδίου είναι
μεγαλύτερο από τα δεδομένα, τότε αυτά θα τοποθετηθούν στη δεξιά άκρη του
πεδίου. Φυσικά μπορούμε να αλλάξουμε τις πληροφορίες σε left – justified
τοποθετώντας το αμέσως μετά το %. Π.χ. %-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
Είναι μία συνάρτηση εισόδου γενικών καθηκόντων. Διαβάζει όλους τους
ενσωματωμένους τύπους δεδομένων και αυτομάτως τροποποιεί αριθμούς στο ανάλογο 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 θα τοποθετηθούν οι χαρακτήρες από Α – Τ. Οι
υπόλοιποι U – Z δεν έχουν χρησιμοποιηθεί ακόμη. Σε μία άλλη εκτίμηση
της 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( ) δεν πρέπει να χρησιμοποιείται
για την εμφάνιση μηνυμάτων.