Wykład II - semestr II Kierunek Informatyka Wydział Matematyki Stosowanej Politechniki Śląskiej Gliwice, 2015 c Copyright 2015 Janusz Słupik
Operacje dyskowe - zapis do pliku #include <iostream> #include <fstream> using namespace std; int main() ofstream plik( "test.txt" ); if( plik.is_open() ) plik << "Napis\n" << "inny" << endl; plik << 12; plik.close(); else cout << "Nieudane otwarcie pliku." << endl; return 0;
Opcje zapisu ofstream plik( "test.txt" ); //tryb tekstowy z nadpisywaniem istniejącego pliku ofstream plik( "test.txt", ios::app ); //dopisywanie na końcu ofstream plik( "test.bin", ios::binary ); //tryb binarny ofstream plik( "test.bin", ios::app ios::binary ); //dopisywanie w trybie binarnym
Odczyt z pliku ofstream plik( "test.txt" ); plik << "Taki napis\n inny" ; plik.close(); string s; ifstream plik( "test.txt" ); while( true ) plik >> s; if( plik.eof() ) break; cout << s << endl; plik.close(); Zwróci: Taki napis inny
Odczyt z pliku po linii ofstream plik( "test.txt" ); plik << "Taki napis\n inny" ; plik.close(); string linia; ifstream plik( "test.txt "); if( plik.is_open() ) while( true ) getline( plik, linia ); if( plik.eof() ) break; cout << linia << endl; plik.close();
Odczyt z pliku Tryb binarny: ifstream plik( "test.bin", ios::binary ); Ustawienie odczytu na końcu pliku: ifstream plik( "test.bin", ios::binary ios::ate ); Odczyt i zapis po bajcie: char bajt; plik.get( bajt ); // lub bajt = plik.get(); plik.put( bajt );
Przykład ifstream plik( "test.bin", ios::binary ); char bajt; while( true ) plik.get( bajt ); if( plik.eof() ) break; cout << bajt << endl; // wypisze znaki //cout << (int) (unsigned char) bajt << endl; //wypisałoby kody 0-255
Pozycja w pliku Ustawianie odpowiedniej pozycji w pliku dla odczytu: plik.seekg( 3, ios::beg ); //3 znak od początku plik.seekg( 2, ios::cur ); //2 znaki dalej od bieżącej plik.seekg( 0, ios::end ); //ostatni znak Zwrócenie aktualnej pozycji w pliku dla odczytu: plik.tellg(); Analogicznie dla zapisu mamy: seekp(... ), tellp()
Przykład Ustalenie rozmiaru pliku wejściowego. ifstream plik("test.txt", ios::binary ); plik.seekg( 0, ios::end ); cout << plik.tellg() << endl; albo ifstream plik("test.txt", ios::binary ios::ate ); cout << plik.tellg() << endl;
Metody read i write plik.read( wskaźnik, rozmiar ); plik.write( wskaźnik, rozmiar ); char z; plik1.read( &z, sizeof(z) ); //odczyt bajta plik2.write( "Tekst", sizeof( "Tekst" ) ); int t[] = 1, 2, 3, 4; plik3.write( (char *) t, sizeof( t ) );
Operatory new i delete Operator new przyporządkowuje dynamicznie pamięć, a operator delete ją zwalnia. Operator te wymagają stosowania wskaźników. typ danych *p = new typ danych; Powstaje obiekt typu typ danych wskazywany przez p. delete p; Zwolnienie pamięci wskazywanej przez p. Pamięć ta musi być zarządzana jawnie przez programistę. Jeżeli p jest pusty, to oznacza, że przydzielenie pamięci się nie powiodło. Operator delete może być stosowany jedynie do wskaźnika przekazanego przez new lub zerowego.
Przykład int *p; p = new int;... delete p; int *t; t = new int[20];... delete [] t; Nie musimy sprawdzać, czy p jest różne od zera: if( p!= 0 ) //niepotrzebne - sprawdzane automatycznie delete p;
Zapis tablicy do pliku int rozmiar; cin >> rozmiar; int *t = new int[ rozmiar ]; for( int i=0; i<rozmiar; i++ ) cin >> t[i]; ofstream plik( "tab.bin", ios::binary ); plik.write( (char *) t, rozmiar*sizeof( int ) ); plik.close(); delete [] t;
Odczyt tablicy z pliku ifstream plik( "tab.bin", ios::binary ios::ate ); int n = plik.tellg(); plik.seekg( 0, ios::beg ); char *tmp = new char[ n ]; plik.read( tmp, n ); plik.close(); int *u = ( int* ) tmp; for( int i = 0; i < n/sizeof(int); i++ ) cout << u[i] << endl; delete [] tmp;
XML - reprezentacja danych Zapis danych do pliku w formie tekstowej wymaga ustalenia sposobu rozmieszczenia tych danych. Możemy skorzystać z istniejących rozwiązań: XML - uniwersalny i niezależny od platformy sposób organizowania danych w plikach. Wiele programów potrafi eksportować i importować dane z formatu XML.
XML - reprezentacja danych Dane w pliku XML są reprezentowane w strukturalizowany sposób. Język ten jest językiem znaczników. Każdy otwarty znacznik musi zostać zamknięty. <znacznik> dane </znacznik> W przypadku pustej zawartości pomiędzy otwarciem znacznika i jego zamknięciem dopuszcza się skrót: <znacznik /> Dokument rozpoczyna się instrukcją sterującą, która zawiera informacje o wersji standardu XML, z jakim jest zgodny, oraz o sposobie kodowania znaków. Można stosować komentarze w formie: <!-- komentarz -->
XML - przykład <?xml version="1.0" encoding="windows-1250"?> <spis-osob> <!-- komentarz --> <osoba typ="pracownik"> <imie>adam</imie> <nazwisko>nowak</nazwisko> <telefon>123-456-789</telefon> </osoba> <osoba typ="klient"> <imie>alina</imie> <nazwisko>kowalska</nazwisko> <telefon/> </osoba> </spis-osob>
XML - przykład Plik otwarty w przeglądarce Firefox:
Strumienie łańcuchowe Strumieniami danych są obiekty cin i cout, oraz obiekty klas ifstream i ofstream. #include <sstream> string s = "12.3"; double x; //uzyskanie wartości w x na podstawie s istringstream o1( s ); o1 >> x; string t = "Dzisiejsza temperatura to "; double y = 23.4; //wstawienie wartości y do tekstu w t ostringstream o2; o2 << y << " stopni."; t += o2.str();
Synchronizacja strumienia wejściowego sync - usuwa zbuforowane znaki ze strumienia wejściowego char first, second; cout << "Podaj imie: "; first = cin.get(); cin.sync(); cout << "Podaj nazwisko: "; second = cin.get(); cout << "Pierwsza litera imienia " << first << endl; cout << "Pierwsza litera nazwiska " << second << endl;
Wzorzec funkcji Zapotrzebowanie: void dzialaj( int *t, int n ); void dzialaj( int *t, int n ) int m = 5; for( int i=0; i<n; i++ ) // przetwarzamy t[i], np.: t[i] += m;
Wzorzec funkcji Zapotrzebowanie: void dzialaj( int *t, int n ); void dzialaj( int *t, int n ) int m = 5; for( int i=0; i<n; i++ ) // przetwarzamy t[i], np.: t[i] += m; void dzialaj( int *t, int n ); void dzialaj( float *t, int n ); void dzialaj( double *t, int n ); void dzialaj( char *t, int n );
Wzorzec funkcji Wzorzec funkcji (function template) - posiada informacje o typach określonych w liście argumentów. template <typename nasztyp> void dzialaj( nasztyp *t, int n ) nasztyp m = 5; for( int i=0; i<n; i++ ) // przetwarzamy t[i], np.: t[i] += m;
Kilka typów template <typename jedentyp, typename drugityp> void dodaj( jedentyp a, drugityp b ) jedentyp a; drugityp b; //...
Koniec