18. ΡΕΥΜΑΤΑ(STREAMS) ΚΑΙ ΑΡΧΕΙΑ (FILES) ΡΕΥΜΑ (stream) : ροή δεδοµένων Ιεραρχία κλάσεων ρευµάτων Βασική κλάση της ιεραρχίας: ios Έχει πολλές κοινές συναρτήσεις π.χ. showpoint, χωριζόµενες σε 3 ειδών λειτουργίες Σηµαίες µορφοποίησης (formatting flags), προηγείται το όνοµα της κλάσης ios ios::showpoint, ios::left, ios::showbase.. Συναρτήσεις για τις σηµαίες µορφοποίησης setf(σηµαία), unsetf(σηµαία) H κλάση ios έχει και χειριστές οδηγίες που εισάγονται απευθείας στο ρεύµα: Χειριστές χωρίς ορίσµατα π.χ. endl,hex,oct,dec.. Χειριστές µε ορίσµατα π.χ. setw(εύρος), setiosflags(σηµαίες..), setprecision(ακρίβεια).. cout<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint) << setprecision(1) <<setw(6) <<pososto[m]; Σηµαίες κατάστασης σφάλµατος (Error status flags) Κατάσταση χειρισµού αρχείων (File operation mode) istream: µέλος της ο τελεστής >> istream_withassign: µε αντικείµενο το cin ostream: µέλος της ο τελεστής << ostream_withassign: µε αντικείµενο το cout iostream: οι δηλώσεις των κλάσεων για input & output (κάποιοι χειριστές στο iomanip) ***Oλα τα αρχεία βρίσκονται στον κατάλογο ΙNCLUDE του compiler VK - page 63
ΣΦΑΛΜΑΤΑ ΡΕΥΜΑΤΩΝ Τι συµβαίνει αν ο χρήστης στη διαδικασία εισαγωγής αντί για αριθµό που του ζητείται εισάγει αλφαριθµητικό ή µόνο enter? Υπάρχουν Σηµαίες κατάστασης σφαλµάτων goodbit,badbit, eofbit,.. Συναρτήσεις για τις σηµαίες σφαλµάτων eof(), bad(), good(), clear() while (true) cout<< Enter an integer ; cin>>i; if ( cin.good() ) //αν δεν υπάρχουν σφάλµατα //αφαίρεσε την γραµµή και βγες από το loop cin.ignore(10, '\n'); //συνάρτηση της istream κλάσης break; cin.clear() ; //καθάρισε τα λάθος bit cout<<"...pame pali DOSE ARITHMO\n"; cin.ignore(10, '\n'); //αγνόησε αυτά που σε έδωσαν Για να πούµε στο ρεύµα να µην αγνοεί τα κενά διαστήµατα: cout<< Enter an integer ; cin.unsetf (ios::skipws); //unset flag skip whitespaces cin >>i; if ( cin.good() ) //αν δεν υπάρχουν σφάλµατα.. //ok.. //σφάλµα Μια άλλη προσέγγιση για έλεγχο εισαγωγής ακεραίου µπορεί να είναι: string sint; while (true) cout<< Enter an integer ; cin.unsetf (ios::skipws); //unset flag skip whitespaces cin >>sint; if ( ΟΚΙ (sint)) //αν δεν υπάρχουν σφάλµατα.. //ok i=atoi(sint.c_str() //µετατροπή σε ακέραιο.... //σφάλµα int ΟΚΙ(string str) int j; int slen = str.size(); if (slen == 0 slen > 5) //αν µήκος 0, ή πολύ µεγάλο δεν είναι ακέραιος VK - page 64
return 0; for (j = 0; j < slen; j++) // έλεγχος ένα ένα χαρακτήρα if ( (str[j] < '0' str[j] > '9') && str[j]!= '-') // για µη ψηφίο return 0; double n = atof(str.c_str()); //µετατροπή σε double if (n < -999.0 n > 999.0 ) //είναι εκτός ορίων return 0; return 1; //οκ ΑΡΧΕΙΑ ΜΕ ΡΕΥΜΑΤΑ Για τα αρχεία δίσκου απαιτούνται οι κλάσεις ifstream,ofstream ή fstream Οι αριθµοί αποθηκεύονται στο δίσκο σαν σειρές χαρακτήρων 6. 2 σαν 6,., 2 //52 formato.cpp - Αρχείο FDATA.txt για εγγραφή: x77 6.02Kafka Proust #include <fstream> #include <string> char ch = 'x'; int j = 77; double d = 6.02; string str1 = "Kafka"; string str2 = "Proust"; ofstream fo("fdata.txt"); //fo αντικείµενο fo << ch //µετά το αντικείµενο, συµπεριφέρεται σαν το cout << j << ' ' << d << str1 << ' ' << str2; cout << "File written\n"; //53 formati.cpp FDATA.txt - για ανάγνωση: x77 6.02Kafka Proust #include <fstream> #include <string> char ch; int j; double d; string str1,str2; ifstream fi("fdata.txt"); //fi αντικείµενο fi >> ch >> j >> d >> str1 >> str2; cout << ch << endl << j << endl VK - page 65
<< d << endl << str1 << endl << str2 << endl; Αλφαριθµητικά µε κενά //54. iοline.cpp #include <fstream> //εγγραφή ofstream fo ("TEST.TXT"); fo << "I fear thee, ancientmariner!\n"; fo << "I fear thy skinny hand \n"; fo << "And thou art long, and lank, and brown,\n"; fo << "As is the ribbed sea sand.\n"; fo.close(); //κλείσιµο του αρχείου //ανάγνωση const int MAX = 80; //µέγεθος char buffer[max]; //Προσωρινή αποθήκευση ifstream fi("test.txt"); while(!fi.eof() ) //µέχρι το τέλος του αρχείου fi.getline(buffer, MAX); //ανάγνωση µιας γραµµής cout << buffer << endl; Συναρτήσεις της κλάσης istream >>,get,getline,putback,ignore,peek,count,read,seek,seekg,pos Συναρτήσεις της κλάσης ostream <<,put,flush,write,seek,pos Εντοπισµός τέλος αρχείου while (!fi.eof()) //µέχρι να βρεθεί το τέλος του αρχείου while ( fi.good()) //µέχρι να βρεθεί σφάλµα Γενικότερα αν «όλα πάνε καλά» το αντικείµενο επιστρέφει µη µηδενική τιµή while ( fi) //µέχρι να βρεθεί σφάλµα Kλείσιµο των αρχείων γίνεται µε την συνάρτηση αποδόµησης των ρευµάτων, αλλά καλό είναι να χρησιµοποιούµε την close(). ιαφορετική προσέγγιση αντί για µία εντολή: ofstream fo ( TEST.TXT ); //δηµιουργία και άνοιγµα, δίνω 2 εντολές ofstream fo; //δηµιουργία fo.open( TEST.TXT ); //άνοιγµα VK - page 66
ΑΝΤΙΚΕΙΜΕΝΑ ΚΑΙ ΑΡΧΕΙΑ // 55 opers.cpp εγγραφή και ανάγνωση αντικειµένου #include <fstream> class Person protected: char name[80]; short age; public: void getdata() cout << "Enter name: "; cin >> name; cout << "Enter age: "; cin >> age; void showdata() cout << "Name: " << name << endl; cout << "Age : " << age << endl; ; Person pers; pers.getdata(); ofstream F("PERSON.DAT", ios::binary);//για δυαδικά δεδοµένα //ο τελεστής reinterpret_cast αλλάζει τον τύπο τµήµατος της µνήµης F.write(reinterpret_cast<char*>(&pers),sizeof(pers));//write(str,sizeof(str)) F.close(); ifstream f("person.dat",ios::binary); f.read(reinterpret_cast<char*>(&pers),sizeof(pers));//read(str,sizeof(str)) cout<<"\n"; pers.showdata(); Προσοχή στις προτάσεις που γράφουν και διαβάζουν ένα αντικείµενο F.write(reinterpret_cast<char*>(&pers), sizeof (pers)); F.read(reinterpret_cast<char*>(&pers), sizeof (pers)); η α παράµετρος τους είναι η διεύθυνση του αντικειµένου: &pers η β είναι το µέγεθος των αντικειµένων της κλάσης Tα bit κατάστασης Ta bit κατάστασης που ορίζονται στη κλάση ios ρυθµίζουν τον τρόπο ανοίγµατος ρεύµατος π.χ. ios:binary (δυαδική κατάσταση) in(ανάγνωση), out (εγγραφή),ate(στο τέλος),app(προσάρτηση),trunk(περικοπή).. VK - page 67
είκτες αρχείων είκτης ή τρέχουσα θέση λήψης(current get position) είκτης ή τρέχουσα θέση τοποθέτησης (current put position) Αυτές οι τιµές καθορίζουν τον αριθµό του byte µέσα στο αρχείο που θα γίνει η ανάγνωση ή η εγγραφή. Οι συναρτήσεις seekg() και tellg() χρησιµοποιούνται µε τον δείκτη ανάγνωσης ενώ οι seekp(),tellp() µε τον δείκτη εγγραφής π.χ seekp(-10, ios::end);// τοποθέτηση 10byte πριν το τέλος του αρχείου seekp(-10, ios::cur);// τοποθέτηση 10byte πριν την τρέχουσα θέση Ορίσµατα γραµµής διαταγών (command-line arguments) H συνάρτηση main παίρνει 2 ορίσµατα, argument count πλήθος ορισµάτων και πρώτο όρισµα είναι πάντα το όνοµα διαδροµής του τρέχοντος προγράµµατος, τα δε υπόλοιπα αν υπάρχουν, είναι ανάλογα το πρόγραµµα. //56. comline.cpp //παρουσιάζει τα ορίσµατα γραµµής διαταγών int main(int argc, char* argv[]) cout << "\nargc= " << argc << endl; //πλήθος for(int j = 0; j < argc; j++) //ορίσµατα cout << "Argument " << j << " = " << argv[j] << endl; Έξοδος στον εκτυπωτή outfile.open( PRN ) ή outfile.open( LPT1 ) Τελεστής typeid Χρησιµοποιείται για να δώσει την κλάση ενός αντικειµένου VK - page 68
// 57. Typeid.cpp #include <typeinfo> //για την typeid class Base virtual void virtfunc(void) ; class Derv1 : public Base ; class Derv2 : public Base ; void displayname(base* pb) if ( typeid(*pb)==typeid(derv1)) cout<<"1h PARAGOMENH\n"; cout << " Pointer to an object of:"; cout << typeid(*pb).name() << endl; Base* pbase = new Derv1; displayname(pbase); pbase = new Derv2; displayname (pbase); YΠΕΡΦΟΡΤΩΣΗ ΤΩΝ ΤΕΛΕΣΤΩΝ << και >> //58. englio.cpp <<,>> ανήκoυν στις κλάσεις ostream, istream. class Distance private: int feet; float inches; public: Distance() : feet(0), inches(0.0) Distance(int ft, float in) :feet(ft), inches(in) ; friend istream& operator >>(istream& s, Distance& d); friend ostream& operator <<(ostream& s, Distance& d); istream& operator >> (istream& s, Distance& d) cout << "\nenter feet: "; s >> d.feet; cout << "Enter inches: "; s >> d.inches; return s; ostream& operator << (ostream& s, Distance& d) VK - page 69
s << d.feet << "\' kai " << d.inches << '\"'; return s; Distance dist1, dist2; Distance dist3(11, 6.25); cout << "\nenter two Distance values:"; cin >> dist1 >> dist2; cout << "\ndist1 = " << dist1 <<"\ndist2 = " << dist2; cout << "\ndist3 = " << dist3<< endl; Η υπερφόρτωση του τελεστή >> επιστρέφει κατ αναφορά ένα αντικείµενο της κλάσης istream και δέχεται δυο ορίσµατα τα οποία µεταβιβάζονται κατ αναφορά. Το α είναι αντικείµενο της κλάσης istream (όπως και το cout), το β της κλάσης που θα εµφανιστεί. Ο τελεστής >> δέχεται είσοδο από το ρεύµα του α ορίσµατος και την τοποθετεί στα µέλη του β ορίσµατος. Οι συναρτήσεις πρέπει να είναι φίλες αφού τα αντικείµενα εµφανίζονται στην αριστερή πλευρά του τελεστή. VK - page 70