Dane do programów wprowadzaliśmy do tej pory z klawiatury (lub generowaliśmy liczby losowe).
Wyniki obliczeń wypisywane były na ekranie komputera.
Duże ilości danych trudno jednak wpisywać ręcznie i w większości przypadków pobieramy je z plików zapisanych na dysku.
Podobnie jest z wynikami obliczeń – można je zapisać w postaci pliku i przeglądać w dowolnym momencie na ekranie komputera.
Dane do plików zapisujemy sekwencyjnie, to znaczy, że muszą być zapisywane po kolei.
Aby zapisać element setny należy najpierw zapisać 99 elementów.
Podobnie jest z odczytywaniem.
Plik należy otworzyć (do zapisu lub odczytu) OPEN i po zakończeniu działań koniecznie go zamknąć CLOSE.
Plik można otworzyć:
IFSTREAMOFSTREAMFSTREAMWRITE i strumieniem <<.READ i strumieniem >>.EOF pozwala sprawdzić czy ciągnięto już koniec pliku.Do obsługi konsoli służyła biblioteka iostream, do obsługi strumieni plikowych należy zadeklarować bibliotekę fstream.
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream ZAPIS("dane.txt");
int l=128;
string t="Ala ma kota";
ZAPIS << "piszemy do pliku" << endl;
ZAPIS << l << endl;
ZAPIS << t << endl;
string tekst;
cout << "wpisz tekst:";
cin >> tekst;
ZAPIS << tekst<< endl;
ZAPIS.close();
return 0;
}
W pliku dane.txt znajdują się 4 wiersze tekstów, które można odczytać zwykłym notatnikiem
piszemy do pliku
128
Ala ma kota
cześć
ofstream - strumień o nazwie ZAPIS kojarzymy z plikiem ”dane.txt” na dysku w katalogu bieżącym.
Możemy zapisywać liczby i teksty, identycznie jak na ekranie konsoli za pomocą polecenia COUT.
Bezwzględnie należy pamiętać o zamknięciu strumienia plikowego za pomocą polecenia
close.
W pliku tekstowym "dane.txt" pojawią się 4 wiersze tekstu.
Problemem mogą być polskie znaki diakrytyczne, zapisywane przez Windows w kodzie OEM 852.
Podczas wczytywania tekstów z konsoli posługujemy się typem string, który reaguje standardowo na spację i enter.
Typu char należy używać raczej do wczytywania pojedynczych znaków.
Zapis do pliku (char): klawiatura-plik tekstowy
Do wczytywania znaków używamy funkcji getch() z biblioteki conio.h. Program będzie wczytywał znaki z klawiatury, zapisywał je do pliku dyskowego. Pętla zapisu kończy się w momencie naciśnięci klawisza ESC (kod 27).
ofstream klaw("klaw.txt");
char c;
do {
c=getch();
if (c==13) {
cout << endl;
klaw << endl;
}
if (c!=27){
cout << c;
klaw << c;
}
} while (c!=27);
klaw.close();
Zwróć uwagę, w jaki sposób program obsługuje klawisz ENTER - sami musimy zadbać o przejście do nowego wiersza i klawisz ESC - nie chcemy aby program wstawiał „dziwny” znaczek na końcu.
Zapis do pliku: liczby i kolumny
Pisanie liczb do pliku wygląda tak samo, jak pisaliśmy je na ekranie w konsoli.
#include <stdlib.h>
...
ofstream Pliczby("liczby.txt");
int liczba;
for (int i=0; i<10; i++) {
liczba=rand() % 6 + 1;
Pliczby << liczba << endl;
cout << liczba << endl;
}
Pliczby.close();
W pliku liczby.txt znajdują się losowe liczby
6
6
5
5
6
5
1
1
5
3
Zapis w kolumnach - tabliczka mnożenia
ofstream plik("mnoz.txt");
int mnoz;
for (int i=1; i<=10; i++) {
for (int j=1; j<=10; j++) {
mnoz=i*j;
plik.width(4);
cout.width(4);
plik << mnoz;
cout << mnoz;
}
plik << endl;
cout << endl;
}
plik.close();
W pliku mnoz.txt znajdują się wyniki mnożenia, w takim samym układzie, jak na ekranie konsoli

