Strona główna » C++ » Kurs » Zapis danych - operator <<

Zapis danych - operator <<

Plik to strumień

Do wypisywania danych na ekran potrzebny jest strumień cout. W przypadku zapisu do pliku potrzebujemy strumienia typu ofstream, który pozwoli nam na wprowadzanie danych przy pomocy <<.

Zadanie

Plik składa się z linijek, które mają tekst składający się z dwóch części przedzielonych myślnikiem. Program ma za zadanie wczytać przykładowy plik o takiej zawartości:

  1. duze - male
  2. zTakimiTezSobieRadzi - tychNieRusza
  3. cyfry 1, 2, 3 to nie problem - ani troche

Jako wynik powinien zostać stworzony nowy plik tekstowy do którego zostaną zapisane zmienione linijki: wszystkie małe litery przed myślnikiem powinny zostać zamienione na duże. Pozostałe znaki powinny zostać niezmienione.

  1. DUZE - male
  2. ZTAKIMITEZSOBIERADZI - tychNieRusza
  3. CYFRY 1, 2, 3 TO NIE PROBLEM - ani troche

Możemy założyć, że dane w pliku są poprawne i, że długość pojedynczej linijki w pliku tekstowym jest niedłuższa niż 4096 znaków.

4096 znaków

Nie znamy z góry długości pliku, dlatego w celu optymalizacji odczytywania danych będziemy wczytywać plik linijka po linijce. Jednak znamy tylko maksymalną długość linijki, więc stworzymy tablicę znaków służącą za bufor. W celu ułatwienia ewentualnej zmiany wielkości bufora zadeklarujemy zmienną stałą typu int na początku kodu:

  1. const int BUFF_SIZE = 4096;

Funkcja pomocnicza - changeTXT()

Przed rozpoczęciem pisania głównej funkcji napiszemy funkcję pomocniczą changeTXT(). Jako argument przyjmuje tablice znaków char. Funkcja może modyfikować podany argument, więc nic nie zwraca.

  1. void changeTXT(char* c){
  2.   int i = 0;
  3.   while(c[i] != '-' && c[i]){
  4.     if(c[i] <= 'z' && c[i] >= 'a')
  5.       c[i] += 'A' - 'a';
  6.     i++;
  7.   }
  8. }

(2.) Ustalamy indeks od którego przeglądamy napis. (3.) Rozpoczynamy pętle, która będzie sprawdzać każdy kolejny znak napisu dopóki nie natrafi na myślnik lub koniec napisu. (4.) Jeśli jesteśmy w pętli to znaczy, że wciąż przeglądamy pierwszą część tekstu czyli kiedy trafimy na małą literę to (5.) zamieniamy ją na dużą. (6.) Przechodzimy do następnego znaku.

Odczyt i zapis

Do zapisania pliku potrzebujemy strumienia typu ofstream, który możemy zadeklarować po dołączeniu biblioteki fstream.

  1. int main() {
  2.   ifstream file;
  3.   file.open("task.txt");
  4.   if(file.good()){

(2.) Deklarujemy nową zmienną typu ifstream służącą do odczytywania pliku. (3.) Otwieramy plik zawierający tekst do skonwertowania. (4.) Upewniamy się, że plik jest gotowy do odczytu.

  1.     ofstream result;
  2.     result.open("result.txt");

(5.) Deklarujemy nową zmienną typu ofstream. Jest to strumień, który pozwoli nam zapisywać dane do pliku. (6.) Wskazujemy komputerowi do jakiego pliku chcemy zapisać dane. W przypadku, gdy taki plik nie istnieje to zostanie utworzony, a jeśli istnieje to zostanie nadpisany.

  1.     if(result.good()){
  2.       char* line = new char[BUFF_SIZE];

(7.) Sprawdzamy czy strumień jest gotowy do zapisu. Jeśli tak to (8.) deklarujemy zmienną line, która będzie naszym buforem podczas odczytywania pliku.

  1.       while(file.good()) {
  2.         file.getline(line, BUFF_SIZE);
  3.         changeTXT(line);
  4.         result << line << endl;
  5.       }

(9.) Dopóki odczytujemy dane wykonujemy pętle while. (10.) Do zmiennej line wczytujemy kolejną linijkę z pliku. (11.) Konwertujemy dane w linijce. (12.) Wprowadzamy do wyjściowego pliku nowe dane.

  1.       delete[] line;
  2.       cout << "Sukces";

Kiedy zakończymy pętle while() (14.) dealokujemy pamięć zajętą przez bufor i (15.) pokazujemy komunikat o powodzeniu konwersji.

  1.     } else {
  2.       cout << "Błąd: Nie można otworzyć pliku zapisu!";
  3.     }
  4.     result.close();

Jeśli jednak nasz plik wyjściowe nie został prawidłowo otwarty to wyświetlamy komunikat. Bardzo ważne jest, aby (20.) zamknąć strumień, aby inne programy mogły mieć dostęp do lokalizacji pliku.

  1.   } else {
  2.     cout << "Błąd: Podany plik nie istnieje!";
  3.   }
  4.   file.close();
  5.   system("PAUSE");
  6.   return 0;
  7. }

W przypadku (22.) Braku odczytania pliku wejściowego warto wypisać odpowiedni komunikat. (24.) Zamykamy strumień odczytu pliku i (25.) czekamy na interakcję użytkownika i (25.) kończymy wykonywanie programu.

Zadania

Zadanie 1

Zmień kod tak, aby wszystkie małe litery przed myślnikiem były zamienione na duże, a po myślniku każdy wyraz zaczynał się z dużej litery, a pozostałem miał małe. Dla ułatwienia możesz przyjąć, że pomiędzy dwoma wyrazami jest spacja.