ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ Федеральное государственное образовательное учреждение высшего профессионального об...
25 downloads
208 Views
409KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ Федеральное государственное образовательное учреждение высшего профессионального образования «ЮЖНЫЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ»
Д. В. Дубров, А. А. Чекулаева
Работа с текстовыми файлами в языке Паскаль
МЕТОДИЧЕСКИЕ УКАЗАНИЯ к решению задач по курсу «Информатика» для студентов 1 курса дневного и вечернего отделений факультета математики, механики и компьютерных наук
Ростов-на-Дону 2008
Методические указания разработаны кандидатом физико-математических наук, ассистентом кафедры прикладной математики и программирования Д. В. Дубровым и старшим преподавателем кафедры прикладной математики и программирования А. А. Чекулаевой.
Печатается в соответствии с решением кафедры прикладной математики и программирования факультета математики, механики и компьютерных наук ЮФУ, протокол № 9 от 2 октября 2008 г.
Оглавление 1
Текстовые файлы ...................................................................................................... 4 1.1 Посимвольная обработка текстовых файлов.................................................... 5 1.2 Построчная обработка текстовых файлов ...................................................... 10 1.3 Изменение содержимого текстовых файлов .................................................. 19 1.4 Ввод/вывод числовой информации в текстовые файлы ............................... 23
2
Задачи....................................................................................................................... 27
3
Индивидуадьные задания ...................................................................................... 29 3.1 Задание 1 ............................................................................................................ 29 3.2 Задание 2 ............................................................................................................ 35
Литература ..................................................................................................................... 42
3
1
Текстовые файлы
Текстовые файлы предназначены для хранения текстовой информации — последовательности символьных строк разной длины. Как и в случае с типизированными файлами, с точки зрения операционной системы текстовые файлы ничем не отличаются от остальных; интерпретация содержимого того или иного
файла
как
текстового
(или
типизированного)
является
целиком
ответственностью прикладной программы, работающей с данным файлом. Обычно (но не всегда) текстовые файлы имеют расширение “txt”, и для их создания и редактирования используют программы — текстовые редакторы. В качестве другого примера тестовых файлов можно привести файлы с расширением “pas” с исходными текстами программ на Паскале. С точки зрения программы на Паскале, текстовый файл — это последовательность символов, разделяемых на строки специальным символом «перевод строки». Например, файл, содержимое которого в текстовом редакторе выглядит следующим образом: ABC DE FG H
будет храниться в виде последовательности: ABC┘DE FG┘┘H
Здесь “┘” означает символ перевода строки (в текстовом редакторе он добавляется при нажатии клавиши “Enter”). Программа на Паскале имеет доступ к двум специальным переменным типа «текстовый файл»: Input и Output. Чтение данных из первой эквивалентно считыванию с клавиатуры, запись во вторую — выводу на экран. Таким образом, например, вывод на экран надписи можно осуществить как при помощи оператора 4
WriteLn(′Text′);
так и WriteLn(Output, ′Text′);
1.1 Посимвольная обработка текстовых файлов Обычно осуществляется при помощи двух вложенных циклов: наружный проходит по всем строкам в файле, а внутренний — по всем символам в текущей строке. Пример 1. Вывести содержимое текстового файла на экран (с сохранением разбиения на строки). Входные данные: SFileName — имя текстового файла; Текст программы: { Вывод на экран содержимого текстового файла } program s_1_1; var SFileName: string; FText: Text; C: Char; begin Write('Имя файла: '); ReadLn(SFileName); {
Открытие файла на чтение
{ Ввод имени файла } }
Assign(FText, SFileName); Reset(FText); {
Вывод содержимого файла
while not EOF(FText) do
} { пока не достигнут конец файла } 5
begin while not EOLn(FText) do
{ пока не конец строки }
begin Read(FText, C);
{ чтение очередного символа }
Write(C)
{ печать символа }
end;
{ while not EOLn(FText) }
ReadLn(FText);
{ пропуск символа перевода строки }
WriteLn
{ перевод строки на экране }
end;
{ while not EOF(FText) }
Close(FText)
{ Закрытие файла }
end.
Замечание: Необходимо особо обратить внимание на то, что в правильно составленной программе оператор Read(FText, C);
никогда не прочитает в переменную С символ перевода строки. Пример 2. Скопировать содержимое одного текстового файла в другой, но без пустых строк. Входные данные: SInFileName — имя входного текстового файла; SOutFileName — имя выходного текстового файла; Текст программы: { Копирование содержимого одного текстового файла в другой без пустых строк } program s_2_1; var SInFileName, SOutFileName: string; FIn, FOut: Text; 6
C: Char; BIsEmpty: Boolean; begin {
Ввод имён файлов
}
Write('Имя входного файла: '); ReadLn(SInFileName); Write('Имя выходного файла: '); ReadLn(SOutFileName); {
Открытие файлов на чтение и запись
}
Assign(FIn, SInFileName); Reset(FIn); Assign(FOut, SOutFileName); Rewrite(FOut); {
Копирование содержимого файла
while not EOF(FIn) do
}
{ пока не достигнут конец файла }
begin BIsEmpty := True;
{ предположение, что строка пустая }
while not EOLn(FIn) do
{ пока не конец строки }
begin Read(FIn, C);
{ чтение очередного символа }
Write(FOut, C);
{ вывод символа в выходной файл }
BIsEmpty := False
{ если попали внутрь цикла, } { значит текущая строка не пустая }
end;
{ while not EOLn(FIn) }
ReadLn(FIn);
{ пропуск в файле перевода строки }
if not BIsEmpty then
{ если строка была не пустой, то }
WriteLn(FOut)
{ перевод строки в выходном файле }
end; {
Закрытие файлов
{ while not EOF(FIn) } }
Close(FIn); Close(FOut) end.
7
Пример 3. Скопировать содержимое одного текстового файла в другой, но без n последних строк. Входные данные: SInFileName — имя входного текстового файла; SOutFileName — имя выходного текстового файла; N — количество строк в конце входного файла, которые не нужно копировать в выходной. Для решения задачи необходимо дважды прочесть содержимое входного файла. Первый проход необходим для того, чтобы узнать общее количество строк в файле (NLines). При втором проходе нужно скопировать в выходной файл известное на данный момент количество строк с начала входного файла (NLines - N). Необходимо предусмотреть случай, когда во входном файле окажется меньше строк, чем N. Текст программы: { Копирование содержимое одного текстового файла в другой без n последних строк } program s_3_1; var SInFileName, SOutFileName: string; FIn, FOut: Text; C: Char; I, N, NLines: Integer; begin {
Ввод данных
}
Write('Имя входного файла: '); ReadLn(SInFileName); 8
Write('Имя выходного файла: '); ReadLn(SOutFileName); Write('Количество строк для пропуска: '); ReadLn(N); {
Открытие входного файла на чтение
}
Assign(FIn, SInFileName); Reset(FIn); {
1. Определение количества строк во входном файле
}
NLines := 0; while not EOF(FIn) do begin NLines := NLines + 1; ReadLn(FIn);
{ пропуск символов до конца текущей } { строки, включая перевод строки }
end; {
{ while not EOF(FIn) }
Открытие выходного файла на запись
}
Assign(FOut, SOutFileName); Rewrite(FOut); {
2. Копирование (NLines - N) строк в выходной файл
}
{ вновь возврат на начало FIn }
Reset(FIn);
for I := 1 to NLines - N do begin while not EOLn(FIn) do begin Read(FIn, C);
{ чтение очередного символа в строке }
Write(FOut, C)
{ вывод символа в выходной файл }
end;
{ while not EOLn(FIn) }
ReadLn(FIn);
{ пропуск в файле перевода строки }
WriteLn(FOut)
{ перевод строки в выходном файле }
end; {
Закрытие файлов
{ for I := 1 to NLines - N } }
Close(FIn); Close(FOut) end. 9
Упражнения 1) Почему в примерах 1–3 были использованы циклы “while”, а не “repeat ... until”? 2) Программы из примеров 1–3 будут всегда добавлять в конец выходного файла (в конце печати на экран в примере 1) символ перевода строки, даже если в конце входного файла его не было. Как можно исправить это поведение (чтобы в конец выходного файла добавлялся символ перевода строки только в том случае, когда он есть в конце соответствующей строки входного файла)? 3) Почему программа s_3_1 будет работать корректно для случая, когда количество пропускаемых строк во входном файле (N), задаваемое пользователем, будет больше общего количества строк в нём? 4) Что произойдёт, если пользователь, запустив программу s_3_1, введёт в N нулевое значение? Отрицательное? 1.2 Построчная обработка текстовых файлов В отличие от посимвольной обработки, осуществляется считыванием из входного файла (записью в выходной файл) строки целиком за одно считывание (запись) — в переменную (из переменной) типа string. Пример 4. Вывести содержимое текстового файла на экран (с сохранением разбиения на строки). Входные данные: SFileName — имя текстового файла; Текст программы: { Вывод на экран содержимого текстового файла, построчная обработка } program s_1_2; 10
var SFileName, S: string; FText: Text; begin {
Ввод имени файла
}
Write('Имя файла: '); ReadLn(SFileName); {
Открытие файла на чтение
}
Assign(FText, SFileName); Reset(FText); {
Вывод содержимого файла
while not EOF(FText) do
} { пока не достигнут конец файла }
begin ReadLn(FText, S);
{ чтение строки, пропуск перевода }
WriteLn(S)
{ печать строки и перевода строки }
end; {
{ while not EOF(FText) }
Закрытие файла
}
Close(FText) end.
При сравнении данного решения с решением той же задачи методом посимвольной обработки (текст программы s_1_1 из примера 1) можно отметить следующие различия: – Вместо двух вложенных циклов здесь остался только один — внешний. – Вместо считывания во внутреннем цикле в переменную типа Char: Read(FText, C);
и пропуска символа перевода строки после внутреннего цикла: ReadLn(FText);
теперь используется одно считывание в переменную типа string, совмещённое с пропуском символа перевода строки: 11
ReadLn(FText, S);
Из данного примера можно сделать вывод о том, что при решении многих задач построчная обработка текстовых файлов будет заведомо проще в реализации, чем посимвольная. Необходимо, однако, выбирая построчную обработку, учитывать следующее: – Тип данных string не является частью стандарта языка Паскаль и доступен лишь в некоторых (хоть и популярных) его реализациях. Поэтому, использование его может привести к меньшей переносимости программ. – Программы, использующие построчную обработку, могут использовать для своей работы большее количество оперативной памяти. – Максимальное количество символов в строке, хранящейся в переменной типа string, ограничено сверху реализацией (обычно — 255), в то время как в строке текстового файла количество символов не ограничено (точнее, ограничено максимальным размером файла, зависящим от операционной системы, обычно — на много порядков большим). При считывании из файла в строковую переменную: ReadLn(FText, S);
в переменную S будет прочитано не больше символов, чем она может вместить (например, 10, если она описана как string[10]). Поскольку процедура ReadLn пропускает все непрочитанные символы до конца текущей строки (вместе с символом перевода строки, если он есть), может получиться так, что будет обработана только часть строки из файла. Этот недостаток можно исправить, используя двойной цикл, аналогичный посимвольной обработке (см. далее пример 5). Однако, в этом случае программа потеряет исходную простоту.
12
Пример 5. Вывести содержимое текстового файла на экран (с сохранением разбиения на строки), используя построчную обработку и учитывая возможность длинных строк в файле. Входные данные: SFileName — имя текстового файла; Текст программы: { Вывод на экран содержимого текстового файла, корректная построчная обработка длинных строк } program s_1_3; var SFileName, S: string; FText: Text; begin {
Ввод имени файла
}
Write('Имя файла: '); ReadLn(SFileName); {
Открытие файла на чтение
}
Assign(FText, SFileName); Reset(FText); {
Вывод содержимого файла
while not EOF(FText) do
} { пока не конец файла }
begin while not EOLn(FText) do
{ пока не конец строки }
begin Read(FText, S);
{ чтение подстроки из файла }
Write(S)
{ печать подстроки }
end;
{ while not EOLn(FText) }
ReadLn(FText);
{ пропуск в файле перевода } 13
WriteLn
{ печать перевода строки }
end; {
Закрытие файла
{ while not EOF(FText) } }
Close(FText) end.
Пример 6. Скопировать содержимое одного текстового файла в другой, но без пустых строк. Входные данные: SInFileName — имя входного текстового файла; SOutFileName — имя выходного текстового файла; Текст программы: { Копирование содержимое одного текстового файла в другой без пустых строк, построчная обработка } program s_2_2; var SInFileName, SOutFileName, S: string; FIn, FOut: Text; begin {
Ввод имён файлов
}
Write('Имя входного файла: '); ReadLn(SInFileName); Write('Имя выходного файла: '); ReadLn(SOutFileName); {
Открытие файлов на чтение и запись
Assign(FIn, SInFileName); Reset(FIn); Assign(FOut, SOutFileName); 14
}
Rewrite(FOut); {
Копирование содержимого файла
while not EOF(FIn) do
}
{ пока не достигнут конец файла }
begin ReadLn(FIn, S);
{ чтение строки, пропуск перевода }
if S <> '' then
{ если считанная строка не пустая, }
WriteLn(FOut, S)
{ вывод строки и перевода строки }
end; {
{ while not EOF(FIn) }
Закрытие файлов
}
Close(FIn); Close(FOut) end.
При сравнении данного решения с решением той же самой задачи методом посимвольной обработки (текст программы s_2_1 из примера 2) можно отметить упрощение
алгоритма.
Действительно,
вместо
использования
логической
переменной для проверки строки на пустоту используется более ясное для понимания сравнение: “S <> ''”. Очевидно, что при решении других задач выбор построчной обработки может привести к ещё большему выигрышу в простоте получаемого алгоритма, здесь в полной мере раскрываются все её преимущества. Пример 7. Скопировать содержимое одного текстового файла в другой, но без n последних строк. Входные данные: SInFileName — имя входного текстового файла; SOutFileName — имя выходного текстового файла; N — количество строк в конце входного файла, которые не нужно копировать в выходной. В отличие от предыдущего решения той же задачи (пример 3), далее будет использован алгоритм, требующий одного прохода по входному файлу, вместо
15
двух, с использованием буфера строк. Возможность использования данного алгоритма открывается благодаря применённой построчной обработке файлов. Алгоритм состоит из двух частей. Сначала происходит заполнение буфера (массив из строк) N первыми строками входного файла. Затем в цикле, перебирающем
оставшиеся
строки
во
входном
файле,
последовательно
записывается в выходной файл строка из буфера в позиции I, и затем в ту же самую позицию в буфере считывается из входного файла очередная строка. При этом I меняет своё значение на каждой итерации циклически: от 1 до N, затем снова 1, и так далее. Таким образом, массив из строк выступает в качестве циклического буфера, и чтение/запись на второй стадии алгоритма организованы таким образом, что на одной итерации в выходной файл будет записана строка, считанная N шагов назад (либо в том же самом цикле, либо на первом шаге алгоритма, когда происходило только чтение). Текст программы: { Копирование содержимое одного текстового файла в другой без n последних строк, построчная обработка } program s_3_2; const NMax = 100; var ASBuffer: array [1 .. NMax] of string; SInFileName, SOutFileName: string; FIn, FOut: Text; I, N: Integer;
16
begin {
Ввод данных
}
Write('Имя входного файла: '); ReadLn(SInFileName); Write('Имя выходного файла: '); ReadLn(SOutFileName); Write('Количество строк для пропуска: '); ReadLn(N); if (N < 1) or (N > NMax) then WriteLn( 'Ошибка: количество пропускаемых строк ', 'должно быть положительным и не больше ', NMax) else begin {
Открытие входного файла на чтение
}
Assign(FIn, SInFileName); Reset(FIn); {
1. Считывание в буфер первых N строк
}
I := 0; while not EOF(FIn) and (I < N) do begin {
Определение следующей позиции в буфере
}
I := I + 1; {
Чтение очередной строки в элемент I буфера
}
ReadLn(FIn, ASBuffer[I]) end; {
{ while not EOF(FIn) and (I < N) }
Открытие выходного файла на запись
}
Assign(FOut, SOutFileName); Rewrite(FOut); {
2. Запись строк из буфера в выходной файл
{
с одновременным считыванием в него строк
{
из входного файла
}
I := 0; 17
} }
while not EOF(FIn) do begin {
Определение следующей позиции в циклическом буфере
}
{
I будет меняться на каждой последующей итерации:
}
{
1, 2, ..., N, 1, 2 и т. д.
}
I := 1 + I mod N; {
Запись строки из элемента I буфера, эта строка
{
была прочитана из входного файла N шагов назад
} }
WriteLn(FOut, ASBuffer[I]); {
Чтение очередной строки в элемент I буфера
}
ReadLn(FIn, ASBuffer[I]) end; {
Закрытие файлов
{ while not EOF(FIn) } }
Close(FIn); Close(FOut) end
{ if N > NMax (else) }
end.
Замечание: Данная программа (как и программа s_3_1 из примера 3) будет считать, что количество строк в файле на единицу больше количества в нём символов перевода строки. Так, будет считаться, что файл с содержимым: ABC┘
состоит из двух строк (первая строка: “ABC”, вторая строка пустая). Поскольку программа всегда добавляет в конец выходного файла символ перевода строки (если последняя записанная строка не пустая), копирование содержимого файла, в конце которого есть символ перевода строки, без одной последней строки фактически приведёт к тому, что последняя (пустая) строка также будет скопирована. При сравнении данного решения с решением той же задачи методом посимвольной обработки (текст программы s_3_1 из примера 3) можно отметить, что выбранный здесь способ даёт выигрыш в производительности
18
(необходимо прочитать входной файл всего один раз вместо двух), правда, за счёт существенного увеличения объёма используемой оперативной памяти. Упражнения 1) Почему в программе s_3_2 из примера 7 запрещён ввод нулевого значения в переменную N? Как изменить программу, чтобы она работала корректно при нулевом значении количества пропускаемых строк? 2) Почему программа s_3_1 будет работать корректно для случая, когда количество пропускаемых строк (N) будет больше общего количества строк во входном файле? В чём отличие, с этой точки зрения, данной программы от программы s_3_1 из примера 3? 3) Как можно исправить программы из примеров 4–7 так, чтобы в конец выходного файла (в конце печати на экран в примере 4) выводился символ перевода строки только в том случае, когда он есть в конце соответствующей строки входного файла? 1.3 Изменение содержимого текстовых файлов Поскольку текстовый файл невозможно открыть на чтение и запись одновременно, изменение его содержимого обычно осуществляется в два этапа. Сначала исходный файл открывается на чтение, и его содержимое (с нужными изменениями) копируется во временный файл, открытый на запись. Затем исходный файл открывается на запись, а временный — на чтение, и содержимое последнего копируется в исходный. В качестве альтернативы можно отметить изменение содержимого на втором этапе (при обратном копировании), вместо первого. Пример 8. Реализовать процедуру, вставляющую в начало заданного текстового файла пустую строку. Входные данные: FT — изменяемый файл; 19
Текст процедуры: { Добавление пустой строки в начало текстового файла - стандартная версия Входные данные: FT - изменяемый файл, должен быть связан с именем существующего файла до вызова процедуры. } procedure s41(var FT: Text); var FTemp: Text; S: string; begin {
Связывание файловой переменной для временного файла
{
Аналогичное связывание для FT выполнено вне процедуры
} }
Assign(FTemp, 'temp.tmp'); {
Открытие исходного файла на чтение
}
Reset(FT); {
Открытие временного файла на запись
}
Rewrite(FTemp); {
Копирование исходного файла во временный с изменениями
}
WriteLn(FTemp);
{ изменения: добавление пустой строки }
while not EOF(FT) do
{ дальше копирование без изменений }
begin ReadLn(FT, S); WriteLn(FTemp, S) end; {
Открытие временного файла на чтение
}
Reset(FTemp); {
Открытие исходного файла на запись
}
Rewrite(FT); {
Копирование временного файла во исходный 20
}
while not EOF(FTemp) do begin ReadLn(FTemp, S); WriteLn(FT, S) end; {
Закрытие входного файла
}
Close(FT); {
Усечение размера временного файла до 0
}
Rewrite(FTemp); {
Закрытие временного файла
}
Close(FTemp) end;
Замечания: 1) Данный пример демонстрирует правила использования файловых переменных в качестве параметров процедур и функций. Во-первых, они всегда передаются по ссылке. Во-вторых, внутри подпрограмм происходит связывание файловых переменных при помощи процедуры Assign только для переменных, объявленных локально. В большинстве случаев связывать файловую переменнуюпараметр подпрограммы внутри самой подпрограммы не имеет смысла и снижает её универсальность. 2) Недостатком данного подхода является то, что временный файл остаётся на диске после завершения процедуры. Отчасти он компенсируется тем, что по окончании процедуры его длина устанавливается в 0 при помощи вызова процедуры Rewrite перед Close. В некоторых реализациях языка Паскаль (Borland Turbo Pascal и т. д.) существуют дополнительные процедуры и функции для управления файлами: удаления, переименования и т. д. Например, для того чтобы удалить временный файл после завершения работы с ним, можно в конце процедуры s41 (обязательно после закрытия временного файла) добавить следующий оператор: Erase(FTemp) 21
Чтобы воспользоваться процедурой переименования файлов, в примере 8 необходимо изменить процедуру s41 таким образом, чтобы она принимала в качестве параметра строку с именем обрабатываемого файла вместо файловой переменной. Пример 9. Реализовать процедуру, вставляющую в начало заданного текстового файла пустую строку (с использованием расширений языка Паскаль для управления файлами). Входные данные: ST — имя изменяемого файла (строка); Текст процедуры: { Добавление пустой строки в начало текстового файла - версия, использующая расширения языка для управления файлами Входные данные: ST - имя изменяемого файла, сам файл не должен быть открыт до вызова процедуры. } procedure s42(ST: string); var FT, FTemp: Text; S: string; begin {
Связывание файловой переменной для основного файла
}
Assign(FT, ST); {
Связывание файловой переменной для временного файла
Assign(FTemp, 'temp.tmp'); {
Открытие исходного файла на чтение
}
Reset(FT); {
Открытие временного файла на запись
Rewrite(FTemp); 22
}
}
{
Копирование исходного файла во временный с изменениями
{
В этой части нет никаких отличий от процедуры s41
}
}
WriteLn(FTemp); while not EOF(FT) do begin ReadLn(FT, S); WriteLn(FTemp, S) end; {
Закрытие основного файла
}
Close(FT); {
Удаление основного файла
}
Erase(FT); {
Закрытие временного файла
}
Close(FTemp); {
Переименование временного файла в имя основного
}
Rename(FTemp, ST) end;
1.4 Ввод/вывод числовой информации в текстовые файлы Точно так же, как и в случае с файлами Input и Output, можно организовать ввод/вывод числовых данных из/в любых других текстовых файлов. Пример 10. Дан текстовый файл, содержащий последовательность вещественных чисел. Необходимо записать в другой текстовый файл все числа из него, бóльшие их среднего арифметического. Входные данные: Последовательность вещественных чисел в текстовом файле с именем “input.txt”. Выходные денные: Последовательность вещественных чисел в текстовом файле с именем “output.txt”. Оба файла расположены в каталоге программы. Текст программы: 23
{ Запись в текстовый файл всех чисел из другого текстового файла, больших их среднего арифметического } program s_5_1; var FIn, FOut: Text; R, RAv: Real; NCount: Integer; begin {
Открытие входного файла
}
Assign(FIn, 'input.txt'); Reset(FIn); {
Нахождение среднего арифметического
}
NCount := 0; RAv := 0.0; while not EOF(FIn) do begin Read(FIn, R); NCount := NCount + 1; RAv := RAv + R end; if NCount > 0 then RAv := RAv / NCount; {
Открытие выходного файла
}
Assign(FOut, 'output.txt'); Rewrite(FOut); {
Возврат на начало входного файла
}
Reset(FIn); {
Запись в выходной файл всех чисел, больших RAv
while not EOF(FIn) do 24
}
begin Read(FIn, R); if R > RAv then Write(FOut, ' ', R) end; {
Закрытие файлов
}
Close(FIn); Close(FOut) end.
При работе с текстовыми файлами необходимо учитывать, что фактически (в отличие от типизированных файлов) в них не содержится никакой числовой информации. Просто при (например) записи в текстовый файл целого или вещественного числа оно преобразуется в последовательность символов, выглядящих, как его десятичное представление. Упражнения 1) Почему в программе s_5_1 из примера 10 при записи в файл очередного вещественного числа перед ним записывается пробел? Что будет, если эти пробелы не записывать перед каждым числом? 2) Почему в программе s_5_1 пробел записывается перед числом, а не после него? Пример 11. Дано натуральное n и последовательность из n целых неотрицательных
чисел,
WriteDiagramLR(N,
хранящаяся VA,
в
массиве.
Реализовать
процедуру
VFText), записывающую в текстовый файл
VFText графическое представление последовательности (передаваемой через параметр-массив VA) в виде столбиковой диаграммы, ориентированной слева направо, с подписями значений последовательности, расположенными слева от столбиков. Пример: для последовательности: 3, 5, 7, 4, 8, 4, 6, 1, 5, 0 25
(n = 10) в текстовый файл необходимо записать следующую информацию: 3 XXX 5 XXXXX 7 XXXXXXX 4 XXXX 8 XXXXXXXX 4 XXXX 6 XXXXXX 1 X 5 XXXXX 0
Входные данные: Натуральное число N и последовательность из N целых неотрицательных чисел, хранящаяся в первых N элементах массива VA. Выходные денные: Последовательность строк, выводимая в текстовый файл VFText. Текст процедуры: { Запись в текстовый файл последовательности целых неотрицательных чисел в виде столбиковой диаграммы, ориентированной слева направо. Входные данные: N
- размер последовательности;
VA
- последовательность;
VFText - текстовый файл. } procedure WriteDiagramLR( N: Integer; var VA: TVector; var VFText: Text); var I, J: Integer; begin 26
{
Открытие выходного файла
}
Rewrite(VFText); {
Запись пустой строки
}
WriteLn(VFText); {
Запись остальных строк
if N > 0 then
}
{
последовательность не пуста
{
для каждого числа послед-сти
}
begin for I := 1 to N do
}
begin {
Запись пробела, текстового представления
}
{
числа в поле из 3 позиций и пробела
}
Write(VFText, ' ', VA[I] : 3, ' '); {
Запись нужного количества 'X'
}
for J := 1 to VA[I] do Write(VFText, 'X'); {
Запись перевода строки
}
WriteLn(VFText) end end; {
{
for I := 1 to N do
{
if N > 0
Запись пустой строки
}
}
}
WriteLn(VFText); {
Закрытие выходного файла
}
Close(VFText) end;
{
WriteDiagramLR
2 1)
}
Задачи
Дан текстовый файл. Необходимо переписать его содержимое в другой текстовый файл, добавляя в начало каждой строки её порядковый номер (десятичную запись целого числа шириной в 5 символов, выровненную по правой границе поля) и пробел.
2)
Дан текстовый файл. Необходимо переписать в другой текстовый файл все его непустые строки, которые начинаются и оканчиваются одинаковым символом. 27
3)
Дан текстовый файл. Необходимо переписать в другой текстовый файл его содержимое, кроме непустых строк, начинающихся с точки.
4)
Дан текстовый файл. Найти количество пустых строк в нём.
5)
Дан текстовый файл. Найти длину его максимальной строки.
6)
Дан текстовый файл. Найти количество строк в нём, начинающихся с заданного символа.
7)
Дан текстовый файл. Найти количество строк в нём, оканчивающихся заданным символом.
8)
Дан текстовый файл. Найти количество строк в нём, состоящих из одинаковых символов.
9)
Дан текстовый файл. Удалить в нём все строки максимальной длины.
10) Дан текстовый файл. Переписать его содержимое (кроме символов перевода строки) в другой текстовый файл, вставляя символы перевода строки после каждой точки, а также через 40 символов после предыдущего перевода строки. 11) Дан текстовый файл. Переписать его содержимое в другой текстовый файл, дополняя справа все его строки, меньшие по длине 80 символов, пробелами справа до 80 символов. 12) Дана последовательность символов, заканчивающаяся точкой и вводимая пользователем с клавиатуры. Необходимо записать её в текстовый файл, вставляя в неё символы перевода строки через каждые 40 символов. 13) Даны два текстовых файла. Проверить их содержимое на равенство. 14) Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Заменить подряд идущие пробелы одним пробелом. 15) В
текстовом
файле
записана
последовательность
целых
чисел,
разделённых пробелами. Описать процедуру, переписывающую в другой текстовый файл все числа из первого файла, кроме чисел, равных максимальному значению данной последовательности. 28
3
Индивидуадьные задания
3.1 Задание 1 1)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами.
Проверить,
содержится ли в файле заданное число. Найти сумму и количество чётных чисел файла. Результаты с соответствующими комментариями дописать в исходный файл. 2)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка
файла
содержит
числа,
разделённые
пробелами.
Извлечь
квадратный корень из каждого числа в тех строках, все элементы которых имеют
положительные значения. Подсчитать количество изменённых
строк и результат с
соответствующими комментариями поместить в
конец исходного файла. 3)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Заменить в каждой строке элементы с наибольшим значением нулём. Создать файл, который будет содержать данные исходного файла, а затем данные преобразованного файла.
4)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами.
Найти
максимальные элементы в каждой строке исходного файла и поместить их в новый текстовый файл. Выдать оба файла. 5)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Подсчитать количество чисел в каждой строке. Найти номера строк, содержащих заданное
число.
Результаты
с соответствующими
поместить в новый текстовый файл.
29
комментариями
6)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Найти среднее арифметическое чисел файла. Затем пустой строкой заменить строку с максимальной количеством чисел и удалить строку с минимальным количеством чисел в строке.
7)
Даны два текстовых файла, состоящих из одной или нескольких строк. Каждая
строка
файла
содержит
числа,
разделённые
пробелами.
Проверить поэлементно файлы на равенство. Если строки файлов не содержат поэлементно одинаковые числа, выдать номер строки и номер числа в строке, указывающих на первое несовпадение. 8)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Удалить из файла все числа, меньшие заданного числа. Если в текстовом файле таких чисел нет, оставить его без изменений.
9)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Из каждой строки файла удалить числа, предшествующие первому положительному числу. Если в строке нет положительных чисел, оставить её без изменений.
10) Дан текстовый файл, состоящий из нескольких строк. Строки содержат слова, разделённые пробелами.
В каждой строке файла найти
максимальную длину слова и подсчитать количество слов максимальной длины. За каждой строкой поместить строку с результатами обработки строки. 11) Дан текстовый файл, состоящий из нескольких строк. Строки содержат слова, разделённые пробелами. Подсчитать количество слов в каждой строке. Результаты с соответствующими комментариями поместить в виде строк в конце исходного файла.
30
12) Дан текстовый файл, состоящий из нескольких строк. Строки содержат слова, разделённые пробелами. В начало каждой строки, содержащей заданное слово, добавить слово ‘ДОБАВЛЕНО’. 13) Дан текстовый файл, состоящий из нескольких строк. Строки содержат слова, разделённые пробелами. Удалить первое слово из каждой строки файла. 14) Дан текстовый файл, состоящий из нескольких строк. Строки содержат слова, разделённые пробелами. Перед каждым словом поместить номер слова в строке. 15) Дан текстовый файл. Структура строки текстового файла: фамилия и инициалы
автора
(20
позиций),
название
книги
(30
позиций),
издательство (10 позиций), год издания (4 позиции). Создать новый текстовый файл из строк, содержащих сведения о книгах, изданных за период с 1960 – 2000г. 16) Дан текстовый файл. Структура строки текстового файла: фамилия и инициалы
автора
(20
позиций),
название
книги
(30
позиций),
издательство (10 позиций), год издания (4 позиции). Создать новый текстовый файл из строк, содержащих сведения о книгах, написанных заданным автором, создать новый текстовый файл. 17) Дан текстовый файл, состоящий из нескольких строк. Каждая строка содержит слова, разделённые пробелами. Найти максимальную длину слов файла и подсчитать количество слов максимальной длины. Результаты с соответствующими комментариями поместить в конце исходного файла. 18) Дан текстовый файл, состоящий из чисел: первое число является целым числом – это показатель степени многочлена n. Далее следуют вещественные числа. Вначале расположено значение x, коэффициенты
многочлена
a n x n + a n −1 x n −1 + ... + a 1 x + a 0 31
затем – все в
порядке
убывания степеней: n x a n a n −1 a n − 2 . . . a 0 . По данным текстового файла, вычислить значение многочлена, используя схему Горнера. Вид заданного многочлена и результат вычислений поместить в новый текстовый файл. 19) Дан текст, состоящий из нескольких строк. Каждая строка текста содержит слова, разделённые пробелами. Создать текстовый файл. В каждую строку файла поместить слово исходного текста и список номеров строк исходного текста, в которых встречается данное слово. Если в некоторой строке текста слово встречалось дважды, номер строки должен один раз попасть в файл. 20) Дан текстовый файл и две цепочки символов x = x1 x 2 ...x n и y = y1 y 2 ... y m (n ≠ m в общем случае). Переписать текст из исходного файла в новый файл, заменяя каждую встреченную цепочку x на заданную цепочку символов y. Дополнительное требование: Данное задание можно выполнять со следующим дополнительным условием: необходимо при считывании из входного файла одновременно хранить в памяти не более одного символа из него (очередной символ считывается в переменную C типа Char, ранее считанные символы нигде не запоминаются, кроме выходного файла). 21) Дан текстовый файл. Удалить из файла текст, расположенный в скобках ‘(‘ и ‘)’, включая скобки. Предполагается, что внутри каждой пары скобок нет вложенных скобок ‘(‘, ‘)’. Указание. Использовать в программе целочисленную переменную i такую, что i равно 0 или 1: i = 1 означает, что ранее была прочитана левая скобка, для которой пока не нашлось правой. 22) Дано натуральное n и последовательность из n целых неотрицательных чисел,
хранящаяся
в
массиве.
Реализовать
процедуру
WriteDiagramDU(N, VA, VFText), записывающую в текстовый 32
файл
графическое
VFText
(передаваемой
через
представление
параметр-массив
VA)
последовательности в
виде
столбиковой
диаграммы, ориентированной снизу вверх, с подписями значений последовательности, расположенными под столбиками. Пример: для последовательности: 3, 5, 7, 4, 8, 4, 6, 1, 5, 0 (n
=
10)
в
текстовый
файл
необходимо
записать
следующую
информацию: X X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
3
5
7
4
8
4
6
1
5
0
Указание: в качестве руководства можно воспользоваться примером 11. 23) Решить предыдущую задачу для случая, когда необходим вывод столбиковой диаграммы, ориентированной сверху вниз: 3
5
7
4
8
4
6
1
5
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
0
X
24) Дано натуральное число n. Напечатать в текстовом файле первые n строк треугольника Паскаля, в одном из следующих видов: 33
1 1 1 1 1
1 1
2 3
4
1
1
2
1
1
3
3
1
4
6
4
1
1 3
6
1 1 4
1
1
..................
.................
Здесь все крайние числа равны 1, а каждое внутреннее — сумме двух чисел над ним. Дополнительное
требование:
В
первом
варианте
отображения
треугольника Паскаля в формируемом текстовом файле должно быть минимально
возможное
количество
пробелов.
Другими
словами,
необходимо минимизировать размер получаемого файла (лишними могут считаться «хвостовые» пробелы в конце каждой строки). 25) Дано натуральное число n, а также входной текстовый файл, состоящий из абзацев. Каждый из абзацев состоит из некоторого количества строк, соседние абзацы отделены друг от друга одной или несколькими пустыми строками. Каждый абзац содержит некоторое количество слов — последовательностей символов, отделяемых друг от друга одним или несколькими пробелами и/или символом перевода строки. В начале каждой строки может находиться один или несколько пробелов перед первым словом. Необходимо скопировать все слова из входного файла в выходной по следующим правилам: a) Необходимо сохранить исходный порядок абзацев и слов в каждом абзаце из входного файла. b) Внутри одного абзаца каждое слово должно отделяться от соседнего либо одним пробелом, либо одним символом перевода строки. c) В начале строки не должно быть ведущих пробелов, также «хвостовых» пробелов не должно быть в конце строки. 34
d) Соседние абзацы должны отделяться друг от друга ровно одной пустой строкой. e) Перед первым абзацем не должно быть пустых строк, после последнего абзаца допускается максимум одна пустая строка. f) На каждой строке абзаца, начиная с первой, необходимо разместить максимальное количество слов, но так, чтобы общая длина строки не превосходила n. Исключение: если некоторое слово длиннее n, оно должно быть расположено без изменений на отдельной строке. Требования к решению: Необходимо использовать посимвольную обработку текстовых файлов. Для считывания данных необходимо использовать символьный массив (“array [1 .. NMax] of Char”) в качестве буфера для накопления символов одного слова. По окончании считывания слова программа должна принять решение: вывести ли данное слово в текущей строке выходного файла, или же начать с него следующую строку. 3.2 Задание 2 1)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит числа, разделённые пробелами. Найти номера строк, содержащих минимальный и максимальный элементы. Результаты с соответствующими пояснениями поместить в конце файла. Переставить в файле строки с минимальным и максимальным элементами.
2)
Даны два текстовых файла, состоящих из одной или нескольких строк. Каждая
строка
файла
содержит
числа,
разделённые
пробелами.
Проверить, состоит ли первый файл из одинаковых чисел. Если все числа первого файла одинаковые, образовать третий текстовый файл, поместив в его начало содержимое второго файла, а затем – содержимое первого файла. Если первый файл не состоит из одинаковых чисел, и оба файла содержат одинаковое количество чисел в каждой строке, поместить в 35
третий текстовый файл значения, равные сумме соответствующих значений первого и второго файлов, сохраняя деление на строки. 3)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит вещественные числа, разделённые пробелами. Найти среднее арифметическое положительных элементов файла и номер максимального элемента. Найденные значения с соответствующими комментариями добавить в конец файла.
4)
Дан текстовый файл, состоящий из одной или нескольких строк. Каждая строка файла содержит вещественные числа, разделённые пробелами. Из строки максимальной длины удалить все числа-нули. Если в строке нет нулей, оставить её без изменений. В строке минимальной длины найти произведение и количество ненулевых элементов. Если в этой строке таких элементов нет, вывести соответствующее сообщение.
5)
Дан текстовый файл, состоящий из одной или нескольких строк. Строки файла содержит вещественные числа (положительные и отрицательные и нулевые), разделённые пробелами. В каждой строке найти два элемента с наиболее близкими значениями. Использовать вспомогательный массив для размещения чисел строки. Результаты поиска с соответствующими комментариями дописывать в конец каждой строки файла.
6)
Дан текстовый файл, содержащий вещественные числа. Описать логическую функцию mid(F, M), которая определяет, имеет ли файл F нечётную длину, и, если имеет, присваивает параметру M средний элемент этого файла. Продемонстрировать работу функции.
7)
Дан текстовый файл. Подсчитать количество пустых строк и количество строк, которые начинаются и оканчиваются на одну и ту же букву.
8)
Подсчитать количество символов-цифр в каждой строке. Результаты подсчёта поместить в другой текстовый файл в виде строк: ‘В строке … количество символов-цифр равно …’
36
9)
Дан текстовый файл, состоящий из одной или нескольких строк. Подсчитать общее количество строк в файле и количество строк максимальной длины. Дополнить файл двумя строчками: ‘Всего строк в файле - …’ и ‘Количество пустых строк - …’
10) Сформировать текстовый файл из строк. В первую строку поместить один символ ‘a’, во вторую – два символа ‘b’, в третью – три символа ‘c’ и т.д. В последнюю строку поместить 26 символов ‘z’. 11) Дан текстовый файл, состоящий из нескольких строк. Подсчитать в нём количество строк и номер первой пустой строки. В каждой строке подсчитать количество символов, отличных от символа ` ` (пробел). Все результаты подсчёта с соответствующими комментариями поместить в новый текстовый файл. 12) Дан текстовый файл, состоящий из нескольких строк. Зашифровать строку наибольшей длины, заменив каждый символ его кодом. Остальные строки оставить без изменения. Расшифровать зашифрованную строку. 13) Дан текстовый файл из строк целых чисел. Каждое число представляет собой код буквы. Расшифровать текст и записать его в новый текстовый файл. Полученный файл зашифровать и сравнить его с заданным файлом. 14) Дан текстовый файл, состоящий из
нескольких строк.
Подсчитать
количество цифр в каждой строке и во всём файле. Определить, сколько раз каждая цифра встречается в файле. Результаты с соответствующими комментариями поместить в конце исходного текстового файла. 15) Дан текстовый файл, состоящий из нескольких строк. Подсчитать количество пустых строк, количество строк заданной длины к и количество
символов-цифр
соответствующими
в
каждой
комментариями
строке.
Результаты
с
поместить в конце исходного
текстового файла. 16) Дан
текстовый
файл,
состоящий
из
нескольких
строк.
Найти
минимальную длину строк файла. Результат с соответствующими 37
комментариями поместить в конце исходного текстового файла. Затем строки минимальной длины заменить двумя пустыми строками. Файл может содержать все строки одинаковой длины, может содержать пустые строки. Все возможные случаи
протестировать при выполнении
программы. 17) Дан текстовый файл, состоящий из нескольких строк. Удалить из него строку с заданным номером, если это возможно. 18) Дан текстовый файл, состоящий из нескольких строк. Удалить из файла символы-согласные, сохранив количество строк в файле. Если строка состоит только из согласных, она становится пустой строкой. 19) Дан текстовый файл, состоящий из нескольких строк. Строку заданной длины k разместить в конце текстового файла. 20) Дан текстовый файл, состоящий из нескольких строк. Подсчитать количество повторений каждой буквы и занести в новый текстовый файл в виде строк: ‘буква … – количество …’ 21) Дан текстовый файл, состоящий из нескольких строк. Проверить, содержит ли файл строку заданной длины. Если строка заданной длины имеется в файле, изменить в ней порядок следования символов на обратный. 22) Дан текстовый файл, состоящий из нескольких строк. Изменить порядок следования строк в файле на обратный порядок следования. 23) Дан текстовый файл, состоящий из нескольких строк. Максимальная ширина строки текстового файла – заданное число k. Текст выровнен по левому краю. Выровнять текст по правому краю и поместить в новый текстовый файл. Выдать содержимое обоих файлов. 24) Дано натуральное n и последовательность из n целых неотрицательных чисел,
хранящаяся
в
массиве.
Реализовать
процедуру
WriteDiagramRL(N, VA, VFText), записывающую в текстовый файл
VFText
графическое 38
представление
последовательности
(передаваемой
через
параметр-массив
VA)
в
виде
столбиковой
диаграммы, ориентированной справа налево, с подписями значений последовательности, расположенными справа от столбиков. Пример: для последовательности: 3, 5, 7, 4, 8, 4, 6, 1, 5, 0 (n
=
10)
в
текстовый
файл
необходимо
записать
следующую
информацию: XXX
3
XXXXX
5
XXXXXXX
7
XXXX
4
XXXXXXXX
8
XXXX
4
XXXXXX
6
X
1
XXXXX
5 0
Указание: в качестве руководства можно воспользоваться примером 11. 25) Даны натуральные числа n и h, а также последовательность из n целых чисел ai. Необходимо создать текстовый файл, содержащий графическое представление последовательности {ai} в виде столбиковой диаграммы, в которой высота i-го столбца (нумерация слева направо) пропорциональна |ai|, столбец направлен вверх или вниз относительно базовой линии в зависимости
от
знака
a i,
максимальная
высота
столбца
(соответствующего maxi |ai|) равна h. Пример: для последовательности: 190, 133, -170, 64, 0, 49, -141, 225, -96, 34 при m = 10 должен быть создан текстовый файл со следующим содержимым:
39
| | |
|
|
|
|
|
|
|
|
|
|
|
-
|
|
1
|
|
|
7
|
|
1
-
|
|
1
|
-
|
|
4
|
9
|
0
|
|
1
|
6
|
1
|
6
4
|
2
|
3
9
3
|
4
9
|
2
|
4
0
3
|
|
5
|
|
|
|
|
|
|
0
|
|
Сформулируем точные требования к формату выходного файла: a) В начале файла должна быть одна пустая строка. b) В начале каждой непустой строки должно быть два пробела, соседние столбцы отделяются друг от друга также двумя пробелами. c) Высота i-го столбца (нумерация слева направо) должна быть равна [k |ai|], где k = h / maxi |ai|, d) [·] — операция округления, соответствующая в Паскале функции Round. e) Столбец должен быть направлен вверх, если ai > 0, иначе — вниз. f) Столбцы должны быть сформированы из символов “|” (можно выбрать любой другой символ), расположенных непрерывно на нескольких соседних строках.
40
g) Разные столбцы, соответствующие положительным ai, должны быть выровнены по нижней строке, на которой они расположены. По следующей
строке
должны
быть
выровнены
все
столбцы,
соответствующие отрицательным ai, причём эта строка должна быть для них верхней. h) Непосредственно под (над) каждым столбцом, соответствующим неотрицательному
(отрицательному)
a i,
должны
располагаться
символы, идущие один за другим в соседних строках, которые, будучи прочитаны сверху вниз, должны составлять десятичную запись числа ai. Над отрицательными числами должны быть знаки “-”. Дополнительное требование: Данное задание можно выполнять со следующим дополнительным условием: в формируемом текстовом файле должно быть минимально возможное количество пробелов (лишними могут считаться «хвостовые» пробелы в конце каждой строки). Другими словами, необходимо минимизировать размер получаемого файла.
41
Литература 1 Абрамов С. А. Задачи по программированию / С. А. Абрамов, Г. Г. Гнездилова, Е. Н. Капустина, М. И. Селюн. – М.: Наука, 1988. – 224 с. 2 Абрамов С. А. Начала информатики / С. А. Абрамов, Е. В. Зима. – М.: Наука, 1989. – 256 с. 3 Амелина Н. И. Задачи по программированию / Н. И. Амелина, Я. М. Демяненко, Е. Н. Лебединская и др. – М. Вузовская книга, 2000. – 104 с. 4 Йенсен К. Паскаль. Руководство пользователя и описание языка: пер. с англ. / К. Йенсен, Н. Вирт. – М.: Финансы и статистика, 1982. – 151 с. 5 Минакова
Н.
И.
Методы
программирования:
Учеб.
пособие
/
Н. И. Минакова, Е. С. Невская, Г. А. Угольницкий и др. – М.: Вузовская книга, 1999. – 280 с. 6 Пильщиков В. Н. Сборник упражнений по языку Паскаль: Учеб. пособие для вузов / В. Н. Пильщиков. – М.: Наука, 1989. – 160 с. 7 Поляков Д. Б. Программирование в среде Турбо Паскаль: Версия 5.5 / Д. Б. Поляков, И. Ю. Круглов. – М.: Изд-во МАИ, 1992. – 575 с. 8 Фаронов В. В. Турбо Паскаль 7.0. Начальный курс: учебное пособие / В. В. Фаронов. – М.: КНОРУС, 2006. – 576 с.
42