Jeżeli znamy dokładnie ilość danych do odczytania, możemy np. korzystać z pętli FOR.
W wielu przypadkach jednak nie znamy długości pliku wówczas posługujemy się funkcją
eof() stosowaną w pętli while, co można przeczytać: „dopóki nie osiągnęliśmy końca pliku …”
ifstream PLIK("plik.txt");
while (!PLIK.eof()){
...
}
PLIK.close();
Odczyt z pliku znak po znaku
Podczas czytania danych z plików pojawiają się problemy podobne do tych podczas zapisywania znaków – pomijane są spacja i enter (zarówno dla typu string i char).
ifstream ODCZYT("dane.txt");
char z;
while (!ODCZYT.eof()){
ODCZYT >> z;
cout << z;
}
ODCZYT.close();
Przedstawiony fragment programu czyta pojedyncze znaki z pliku ”dane.txt” i wyświetla na ekranie,
bez spacji i przejść do nowego wiersza.
Jeżeli użyjemy funkcji GET ominiemy problemy z tzw. "białymi znakami".
ODCZYT.get(z);
ifstream ODCZYT("dane.txt");
char z;
while (!ODCZYT.eof()){
ODCZYT.get(z);
cout << z;
}
ODCZYT.close();
Odczyt z pliku: czytanie wierszami
Instrukcja getline odczytuje całe wiersze, łączenie ze spacjami.
Jeśli odczytujemy w ten sposób liczby i teksty, konieczne będzie wyodrębnianie z tekstu fragmentów i konwersja.
ifstream Wodczyt("dane.txt");
string wiersz;
while (!Wodczyt.eof()){
getline(Wodczyt,wiersz);
cout << wiersz << endl;
}
Wodczyt.close();
Odczyt z pliku: liczby na ekran i liczby do tablicy
Liczby czytamy dokładnie tak samo jak teksty.
W pliku dane mogą być rozdzielone spacjami lub każda może wystąpić w nowym wierszu.
Spacja i nowy wiersz zostaną potraktowane identycznie - odczytane jako nowa watrość.
ifstream ODCZYT("liczby.txt");
int li;
while (!ODCZYT.eof()){
ODCZYT >> li;
cout << li;
}
ODCZYT.close();
int tabl[20];
int ile=0;
ifstream oplik("liczby.txt");
if(oplik.is_open()) {
while(!oplik.eof()) {
oplik >> tabl[ile];
ile++;
}
}
else cout << "Brak pliku";
oplik.close();
for (int i=0; i < ile; i++)
cout << tabl[i];
Warto zwrócić uwagę na sprawdzenie poprawności otwarcia pliku.
Jeśli takiego pliku nie ma - funkcja is_open(), to możemy pominąć wykonywanie programu.
Problemy mogą pojawić się, jeśli plik na końcu zawiera pusty wiersz - do tablicy zostanie wczytany jeden więcej element - zero!
Do istniejącego pliku możemy dopisywać na końcu pliku nowe dane:
fstream dopis;
dopis.open("dane.txt", ios::app);
dopis << "Tekst dopisany na końcu";
dopis.close();
PALINDROMY
Palindromem nazywamy słowo, które czytane od lewej i od prawej strony
jest takie samo.
Palindromami są słowa: JABFDFBAJ, HAJAHAJAH, ABBA.
Słowo JANA nie jest palindromem.
zadanie:
Wygeneruj plik tekstowy palindrom.txt, który zawierał będzie 1000 słów o długościach od 2 do 25 znaków, każde w nowym wierszu, składających się z wielkich liter A, B, C, D, E, F, G, H, I, J.
Aby plik zawierał jakieś „ciekawe” palindromy zmodyfikuj program w następujący sposób:
- co 30 generowany wyraz sprawdź, czy jest krótszy niż 13 znaków
- jeśli tak, to doklej do niego ten sam odwrócony wyraz, np. DCEAB i doklejamy BAECD
ofstream PALzapisz("palindrom.txt");
for (int i=1; i <= 1000; i++){
int ile=rand() % 24 + 2; //ile znaków w wyrazie
string pal="";
//sklejamy wyrazy z ile znaków
for (int j=1; j <= ile; j++){
char zna=char(rand() % 10 +65); //losowe znaki o kodach 65-74
pal=pal+zna;
}
//co 30 wyraz i jeśli krótszy niż 13 znaków
//robimy z wyrazu palindrom
int dl=pal.length();
if (i%30 == 0 && dl <= 12){
for (int k=0; k < dl; k++)
pal=pal+pal[dl-k-1];
}
//zapisujemy wyrazy w pliku
PALzapisz << pal << endl;
cout << pal << endl;
}
PALzapisz.close();
Plik tekstowy palindrom.txt zawiera wygenerowane słowa (maksymalnie 1000).
Odczytaj je i sprawdź, które są palindromami.
Wynik wyświetl na ekranie oraz zapisz w pliku tekstowym palindrom-wynik.txt.
// odczytywanie pliku i sprawdzanie palindromów
ifstream PALodczyt("palindrom.txt");
string wyraz;
while (!PALodczyt.eof()){
PALodczyt >> wyraz;
//całkowita połowa długości
int dl=wyraz.length();
int dl2=dl/2;
bool palindrom=true;
//sprawdzamy od początku do połowy
//i porównujemy ze znakami od końca
for (int i=0; i < dl2; i++)
//jeśli którakilwiek litera się nie zgadza
//to nie jest palindrom
if (wyraz[i] != wyraz[dl-1-i])
palindrom=false;
if (palindrom)
cout << wyraz << endl;
}
PALodczyt.close();
Przykładowe słowa będące palindromami z wygenerowanego pliku:
FBJGGJBF
EE
CBBC
ICI
ECGECFFCEGCE
EIFBDHHDBFIE
FF
HGHAEFEIGIBBIGIEFEAHGH
HASŁA
Wygeneruj plik tekstowy hasla.txt, zawierający 200 słów, składających się z małych liter alfabetu angielskiego,
każde w osobnym wierszu, których długość wynosi od 3 do 10 znaków.
//generator pliku z hasłami
//3-10 małych liter (ASCII 97-122)
ofstream HASzapis("hasla.txt");
string napis;
for (int i=1;i<=200;i++){
napis="";
int ile=rand() % 8 +3; //ile znaków od 3 do 10
for (int j=1;j<=ile;j++)
//losujemy małe litery kodów ASCII
napis+=rand() % (122-97+1)+97;
HASzapis << napis << endl;
}
HASzapis.close();
Odpowiedz na poniższe pytania:
//parzysta-nieparzysta
int PA=0; //parzyste
int NP=0; //nieparzyste
ifstream odczytA("hasla.txt");
string napisA;
while (!odczytA.eof()){
odczytA >> napisA;
//sprawdzamy długości napisów za pomocą modulo
if (napisA.length() % 2 ==0)
PA++;
else
NP++;
}
odczytA.close();
cout << " parzyste: " << PA << endl;
cout << "nieparzyste: " << NP << endl;
//palindromy
cout << "PALINDROMY" << endl;
ifstream odczytB("hasla.txt");
string napisB;
while (!odczytB.eof()){
odczytB >> napisB;
int dl=napisB.length();
int dl2=dl/2;
//na początku każdy wyraz jest palindromem
bool palindrom=true;
for (int i=0; i < dl-2; i++)
//porównujemy znak z początku ze znakiem od końca
if (napisB[i]!=napisB[dl-1-i])
//jeśli jakikolwiek znak różny to
//nie jest palindromem
palindrom=false;
// jest palindromem, bo porównało
//i wszystkie znaki były zgodne
if (palindrom)
cout << napisB << endl;
}
odczytB.close();
//dwa identyczne znaki
cout << "ASCII 220"<< endl;
ifstream odczytC("hasla.txt");
string napisC;
while (!odczytC.eof()){
odczytC >> napisC;
int dl=napisC.length();
//sprawdzamy do przedostatniego znaku
//aby nie zawiesił się na ostatnim [i+1]
for (int i=0;i < dl-2;i++)
//dwa znaki obok siebie takie same
if (napisC[i] == napisC[i+1]) {
cout << napisC << endl;
break;
}
}
odczytC.close();
CIĄGI
Wygeneruj plik tekstowy ciagi.txt, zawierający 1000 słów składających się z trzech liter A, B, C, każde słowo w osobnym wierszu, litery mogą się powtarzać.
ofstream CIAGzapis("ciagi.txt");
string napis;
for (int i=1; i<=1000; i++){
napis="";
//losowe znali ABC
napis=rand() % 3+65;
napis+=rand() % 3+65;
napis+=rand() % 3+65;
CIAGzapis << napis << endl;
}
CIAGzapis.close();
Odpowiedz na poniższe pytania:
ifstream CIAGodczyt("ciagi.txt");
int licznik = 0;
string napis;
while (!CIAGodczyt.eof()) {
CIAGodczyt >> napis;
//sprawdzamy zerowy z pierwszym i zerowy z drugim
//nie potrzeba sprawdzać pierwszego z drugim
if (napis[0]==napis[1] && napis[0]==napis[2])
licznik++;
}
CIAGodczyt.close();
ifstream CIAGodczyt("ciagi.txt");
int licznik = 0;
string napis;
while (!CIAGodczyt.eof()) {
CIAGodczyt >> napis;
//wystarczy sprawdzić zerowy z drugim
if (napis[0]==napis[2])
licznik++;
}
CIAGodczyt.close();
CYFRY
Wygeneruj plik tekstowy cyfry.txt, zawierający 1000 liczb naturalnych, mniejszych niż 10000, każda w osobnym wierszu.
ofstream CYFRYzapis("cyfry.txt");
for (int i=1; i <= 1000; i++){
int c=rand() % 10000 + 1;
CYFRYzapis << c;
//nowy wiersz bez ostatniego
if (i < 1000) CYFRYzapis << endl;
}
CYFRYzapis.close();
Odpowiedz na poniższe pytania:
ifstream CYFRYodczytA("cyfry.txt");
int liczba, suma=0, ilosc=0;
while (!CYFRYodczytA.eof()){
CYFRYodczytA >> liczba;
ilosc++;
suma += liczba;
}
CYFRYodczytA.close();
//aby wynik był rzecywisty, wykonujemy daiałanie: (ilosc*1.0)
cout << "Średnia=" << suma/(ilosc*1.0) << endl;
ifstream CYFRYodczytB("cyfry.txt");
int liczbaB;
int CP=0;//licznik parzystych
int CN=0;//i nieparzystych
while (!CYFRYodczytB.eof()){
CYFRYodczytB >> liczbaB;
if (liczbaB % 2 == 0) CP++;
else CN++;
}
CYFRYodczytB.close();
cout << "Parzyste=" << CP << endl;
cout << "nieParzyste=" << CN << endl;
DWÓJKOWE
Wygeneruj plik tekstowy napisy.txt, zawierający 1000 napisów od 20 do 100 znaków.
Napisy to liczby binarne składające się ze znaków ‘0’ lub ‘1’.
ofstream NDzapis("liczby.txt");
int ile;
int znak;
string napis;
for (int j=1;j<=1000;j++){
ile=rand() %80 + 20; //20-100
if(rand()%150 == 10) napis = "00000000000";
else if(rand()%200 == 10) napis = "1111111111111111111111111111";
else if(rand()%200 == 10) napis = "00000000000000000000000000000000000000000010000000000000100000000000000000000100";
else {
napis="";
for (int i=1;i<=ile;i++){
znak=rand() % 2;//0 lub 1 losowo
//znak ASCII '0' lub '1'
napis=napis+char(znak+48);
}
}
NDzapis << napis << endl;
}
NDzapis.close();
W pliku napisy.txt znajduje się 1000 napisów o długościach od 2 do 16 znaków, każdy napis w osobnym wierszu. W każdym napisie mogą wystąpić jedynie dwa znaki: „0” lub „1”. Odpowiedz na poniższe pytania: ekran i plik
int zadanie1() {
int parzyste=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
while(!plik.eof()) {
plik >> liczba;
if(liczba.size() % 2 == 0) parzyste++;
}
plik.close();
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
return parzyste;
}
int zadanie2() {
int zera=0, jedynki=0, ilosc=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
while(!plik.eof()) {
zera=0;
jedynki=0;
plik >> liczba;
for(int i=0; i<liczba.size(); i++) {
if(liczba[i] == '0') zera++;
if(liczba[i] == '1') jedynki++;
}
if(zera == jedynki) ilosc++;
}
plik.close();
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
return ilosc;
}
void zadanie3() {
int zera=0, jedynki=0, suma=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
while(!plik.eof()) {
suma = 0;
plik >> liczba;
for(int i=0; i<liczba.size(); i++) {
suma += int(liczba[i]) - 48;
}
if(suma == 0) zera++;
if(suma == liczba.size()) jedynki++;
}
plik.close();
cout << "W pliku liczby.txt:\n" << zera << " - same zera\n" << jedynki << " - same jedynki.";
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
}
void zadanie4() {
int tablica[80];
for (int i=0; i < 80; i++) tablica[i]=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
while(!plik.eof()) {
plik >> liczba;
tablica[liczba.size()-20]++;
}
plik.close();
cout << "W pliku liczby.txt:\n";
for(int i=0; i < 80; i++) {
cout << i+20 << " znakow: " << tablica[i] << ", ";
}
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
}
int jedynki(string liczba) {
int ilosc=0;
for(int i=0; i<liczba.length(); i++) {
if(liczba[i] == '1') ilosc++;
}
return ilosc;
}
void zadanie5() {
int ile=0, ile1, max1=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
plik >> liczba;
ile = 1;
max1 = ile1 = jedynki(liczba);
while(!plik.eof()) {
plik >> liczba;
ile0 = jedynki(liczba);
if(ile1 == max1) ile++;
else if(ile1 > max1) {
max1 = ile1;
ile = 1;
}
}
plik.close();
cout << "W pliku liczby.txt maksymalna ilosc jedynek wynosi: " << max1 << " - takich liczb jest: " << ile;
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
}
int zera(string liczba) {
int ilosc=0;
for(int i=0; i<liczba.length(); i++) {
if(liczba[i] == '0') ilosc++;
}
return ilosc;
}
void zadanie6() {
int ile=0, ile0, max0=0;
string liczba;
ifstream plik("liczby.txt");
if(plik.is_open()) {
plik >> liczba;
ile = 1;
max0 = ile0 = zera(liczba);
while(!plik.eof()) {
plik >> liczba;
ile0 = zera(liczba);
if(ile0 == max0) ile++;
else if(ile0 > max0) {
max0 = ile0;
ile = 1;
}
}
plik.close();
cout << "W pliku liczby.txt maksymalna ilosc zer wynosi: " << max0 << " - takich liczb jest: " << ile;
} else {
cout << "Problem z otwarciem pliku ilczby.txt ";
}
}