Edward Preweda KIOT WGGiIŚ AGH
- 1 -
Szkoła programowania w Pascalu
7. Przetwarzanie plików (operacje wejścia-wyjścia)
7.1. Wprowadzenie
7.2. Funkcje i procedury obsługi dowolnych plików
7.3. Funkcje i procedury przetwarzania plików tekstowych
7.4. Funkcje i procedury działające wyłącznie na plikach nietekstowych
7.5. Przykłady
7.1. Wprowadzenie
Do wprowadzania/wyprowadzania danych z/do komputera służą urządzenia zewnętrzne, takie jak klawiatura,
ekran monitora, dyski, drukarki. Dane te nazywane są fizycznymi zbiorami danych. Do ich obsługi stosuje się pliki.
Plik są logicznym odwzorowaniem fizycznych zbiorów. W języku potocznym pojęć tych często nie rozróżnia się,
określając je, podobnie jak w języku angielskim, jednym terminem plik (file). W języku Turbo Pascal istnieją trzy
rodzaje plików:
• tekstowe,
• zdefiniowane (elementowe),
• niezdefiniowane (amorficzne).
Pliki tekstowe zapisują informacje jako ciąg znaków (kodów ASCII) . Można w nich zapisywać wielkości
różnych typów oraz stosować formatowanie zapisu. Pliki te umożliwiają wyłącznie dostęp sekwencyjny do
zawartych w nich danych. Oznacza to, że aby odczytać wartość określonego elementu, należy wcześniej
przeczytać to co jest przed nim.
Pliki zdefiniowane wykorzystują w zapisie reprezentację maszynową. W przypadku pliku zdefiniowanego
możliwy jest zapis i odczyt wielkości wyłącznie jednego typu składowego. Pliki te są plikami o dostępie
swobodnym, co oznacza, że w każdym momencie możliwy jest dostęp do dowolnego elementu pliku.
Pliki niezdefiniowane stosuje się w celu dostępu do fizycznych zbiorów danych zgodnie z ich wewnętrzym
formatem lub w przypadku, gdy typ pliku nie jest istotny (np. podczas kasowania pliku z dysku).
W przetwarzaniu plików wyróżnia się następujące etapy:
• kojarzenie pliku z fizycznym zbiorem danych
• otwarcie pliku
• wykonanie operacji plikowych (przetwarzanie pliku)
• zamknięcie pliku
Dostęp do pliku uzyskuje się za pomocą zmiennej plikowej odpowiedniego typu (zmiennej typu plikowe-
go). Zanim zmienną plikową wykorzysta się do przetwarzania pliku, należy, za pomocą odpowiedniej procedury,
skojarzyć ją z fizycznym zbiorem danych. Procedurą wiążącą nazwę urządzenia (klawiatura, ekran, dysk, drukarka)
z którego będzie wyprowadzany/wprowadzany fizyczny zbiór danych ze zmienną typu plikowego jest procedura
Assign. Po skojarzeniu zmiennej plikowej z fizycznym zbiorem danych można zmienną plikową (plik) otworzyć,
czyli przygotować ją do wprowadzania/wyprowadzania poszczególnych elementów pliku. Do otwarcia pliku, w
zależności od kierunku przesyłania elementów pliku oraz typu pliku, służą procedury Reset, Rewrite i Append
(tylko pliki tekstowe). Dopiero po otwarciu pliku może być on przetwarzany przez program. Po zakończeniu
przetwarzania, plik (zmienna plikowa) powinien być zamknięty za pomocą procedury Close.
W języku Turbo Pascal istnieją dwie predefiniowane zmienne plikowe typu tekstowego które otwierane są
automatycznie po rozpoczęciu wykonywania programu. Są to zmienne przypisane do standardowych urządzeń
wejścia (zmienna Input) - wyjścia (zmienna Output). W przypadku korzystania z tych zmiennych plikowych,
stosowanie procedury Assign, procedur otwierających i zamykających odpowiednie pliki jest zbyteczne.
Edward Preweda KIOT WGGiIŚ AGH
- 2 -
Szkoła programowania w Pascalu
Domyślnym urządzeniem wejścia jest najczęściej klawiatura, zaś wyjścia - ekran monitora Do odczytywania
danych stosuje się standardową procedurę Read (pliki tekstowe i zdefiniowane) lub Readln (tylko pliki tekstowe).
Parametrami tych procedur są identyfikatory zmiennych których wartości wprowadzamy. Wprowadzanie nowych
elementów do plików umożliwiają procedury Write (pliki tekstowe i zdefiniowane) i Writeln (wyłącznie pliki
tekstowe). Podobnie jak w przypadku procedur Read i Readln, parametrami są identyfikatory wyprowadzanych
elementów, lub stałe łańcuchowe.
7.2. Funkcje i procedury obsługi dowolnych plików
Poniżej zostaną przedstawione podstawowe funkcje i procedury działające na dowolnych plikach:
•
Assign
(zmienna_plikowa, nazwa_zbioru_typu_łańcuchowego)
Procedura ta umożliwia skojarzenie zmiennej plikowej z fizycznym zbiorem danych o podanej ścieżce (max 79
znaków) . W momencie wywołania powyższe procedury plik nie może być otwarty. Jeżeli jako drugi parametr
podamy pusty łańcuch, zmienna plikowa zostanie skojarzona ze standardowymi urządzeniami wejścia i wyjścia
- klawiaturą i monitorem.
•
Rewrite
(zmienna_plikowa)
lub
•
Rewrite
(zmienna_plikowa,rozmiar)
Procedura powoduje utworzenie nowego fizycznego zbioru danych o nazwie skojarzonej wcześniej z podaną
zmienną plikową (otwarcie do zapisu). W przypadku gdy zbiór o takiej nazwie już istnieje, zostanie on
usunięty a w jego miejscu zostanie utworzony nowy zbiór pusty. Zbiór po otwarciu ustawiany jest w pozycji
początkowej. Druga postać wywołania procedury może być stosowana tylko w odniesieniu do plików
niezdefiniowanych. W przypadku plików niezdefiniowanych, za pomocą parametru rozmiar (typu Word)
można określić rozmiar tworzonych zapisów zewnętrznego zbioru danych. Pominięcie tego argumentu
(parametru) oznacza przyjęcie rozmiaru domyślnego równego 128 bajtów.
•
Reset
(zmienna_plikowa)
lub
•
Reset
(zmienna_plikowa, rozmiar)
Procedura ta służy do otwarcia pliku skojarzonego z już istniejącym zbiorem. (Otwarcie do odczytu). Zbiór po
otwarciu ustawiany jest w pozycji początkowej. Druga postać wywołania procedury może być stosowana tylko
w odniesieniu do plików niezdefiniowanych.
•
Close
(zmienna_plikowa);
Procedura zamyka fizyczny zbiór danych skojarzony ze zmienną plikową.
•
Eof
(zmienna_plikowa);
lub
•
Eof
(gdy wywołanie dotyczy standardowego pliku wejściowego Input)
Funkcja ta przyjmuje wartość logiczną TRUE gdy plik znajduje się w pozycji przed ostatnim znakiem zbioru
(znakiem Ctrl-Z) lub gdy zbiór nie zawiera żadnych elementów. W przeciwnym wypadku ma wartość FALSE.
•
Erase
(zmienna_plikowa)
Procedura usuwa zbiór skojarzony ze zmienną plikową. Plik ten nie może być otwarty.
Edward Preweda KIOT WGGiIŚ AGH
- 3 -
Szkoła programowania w Pascalu
•
Rename
(zmienna_plikowa, łańcuch)
Procedura umożliwia zmianę nazwy zbioru dyskowego. Zbiorowi skojarzonemu ze zmienną plikową
nadawana jest nazwa określona przez łańcuch. Plik nie może być otwarty.
•
ChDir
(ścieżka)
Procedura umożliwiają zmianę bieżącego katalogu na katalog i/lub napęd określony przez ścieżkę, np.:
ChDir('C:');
ChDir(A:\PROGRAMY');
•
GetDir
(liczba, łańcuch)
Po wywołaniu tej procedury uzyskamy informacje o bieżącym katalogu w określonym napędzie.
liczba = 0 - napędem jest napęd bieżący
liczba = 1 - napęd A
liczba = 2 - napęd B, itd.
Nazwa bieżącego katalogu (dla napędu określonego liczbą) podstawiana jest pod zmienną łańcuch typu string.
Dla przykładu, po wywołaniu procedury
GetDir(3,katalog);
pod zmienną katalog podstawiana jest nazwa bieżącego katalogu na dysku C:
•
MkDir
(łańcuch)
Procedura powoduje utworzenie nowego podkatalogu określonego przez łańcuch (ścieżkę nowego
podkatalogu), np.;
MkDir('A:\PASCAL\DANE');
{ utworzenie na dyskietce w napędzie A: w katalogu PASCAL podkatalogu DANE }
•
RmDir
(ścieżka)
Procedura usuwa pusty podkatalog określony przez ścieżkę.
•
IOResult
Jest to bezparametrowa funkcja typu Word podająca, w przypadku wyłączonej kontroli systemowej
warunków wejścia wyjścia, status ostatnio wykonanej operacji wejścia-wyjścia. Jeżeli podczas wykonywania
operacji wejścia wyjścia nie wystąpi żaden błąd to funkcja przyjmuje wartość 0, w przeciwnym wypadku
zwraca kod błędu.
7.3. Funkcje i procedury przetwarzania plików tekstowych
Pliki tekstowe zapisują informacje jako ciąg znaków, kodów ASCII. Dzięki temu można w nich zapisywać
wielkości praktycznie dowolnych typów. Ograniczeniem dla plików tekstowych jest sekwencyjny dostęp do
danych. Oznacza to, że aby dostać się do określonego elementu należy przeczytać wszystko co jest przed nim.
•
Append
(zmienna_plikowa)
Procedura otwiera plik skojarzony ze zmienną plikową i ustawia zbiór na pozycji końcowej (otwarcie do
dopisywania).
•
Eoln
(zmienna_plikowa);
lub
Edward Preweda KIOT WGGiIŚ AGH
- 4 -
Szkoła programowania w Pascalu
•
Eoln
(gdy wywołanie dotyczy standardowego pliku wejściowego Input)
Funkcja, której wartość logiczna jest TRUE gdy plik znajduje się w pozycji znaku końca wiersza (tj. znaku
CR) lub gdy wartością funkcji Eof dla tej samej zmiennej plikowej jest TRUE. W przeciwnym wypadku
wartością funkcji jest FALSE.
•
Flush
(zmienna_plikowa)
Procedura ta powoduje dla pliku tekstowego otwartego wywołaniem procedury Rewrite lub Append
wyzerowanie bufora wejścia. Przez ten bufor wprowadzane są zapisy do zewnętrznego zbioru danych.
•
Read
(zmienna_plikowa,lista_zmiennych)
lub
•
Readln
(zmienna_plikowa,lista_zmiennych)
Procedury te służą do czytania elementów z plików. Pierwszym parametrem tych procedur jest odpowiednia
zmienna plikowa, po której następują oddzielone przecinkami nazwy czytanych zmiennych. Po każdorazowym
odczytaniu wartości pojedynczej zmiennej następuje automatyczne przesunięcie wskaźnika do początku
następnego elementu. W przypadku procedury Readln wskaźnik przesuwa się do początku następnego wiersza.
•
Write
(zmienna_plikowa,lista_argumentów)
lub
•
Writeln
(zmienna_plikowa,lista_argumentów)
Procedury powyższe umożliwają wprowadzanie elementów do plików. Podobnie jak w przypadku czytania,
pierwszym parametrem tych procedur jest identyfikator odpowiedniej zmiennej plikowej, odpowiadającej
otwartemu uprzednio plikowi. Wywołanie procedur powoduje zapisanie do fizycznego zbioru odpowiednich
wielkości. Po każdorazowym zapisaniu wartości pojedynczej zmiennej następuje automatyczne przesunięcie
wskaźnika do początku następnego elementu. W przypadku procedury Writeln wskaźnik przesuwa się do
początku następnego wiersza.
•
SeekEof
(zmienna_plikowa);
lub
•
SeekEof
Funkcja ta daje takie same wyniki jak funkcja Eof, z tym że ignoruje najbliższe spacje, znaki tabulacji oraz
znaki CR i LF.
•
SeekEoln
(zmienna_plikowa);
lub
•
SeekEof
Funkcja ta daje takie same wyniki jak funkcja Eoln, z tym że ignoruje najbliższe spacje, znaki tabulacji oraz
znaki CR i LF.
•
SetTextBuf
(zmienna_plikowa, bufor)
lub
•
SetTextBuf
(zmienna_plikowa, bufor, rozmiar)
Procedura ta przypisuje bufor wejścia wyjścia do danego pliku tekstowego. Bufor jest w tym przypadku
dowolna zmienną. Zwiększając rozmiar bufora można uzyskać np. szybszy odczyt danych ze zbioru.
Edward Preweda KIOT WGGiIŚ AGH
- 5 -
Szkoła programowania w Pascalu
7.4. Funkcje i procedury działające wyłącznie na plikach nietekstowych
•
FileSize
(zmienna_plikowa)
Wartością funkcji jest rozmiar (LongInt) wyspecyfikowanego pliku
•
FilePos
(zmienna_plikowa)
Wartością funkcji jest liczba całkowita typu LongInt, podająca aktualną pozycje pliku skojarzonego ze zmienną
plikową .Wartość funkcji jest równa 0 jeżeli plik znajduje się w pozycji początkowej, natomiast gdy plik
znajduje się w pozycji końcowej wartość ta jest równa wartości funkcji FileSize.
•
Seek
(zmienna_plikowa, pozycja)
Procedura ta umożliwia przesunięcie aktualnego położenia pliku do elementu o podanej liczbie porządkowej,
określonego parametrem pozycja typu LongInt.
•
Truncate
(zmienna_plikowa)
Procedura usuwa z pliku skojarzonego ze zmienną plikową wszystkie elementy począwszy od aktualnej
pozycji do końca pliku.
Uwaga, zapisywanie i odczytywanie plików zdefiniowanych odbywa się za pomocą standardowych procedur Read
oraz Write.
7.5. Przykłady
Przykład 1
Utwórz plik tekstowy skojarzony ze zbiorem dane.txt i zapisz do niego wartości zmiennych x, y, z.
var
dane : Text
{ ... }
Assign (dane, 'dane.txt');
{ skojarzenie zmiennej plikowej dane ze zbiorem „dane.txt” }
Rewrite (dane);
{ otwarcie pliku do zapisu }
Write (dane, x, y, z); { zapisanie wartości zmiennych x, y, z }
Close (dane);
{ zamknięcie pliku }
{ ... }
Przykład 2
Do istniejącego pliku tekstowego „dane.txt” dopisz wartości zmiennych x, y, z
var
dane:Text
{ ... }
Assign (dane, 'dane.txt');
{ skojarzenie zmiennej plikowej dane ze zbiorem „dane.txt” }
Append (dane);
{ otwarcie pliku do „dopisywania” }
Write (dane, x, y, z); { zapisanie wartości zmiennych x, y, z }
Close (dane);
{ zamknięcie pliku }
{ ... }
Przykład 3
Do pliku zdefiniowanego (plik : file of Byte) dane.dat, zapisz 10 przypadkowych liczb całkowitych.
var
plik : file of Byte;
{ ... }
Edward Preweda KIOT WGGiIŚ AGH
- 6 -
Szkoła programowania w Pascalu
Assign (plik, 'dane.dat');
Rewrite(plik);
Randomize;
for
i:=1 to 10 do
begin
x:=Random(255);
Write(plik,x);
end
;
Close(plik);
{ ... }
Przykład 4
Z pliku zdefiniowanego (plik : file of Byte) dane.dat, odczytaj n-ty element.
var
plik:file of Byte;
{ ... }
Write('Podaj numer kolejny elementu :');
Readln(numer);
Assign (plik, 'dane.dat');
Reset(plik);
if
numer <= FileSize(plik) then { sprawdzamy, czy istnieje element }
begin
Seek (plik, numer-1); { numer-1, ponieważ pierwszy element ma numer 0 }
Read (plik, liczba);
end
else Write('Brak elementu ',numer);
Close (plik);
{ ... }
Przykład 5
Na końcu pliku zdefiniowanego „dane.dat” dopisz jeden element.
var plik:file of Byte;
x : Byte;
{ ... }
Assign (plik, 'dane.dat');
Reset (plik);
Seek (plik, FileSize(plik)); { porównaj z procedurą Append }
Write (plik, x);
Close (plik);
{ ... }
Przykład 6
Odczytaj z pliku zdefiniowanego „dane.dat” wszystkie elementy i wypisz je na ekranie.
var
plik : file of Byte;
x:Byte;
{ ... }
Assign (plik, 'dane.dat' );
Reset (plik);
while
not Eof(plik) do { dopóki nie ma końca zbioru }
begin
Read (plik, x);
Writeln (x)
end;
Close (plik);
{ ... }
Edward Preweda KIOT WGGiIŚ AGH
- 7 -
Szkoła programowania w Pascalu
Przykład 7
Przykład programu korzystającego z plików tekstowych.
program
pliki_tekstowe_macierze;
const
max_W = 10;
max_K = 10;
var
f
:
Text;
opis :
String;
N_wierszy,N_kolumn :
Word;
macierz
: Array [1..max_W,1..max_K] of Real;
i,j :
Integer;
procedure
czytaj;
begin
Assign
(f,'dane.txt');
{ Skojarzenie zmiennej plikowej f z fizycznym zbiorem danych dane.txt }
Reset
(f);
{ Otwarcie zmiennej plikowej (pliku dane.txt) do odczytu }
Readln(f,opis);
{ Wczytanie 1-ego wiersza pliku dane.txt i przejście do początku następnego wiersza }
Read(f,N_wierszy,N_kolumn);
{ Wczytanie liczby wierszy i liczby kolumn macierzy }
Readln(f);
{ Przejście do początku następnego wiersza pliku }
for i:=1 to N_wierszy do
begin
for j:=1 to N_kolumn do Read(f,macierz[i,j]);
{ Wczytanie elementów jednego wiersza macierzy }
Readln(f);
{ Przejście do początku wiersza następnego }
end
;
Close
(f);
{ Zamknięcie zmiennej plikowej f (pliku dane.txt) }
end
; { procedury czytaj }
procedure
wypisz_na_ekran;
begin
for
i:=1 to N_wierszy do
begin
for
j:=1 to N_kolumn do Write(macierz[i,j]:6:2);
{ Wypisanie jednego wiersza macierzy na ekranie monitora}
Writeln;
{ Przejście do początku wiersza następnego }
end
;
end
; { wypisz_na_ekran}
procedure
zapisz_do_pliku;
begin
Assign(f,'wyniki.txt');
{ Skojarzenie zmiennej plikowej f z fizycznym zbiorem danych wyniki.txt }
Rewrite(f);
{ Otwarcie zmiennej plikowej f (pliku wyniki.txt) do zapisu }
Writeln(f,opis+' pomnozona przez 2');
Edward Preweda KIOT WGGiIŚ AGH
- 8 -
Szkoła programowania w Pascalu
{ Zapis 1-ego wiersza w pliku wyniki.txt i przejście do początku następ. wiersza }
Write(f,N_wierszy,' ',N_kolumn);
{ Zapisanie liczby wierszy i liczby kolumn macierzy }
Writeln(f);
{ Przejście do początku następnego wiersza }
for i:=1 to N_wierszy do
begin
for j:=1 to N_kolumn do Write(f,2*macierz[i,j]:10:2);
{ Zapisanie jednego wiersza macierzy }
Writeln(f);
{ Przejście do wiersza następnego }
end
;
Close(f);
{ Zamknięcie zmiennej plikowej f (pliku wyniki.txt) }
end
; {wypisz_do_pliku}
procedure
dopisz_do_pliku;
begin
Assign(f,'wyniki.txt');
{ Skojarzenie zmiennej plikowej f z fizycznym zbiorem danych wyniki.txt }
Append(f);
{ Otwarcie zmiennej plikowej f (pliku wyniki.txt) do dopisywania }
Writeln(f,opis);
{ Dopisanie wiersza do pliku wyniki.txt i przejście do początku następnego wiersza }
Write(f,N_wierszy,' ',N_kolumn);
{ Zapisanie liczby wierszy i liczby kolumn macierzy }
Writeln(f);
{ Przejście do początku następnego wiersza }
for i:=1 to N_wierszy do
begin
for j:=1 to N_kolumn do Write(f,macierz[i,j]:10:2);
{ Zapisanie jednego wiersza macierzy }
Writeln(f);
{ Przejście do wiersza następnego }
end
;
Close(f);
{ Zamknięcie zmiennej plikowej f (pliku wyniki.txt) }
end
; { dopisz_do_pliku }
begin
{ programu }
czytaj;
{ wywołanie procedury czytaj }
wypisz_na_ekran;
{ wywołanie procedury wypisz_na_ekran }
zapisz_do_pliku;
{ wywołanie procedury zapisz_do_plikuj }
dopisz_do_pliku;
{ wywołanie procedury dopisz_do_pliku }
end
. { programu }
Edward Preweda KIOT WGGiIŚ AGH
- 9 -
Szkoła programowania w Pascalu
Zawartość pliku dane.txt (plik ten znajduje się w bieżącym katalogu) :
Macierz A
2 3
1.34 1.56 -0.45
0.34 -3.45 1.22
Zawartość pliku wyniki.txt po wywołaniu procedury zapisz_do_pliku
Macierz A pomnozona przez 2
2 3
2.68 3.12 -0.90
0.68 -6.90 2.44
Zawartość pliku wyniki.txt po wywołaniu procedury dopisz_do_pliku
Macierz A pomnozona przez 2
2 3
2.68 3.12 -0.90
0.68 -6.90 2.44
Macierz A
2 3
1.34 1.56 -0.45
0.34 -3.45 1.22
Przykład 8
Przykład programu przetwarzającego pliki zdefiniowane.
program
pliki_zdefiniowane;
uses Crt;
type punkty = record
Oznaczenie : String[10];
X,Y,Z : Real;
end;
var wsp :
punkty;
f
: file of punkty;
N_pkt
: Integer;
opis
: String;
i,j
: Integer;
procedure
czekaj;
var znak:Char;
begin
Writeln;
Write('Nacisnij dowolny klawisz ...');
znak:=Readkey; Writeln;
end
;
procedure
wprowadz_zapisz;
begin
ClrScr;
Write(' Podaj liczbe wprowadzanych punktow : ');
Readln(N_pkt);
Writeln('---------------------------------------------------');
Assign(f,'dane.wsp');
Edward Preweda KIOT WGGiIŚ AGH
- 10 -
Szkoła programowania w Pascalu
Rewrite(f);
for i:=1 to N_pkt do
begin
Writeln('Numer kolejny punktu : ',i:3);
Write('Podaj oznaczenie punktu (maksymalnie 10 znakow) : ');
Readln(wsp.oznaczenie);
Write('Wspolrzedna X = '); Readln(wsp.X);
Write('Wspolrzedna Y = '); Readln(wsp.Y);
Write('Wspolrzedna Z = '); Readln(wsp.Z);
Writeln('---------------------------------------------------');
Write(f,wsp);
end
;
Close(f);
end
;
procedure
czytaj_wypisz;
var k:Integer;
begin
ClrScr;
Assign(f,'dane.wsp');
Reset(f);
Writeln(' Wykaz wspolrzednych punktow');
Writeln;
Writeln(' Lp Oznaczenie X Y Z');
Writeln;
k:=0;
while not Eof(f) do
{ Eof - patrz Funkcje i procedury obsługi zbiorów }
begin
k:=k+1;
Read(f,wsp);
Write(k:5);
Write(wsp.oznaczenie:15);
Writeln(wsp.X:15:3,wsp.Y:12:3,wsp.Z:12:3);
end
;
Close(f);
czekaj;
end
;
procedure
czytaj_wypisz_jeden_punkt;
var Lp :
Integer;
Blad
: Word;
begin
ClrScr;
Write('Podaj nr kolejny punktu : '); Readln(Lp);
ClrScr;
Assign(f,'dane.wsp');
Reset(f);
Seek(f,Lp-1);
{Seek - standardowa procedura modułu system,
patrz: Funkcje i procedury obsługi zbiorów }
{$I-}
{ lokalna, przełącznikowa dyrektywa kompilatora, patrz: Dyrektywy kompilatora }
Read(f,wsp);
{$I+}
{ lokalna, przełącznikowa dyrektywa kompilatora, patrz: Dyrektywy kompilatora }
Blad:=IOResult;
{ IOResult - bezparametrowa funkcja modułu system,
Edward Preweda KIOT WGGiIŚ AGH
- 11 -
Szkoła programowania w Pascalu
patrz: Funkcje i procedury obsługi zbiorów }
if Blad<>0 then
begin
Writeln('Blad odczytu z dysku');
halt;
end
;
Writeln(' Punkt nr kolejny : ',Lp);
Writeln;
Writeln(' Oznaczenie X Y Z');
Writeln;
Write(wsp.oznaczenie:15);
Writeln(wsp.X:15:3,wsp.Y:12:3,wsp.Z:12:3);
Close(f);
czekaj;
end
;
begin
wprowadz_zapisz;
czytaj_wypisz;
czytaj_wypisz_jeden_punkt;
end
.