На занятии будет рассмотрена работа с текстовыми файлами в Паскале и разобраны конкретные решенные примеры задач
Работа с файлами в паскале
Виды файлов в зависимости от их описания и режимом работы
- текстовые (тип text) файлы со строками неопределенной длины;
- файлы с типом записей (двоичные или типизированные (file of) );
- файлы без типа для передачи данных блоками записей нетипизированные (file).
Описание файловых переменных:
var
f1: file of char; {типизированный файл}
f2: file of integer; {типизированный файл}
f3: file; {нетипизированный файл}
f: text; {текстовый файл} |
var
f1: file of char; {типизированный файл}
f2: file of integer; {типизированный файл}
f3: file; {нетипизированный файл}
f: text; {текстовый файл}
Для связи файла в коде программы и действительного файла на внешнем носителе используется процедура ASSIGN
:
assign(myfile,'c:\text.txt'); |
assign(myfile,'c:\text.txt');
где myfile
— имя переменной (объявленной ранее в области var
), ассоциированной с файлом
c:\text.txt
— путь к реальному файлу
Первый аргумент процедуры assign в паскаль — переменная, второй – путь к файлу на диске.
Для считывания из файла достаточно связать поток ввода с файлом:
Считывание строки
|
Считывание массива из N целых
|
begin
Assign(input,'24.txt');
var s := ReadString;
...
end. |
begin
Assign(input,'24.txt');
var s := ReadString;
...
end.
|
begin
Assign(input,'26.txt');
var N := ReadInteger;
var a := ReadArrInteger(N);
...
end. |
begin
Assign(input,'26.txt');
var N := ReadInteger;
var a := ReadArrInteger(N);
...
end.
|
Текстовые файлы в паскале: процедуры работы
Текстовый файл в Паскале — это совокупность строк произвольной длины, которые разделены между собой метками конца строки, а весь файл заканчивается меткой конца файла.
Важно: Если быть точными, то каждая строка текстового файла завершается специальной комбинацией, называемой «конец строки».
Комбинация «конец строки» состоит из двух символов:
перевод каретки (
ASCII-код #13
) и
перевод строки (
#10
). Завершается текстовый файл символом
конец файла (
#26
).
Возможные расширения файлов:
*.txt, *.log,
*.htm, *.html
Метод работы с текстовым файлом в Паскале предусматривает лишь последовательный доступ к каждой строке файла. Это означает, что начинать всегда возможно только с первой строки, затем проходя по каждой строке, дойти постепенно до необходимой. Т.е. можно сказать, что чтение (или запись) из файла (в файл) ведутся байт за байтом от начала к концу.
Предусмотрены два режима работы: режим для записи в файл информации и для чтения ее из файла. Одновременная запись и чтение запрещены.
Открытие файла (классический Pascal)
Допустим, мы в программе описали переменную для работы с текстовым файлом:
Рассмотрим дальнейшую последовательность работы с ним, и рассмотрим процедуры, необходимые для работы с текстовым файлом в Паскале:
процедура открытия существующего файла для чтения при последовательном доступе:
процедура открытия создаваемого файла для записи в него информации; если файл с таким именем уже существует, то информация в нем стирается:
процедура добавления в конец:
- При открытии курсор устанавливается в начало файла.
Чтение из файла (классический Pascal)
Read (f, список переменных);
ReadLn (f, список переменных); |
Read (f, список переменных);
ReadLn (f, список переменных);
Отличие ReadLn
от Read
в том, что при использовании readln после прочтения данных пропускаются все оставшиеся символы в данной строке, включая метку конца строки.
- чтение осуществляется с той позиции, где в данный момент стоит курсор;
- после чтения курсор сдвигается к первому непрочитанному символу.
Чтение до конца файла: оператор EOF (end of file)
.
Чтение до конца строки: оператор EOL (end of line)
.
Для возврата в начало файла:
close ( f );
reset ( f ); { начинаем с начала } |
close ( f );
reset ( f ); { начинаем с начала }
Запись в текстовый файл (классический Pascal)
Write (f, список переменных);
WriteLn (f, список переменных); |
Write (f, список переменных);
WriteLn (f, список переменных);
где f
— файловая переменная, а второй параметр – выводимые из программы и вводимые в файл данные (в виде значений переменных или просто данные)
Процедуры работы с файлом и закрытие файла
Нахождение конца файла:
Логическая функция, возвращающая True, если достигнут конец файла.
Нахождение конца строки:
Логическая функция, возвращающая True, если достигнут конец строки.
Удалить файл в Паскале
Переименование файла в Паскале
rename(переменная_файла,'новое имя файла'); |
rename(переменная_файла,'новое имя файла');
Закрытие:
Close (f); {закрытие файла} |
Close (f); {закрытие файла}
Важно: Таким образом, работа с файлом осуществляется через три основных шага:
- Процедура assign.
- Процедура reset или rewrite.
- Процедура close.
Рассмотрим пример работы с файлами в паскале:
Пример 1: В файле text.txt записаны строки. Вывести первую и третью из них на экран.
(предварительно создать text.txt с тремя строками)
Решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
| var
filetext: text;
a,b,c:string;
begin
assign(filetext,'c:\text.txt');
reset(filetext);
readln(filetext,a);
readln(filetext,b);
readln(filetext,c);
close(filetext);
writeln(a);
writeln(c);
end. |
var
filetext: text;
a,b,c:string;
begin
assign(filetext,'c:\text.txt');
reset(filetext);
readln(filetext,a);
readln(filetext,b);
readln(filetext,c);
close(filetext);
writeln(a);
writeln(c);
end.
|
1
2
3
4
5
6
7
| begin
Assign(input, '1.txt');
var a := ReadString;
var b := ReadString;
var c := ReadString;
print(a, c)
end. |
begin
Assign(input, '1.txt');
var a := ReadString;
var b := ReadString;
var c := ReadString;
print(a, c)
end.
|
Пример 2: Дан текстовый файл. Вывести количество содержащихся в нем символов и строк (маркеры концов строк
EOLN и конца файла
EOF при подсчете количества символов не учитывать).
Показать решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| var
F: Text;
N,K:integer;
Name:String;
C:Char;
begin
Assign(F,'c:\text.txt');
Reset(F);
N:=0;
K:=0;
While not eof(F) do
begin
inc(N);
While not eoln(f) do
begin
inc(K);
Read(F,C);
end;
Readln(F);
end;
Close(F);
Writeln(N,' ',K);
end. |
var
F: Text;
N,K:integer;
Name:String;
C:Char;
begin
Assign(F,'c:\text.txt');
Reset(F);
N:=0;
K:=0;
While not eof(F) do
begin
inc(N);
While not eoln(f) do
begin
inc(K);
Read(F,C);
end;
Readln(F);
end;
Close(F);
Writeln(N,' ',K);
end.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| begin
Assign(input, '1.txt');
var n, k: integer;
while not eof(input) do
begin
inc(n);
while not eoln(input) do
begin
inc(k);
var a := ReadChar;
end;
var b := ReadString;
end;
print($'строк {n}, символов {k}')
end. |
begin
Assign(input, '1.txt');
var n, k: integer;
while not eof(input) do
begin
inc(n);
while not eoln(input) do
begin
inc(k);
var a := ReadChar;
end;
var b := ReadString;
end;
print($'строк {n}, символов {k}')
end.
|
Пример 3:
Считать из файла input.txt числа (числа записаны в столбик). Затем записать их произведение в файл output.txt
Решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| var p, x: integer;
f: text;
begin
assign(f, 'input.txt');
reset(f);
p := 1;
while not eof(f) do begin
readln(f, x);
p := p * x;
end;
close(f);
assign(f, 'output.txt');
rewrite(f);
writeln(f, 'Произведение чисел ', p);
close(f);
end. |
var p, x: integer;
f: text;
begin
assign(f, 'input.txt');
reset(f);
p := 1;
while not eof(f) do begin
readln(f, x);
p := p * x;
end;
close(f);
assign(f, 'output.txt');
rewrite(f);
writeln(f, 'Произведение чисел ', p);
close(f);
end.
|
begin
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var p := 1;
while not eof(input) do
begin
var x := readInteger;
p := p * x;
end;
print($'произведение {p}');
end. |
begin
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var p := 1;
while not eof(input) do
begin
var x := readInteger;
p := p * x;
end;
print($'произведение {p}');
end.
|
pascal file text1. В цикле записать в файл числа от 1 до 10 (каждое — в своей строке), а затем их считать и отобразить на экране.
Дополните код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| var
filetext: text;
a:string;
i:integer;
begin
assign(filetext,'c:\text.txt');
rewrite(filetext);
for i:=1 to 10 do
...
reset(filetext);
for i:=1 to 10 do begin
...
...
end;
close(filetext);
end. |
var
filetext: text;
a:string;
i:integer;
begin
assign(filetext,'c:\text.txt');
rewrite(filetext);
for i:=1 to 10 do
...
reset(filetext);
for i:=1 to 10 do begin
...
...
end;
close(filetext);
end.
pascal file text2. Даны целые положительные числа
N и
K. Создать текстовый файл и записать в него
N строк, каждая из которых состоит из
K символов «*» (звездочка).
pascal file text3. Дана строка
S
и текстовый файл. Добавить строку
S
в конец файла.
Показать решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| var
F_in,F_out: Text;
Name,S: String;
begin
Write('S: ');
Readln(S);
Assign(F_in,'c:\text.txt');
Reset(F_in);
Assign(F_out,'c:\text1.txt');
Rewrite(F_out);
Writeln(F_out,S);
While not eof(F_in) do
begin
Readln(F_in,S);
Writeln(F_out,S);
end;
Close(F_in);
Close(F_out);
Erase(F_in);
Rename(F_out,'c:\text.txt');
end. |
var
F_in,F_out: Text;
Name,S: String;
begin
Write('S: ');
Readln(S);
Assign(F_in,'c:\text.txt');
Reset(F_in);
Assign(F_out,'c:\text1.txt');
Rewrite(F_out);
Writeln(F_out,S);
While not eof(F_in) do
begin
Readln(F_in,S);
Writeln(F_out,S);
end;
Close(F_in);
Close(F_out);
Erase(F_in);
Rename(F_out,'c:\text.txt');
end.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| begin
var s := readstring('s: ');
Assign(input, 'input.txt');
Assign(output, 'output.txt');
println(S);
while not eof(input) do
begin
s := ReadString;
println(s);
end;
close(input); // обязательно!
close(output); // обязательно!
Erase(input);
Rename(output, 'input.txt');
end. |
begin
var s := readstring('s: ');
Assign(input, 'input.txt');
Assign(output, 'output.txt');
println(S);
while not eof(input) do
begin
s := ReadString;
println(s);
end;
close(input); // обязательно!
close(output); // обязательно!
Erase(input);
Rename(output, 'input.txt');
end.
|
pascal file text4. Дано целое число
K
и текстовый файл. В данном файле вставить пустую строку перед строкой с номером
K
. Если строки с таким номером нет, то оставить файл без изменений.
Для решения задачи можно использовать дополнительный временный файл.
Пример 5: Дано целое число
K
и текстовый файл. Удалить из файла строку с номером
K
. Если строки с таким номером нет, то оставить файл без изменений.
Примерный результат:
до:
>> 2
0line
1line
2line
3line
после:
0line
2line
3line
Показать решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| var
F_in,F_out: Text;
Name,line: string;
K,i:integer;
begin
Write('K: ');
Readln(K);
Assign(F_in,'c:\text.txt');
Assign(F_out,'c:\text1.txt');
Reset(F_in);
Rewrite(F_out);
i:=0;
While not eof(F_in) do
begin
Readln(F_in,line);
inc(i);
if i<>K then Writeln(F_out,line);
end;
Close(F_in);
Close(F_out);
Erase(F_in);
Rename(F_out,'c:\text.txt');
end. |
var
F_in,F_out: Text;
Name,line: string;
K,i:integer;
begin
Write('K: ');
Readln(K);
Assign(F_in,'c:\text.txt');
Assign(F_out,'c:\text1.txt');
Reset(F_in);
Rewrite(F_out);
i:=0;
While not eof(F_in) do
begin
Readln(F_in,line);
inc(i);
if i<>K then Writeln(F_out,line);
end;
Close(F_in);
Close(F_out);
Erase(F_in);
Rename(F_out,'c:\text.txt');
end.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| begin
var k := readinteger('k: ');
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var i:=0;
while not eof(input) do
begin
var s := ReadString;
inc(i);
if i<>k then
println(s);
end;
close(input); // обязательно!
close(output); // обязательно!
Erase(input);
Rename(output, 'input.txt');
end. |
begin
var k := readinteger('k: ');
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var i:=0;
while not eof(input) do
begin
var s := ReadString;
inc(i);
if i<>k then
println(s);
end;
close(input); // обязательно!
close(output); // обязательно!
Erase(input);
Rename(output, 'input.txt');
end.
|
Пример 6: Дан текстовый файл
F1
с набором нулей и единиц. Необходимо заменить все вхождения сочетаний
101
на
000
. Скорректированные записи поместить в файл
F2
.
* Использовать функции для работы со строками:
— Pos()
— Delete()
— Insert()
Показать решение:
Паскаль |
PascalAbc.NET |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| var f1,f2: text;
pole:string;
pz:integer;
begin
assign(f1,'1.txt');
assign(f2,'2.txt');
reset(f1); rewrite(f2);
while not eof(f1) do
begin
readln(f1, pole);
while pos('101',pole)<>0 do
begin
pz:=pos('101',pole);
delete(pole,pz,3);
insert('000',pole,pz);
end;
writeln(f2,pole)
end;
close(f1);
close(f2);
end. |
var f1,f2: text;
pole:string;
pz:integer;
begin
assign(f1,'1.txt');
assign(f2,'2.txt');
reset(f1); rewrite(f2);
while not eof(f1) do
begin
readln(f1, pole);
while pos('101',pole)<>0 do
begin
pz:=pos('101',pole);
delete(pole,pz,3);
insert('000',pole,pz);
end;
writeln(f2,pole)
end;
close(f1);
close(f2);
end.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| begin
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var s:=readString;
var s1:='';
var ind := s.IndexOf('101');
while ind<>-1 do
begin
s1+=s[:ind+1];
s1+='000';
delete(s,1,ind+3); // удаляем всё вместе с 101
ind := s.IndexOf('101');
end;
s1+=s;
Println(s1);
end. |
begin
Assign(input, 'input.txt');
Assign(output, 'output.txt');
var s:=readString;
var s1:='';
var ind := s.IndexOf('101');
while ind<>-1 do
begin
s1+=s[:ind+1];
s1+='000';
delete(s,1,ind+3); // удаляем всё вместе с 101
ind := s.IndexOf('101');
end;
s1+=s;
Println(s1);
end.
|
Работа с данными из файла как с массивом
Пример 7: В файле
input.txt записаны числа (каждое — с новой строки), их количество не превышает
100. Необходимо
отсортировать их по возрастанию и записать в файл
output.txt.
Трудности:
- для сортировки необходим массив, для того чтобы одновременно работать со всеми числами;
- неизвестно общее количество чисел.
Алгоритм решения:
- объявляем массив для 100 элементов;
- открываем файл на чтение, просчитываем количество чисел, заполняя массив, сохраняем количество в N;
- сортируем N элементов массива;
- записываем результат в файл.
Фрагмент решения:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| { Определяем глобальные переменные: }
var A: array[1..100] of integer;
f: text;
N, i: integer;
{ Определяем функцию, считывающую числа из файла, и
записывающую их в массив. Функция возвращает кол-во элементов массива: }
function ReadFromFile: integer;
var i: integer;
begin
assign(f, 'input.txt');
...;{ открытие файла в режиме чтения }
i := 0;
while (...) and (...) do begin
i := i + 1;
readln(...,...);
end;
close(f);
ReadFromFile := i;
end;
{ Основная программа }
Begin
N := ReadFromFile ;
{ сортировка N элементов по возрастанию }
{ ... }
{ запись отсортированного массива в файл: }
assign(..., ...);
...;{ открытие файла в режиме записи }
for i:=1 to N do
writeln(..., ...);
close(f);
end. |
{ Определяем глобальные переменные: }
var A: array[1..100] of integer;
f: text;
N, i: integer;
{ Определяем функцию, считывающую числа из файла, и
записывающую их в массив. Функция возвращает кол-во элементов массива: }
function ReadFromFile: integer;
var i: integer;
begin
assign(f, 'input.txt');
...;{ открытие файла в режиме чтения }
i := 0;
while (...) and (...) do begin
i := i + 1;
readln(...,...);
end;
close(f);
ReadFromFile := i;
end;
{ Основная программа }
Begin
N := ReadFromFile ;
{ сортировка N элементов по возрастанию }
{ ... }
{ запись отсортированного массива в файл: }
assign(..., ...);
...;{ открытие файла в режиме записи }
for i:=1 to N do
writeln(..., ...);
close(f);
end.
pascal file text5. В файле input.txt записаны числа (каждое — с новой строки), их количество не превышает 100. Необходимо найти максимальное и минимальное число и записать их в файл output.txt.
pascal file text6. Дан текстовый файл. Удалить из него все пустые строки.
А теперь вернемся к олимпиадному заданию по Паскалю, частично решенному на одном из предыдущих заданиях:
Пример 8: Шифр Цезаря заключается в том, что каждая буква исходной строки заменяется третьей после нее буквой в алфавите, который считается написанным по кругу (все символы текста латинские и прописные).
Решить ту же задачу, в которой сдвиг будет не на 3 позиции, а на k, причем отрицательное значение является признаком сдвига влево, положительное — вправо.
Формат входных данных (файл p.in): В первой строке записано число k, не превышающее по модулю 20. Во второй строке — текст, который необходимо зашифровать. Все символы текста латинские и прописные.
Формат выходных данных (файл p.out): Выведите зашифрованный текст.
Пример:
p.in |
p.out |
3
hello earth
|
khoor hduwk |
* желательно создать файлы и записать данные в исходный файл «вручную»
* программа решена для k=3, выполните программу для любых k (не превышающих 20 по модулю)
Фрагменты кода:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| var a:char;
i,n,k:byte;
s,s1:string;
f_in,f_out:text;
begin
Assign(F_in,'z:\p.in');
Assign(F_out,'z:\p.out');
Reset(F_in);
Rewrite(F_out);
s1:='';
readln(f_in,k);
readln(f_in,s);
for i:=1 to length(s) do
begin
n:=ord(s[i]);
if n<>32 then {32 - пробел}
n:=n+3;
if ... then ...;
if ... then ...;
if ... then ...;
a:=chr(...);
s1:=...;
end;
writeln(s1);
writeln(f_out,s1);
close(f_in);
close(f_out)
end. |
var a:char;
i,n,k:byte;
s,s1:string;
f_in,f_out:text;
begin
Assign(F_in,'z:\p.in');
Assign(F_out,'z:\p.out');
Reset(F_in);
Rewrite(F_out);
s1:='';
readln(f_in,k);
readln(f_in,s);
for i:=1 to length(s) do
begin
n:=ord(s[i]);
if n<>32 then {32 - пробел}
n:=n+3;
if ... then ...;
if ... then ...;
if ... then ...;
a:=chr(...);
s1:=...;
end;
writeln(s1);
writeln(f_out,s1);
close(f_in);
close(f_out)
end.
pascal file text7.
Пять делителей.
Имя входного файла: z3.in
Имя выходного файла: z3.out
Найти сумму всех чисел от 1 до n, имеющих ровно 5 делителей.
Единица и само число входят в число его делителей.
Входные данные
В единственной строке входного файла z3.in записано одно натуральное число n(1 <= n <= 1012).
Выходные данные
В единственную строку выходного файла z3.out нужно вывести одно натуральное число — найденную сумму.
Примеры:
z3.in |
z3.out |
50 |
16 |
200 |
97 |
2015 |
722 |
* Олимпиадное задание (11 класс, 2016)
Зачем нужен c:char и name:string во втором примере?
не вижу такого примера…
Char — это переменная под символ, а String — под строку (по умолчанию 255-ти) символов. Можно было, конечно, использовать String [1], но легче же записать Char.
Моя программа:
Program z1;
var input,output: text;
str,str1:string;
i,j:integer;
Begin
assign(input,’input.txt’);
assign (output,’output.txt’);
reset(input);
rewrite(output);
while not eof(input)do Begin
while not eoln(input)do Begin
readln(input,str);
i:=length(str);writeln(str);
for j:= i downto 1 do str1:=str1+str[j];
end;
writeln(str1);
writeln(output,str1);
end;
close(input);
close(output);
end.
На входе:
Mercury 50
Venus 108
Earth 150
На выходе:
05 yrucreM801 suneV051 htraE
А надо:
05 yrucreM
801 suneV
051 htraE
Спасибо.
Не посмотрел дату, но в тоже время Вы определяете домену строки и уже потом читаете с конца к началу. Поэтому у вас все справа на лево. Так же вы производите чтение до конца строки и в тоже время читаете всю строку сразу readLN. На скидку.