Модуль (unit) на паскале

Был у меня блог на av-school.ru, который в скором времени, возможно, прекратит свое существование, поэтому я перенесу некоторые полезные посты из того блога в этот.

Задача на паскале была такая:

Написать модуль, подключение которого позволяло бы вставлять\удалять символ в любом месте строки, по указателю, заданному пользователем.

при этом дополнительные условия:

1. Нельзя использовать глобальные переменные
2. Необходимо реализовать модель + демонстрационную программу
3. Демка должна иметь удобный интерфейс.
4. Обязательно оформлять отдельные операции в процедуры\функции
5. Исходные данные берутся из input.txt
6. Результаты работы сохраняются в Output.txt

Решение:

Для начала нужно проставить подзадачи.

1. Забить все процедуры в модуль
2. Написать функцию\процедуру для удаления символов из строки
3. Написать функцию\процедуру для добавления символов в строку
4. Сделать демку

Второй шаг — построение алгоритма. И не обязательно оформлять это красиво в блок-схему, как везде учат. Я, конечно, еще не столь опытен, что бы судить, но мне оформление в виде блок-схемы неудобно, это просто долго. А алгоритм для понимания лучше сделать. Я для себя решил проблему так: беру листик с бумагой и начинаю писать. Просто последовательности-что за чем следует — без ветвлений и красивого оформления циклов.

Алгоритм, который я написал первоначально на листике был таким (Орфография сохранена):

1. Открытие
2. Чтение в STR
РАБОТА СО СТРОКОЙ
1. Измерение длины строки
2. Получение информации для вставки в строку
3. Получение указателя (Число — куда вставлять)
4. Пробежка по строке. Встаем в то место, где нужно вставить.
5. Копирование всего, что есть в строке после этого символа в Str2
6. Срезка строки
7. Вставляем символ
8. Вставляем из Str2 в Str
РАБОТА С ФАЙЛАМИ
1. Запись строки в выходной файл
2. Закрытие файла

То есть, мы получаем информацию из файла —> преобразуем эту информацию в строку и работаем уже с ней —> записываем ее в файл.

Кодинг:

Начнем с открытия файла.


Procedure OpenFile(var f:text);
var
err: integer;
str: string;
begin
repeat
Write ('Введите имя файла : ');
Readln (str);
Assign (F, str);
{$I-}
Reset(F);
err := IOResult;
if err<>0 then
begin
writeln('файла  ',str,' ­не существует.');
end;
{$I+}
until (err=0) and (length(str)>0);
end;

В Var находятся 2 переменные:

Err — переменная для хранения информации об ошибке. Ее код.
Str — строка, содержащие имя файла

Попадая в тело процедуры, сразу направляемся в цикл, который будет выполняться , пока не откроется файл (IO код будет равен 0) и Длина имени файла будет больше нуля, или попросту будет подано имя файла.

Внутри цикла:

Write (‘Введите имя файла : ‘); \\ Вывод подскаски для пользователя — что от него хочет программа =)
Readln (str); \\ Чтение введеной пользователем строки в переменную str (тип : String)
Assign (F, str); \\ Связка текстовой переменной f (F: text — как входной параметр для функции) с файлом , имя которого написано в str.
{$I-} и {$I+} \\ включение обработки исключительных ситуаций dos.
Reset(F); \\ Открытие файла на чтение
err := IOResult; \\ переменной для ошибок присваиваем значение системной переменной IOResult переменной для ошибок. Это рекомендуется делать, так как значение IOResult будет сменено при следующей операции с файлом. Если все в порядке — она вернет 0. Любые другие значения — это ошибки работы с файлами.
if err<>0 then \\ Если код err неравен 0, тогда…
writeln(‘файла ‘,str,’ ­не существует.’); \\ …вывести на экран строку «Файла <имя файла> не существует»

После открытия файла неплохо бы что-то с ним сделать. А в нашем случае это вставка и удаление.

Рассмотрим процедуру вставки в строку:


Procedure IncludeString(var f:text);
var
str, str2, includ, str3: string;
len, place: word;
begin
Reset (f);
Read (f, str);
len := length(str);
Writeln ('введите добавляемые символ(ы): ');
Readln (includ);
Writeln ('Место указателя');
Readln (place);
if place > len then
Writeln('За пределами файла');
str2 := copy(str, place, (len - place)+1);
Delete(str,place,(len - place)+1);
str3 := (str + includ+ str2);
Rewrite (f);
Writeln (f,Str3);
close (f);
end;

в блоке переменных 4 переменных строкового типа, а так же 2 типа Word, этот тип целесообразно использовать при работе со строками, так как максимальная длина строки 255 символов, этот тип ее полностью покрывает.

Reset (f); \\ открытие файла на чтение
Read (f, str); \\ чтение в строку str
len := length(str); \\ получение длинны строки и помещение значения в переменную len
Writeln (‘введите добавляемые символ(ы): ‘); \\ вывод текста на экран
Readln (includ); \\ чтение информации с клавиатуры в строковую переменную include. Это будет наша подстрока для вставки
Writeln (‘Место указателя’); \\ снова вывод текста
Readln (place); \\ чтение с клавиатуры в переменную численного типа

if place > len then \\ проверка вхождения указателя в пределы файла, если True, тогда
Writeln(‘За пределами файла’); \\ указатель не входит в границы файла. выводим текст.

str2 := copy(str, place, (len — place)+1); \\ Копирование подстроки в переменную str2.

Параметры:

первый = str = с какой строкой работаем
второй = pleaсe = откуда начинаем копирование
тетий = (Len -pleace) +1 = сколько символов копируем.

Delete(str,place,(len — place)+1); \\ после этого строка затирается. параметры те же.
str3 := (str + includ+ str2); \\ «склеиваем» строки
Rewrite (f); \\ открываем файл на перезапись
Writeln (f,Str3); \\ записываем новую строку
close (f); \\ закрываем файл

Процедура для удаления символа:


Procedure DelChar(var f:text);
var
str: string;
len, place: word;
begin
Reset (f);
Read (f, str);
len := length (str);
Writeln('Место указателя');
Readln (place);
if place > len then Writeln('за пределами файла');
Delete (str, place, 1);
Rewrite (f);
Writeln (f,Str);
close (f);
end;

Строк здесь меньше — всего одна, а так же еще 2 переменные для хранения длины строки и указателя.

Reset (f); \\ открытие на чтение
Read (f, str); \\ чтение в строку
len := length (str); \\ получение длины строки и запись значения в переменную len
Writeln(‘Место указателя’); \\ вывод текста
Readln (place); \\ чтение информации от пользователя
if place > len then Writeln(‘за пределами файла’); \\ поверка вхождения указателя в границы файла
Delete (str, place, 1); \\ удаление из строки str, начиная с места Pleace одного символа
Rewrite (f); \\ открытия файла на перезапись
Writeln (f,Str); \\ запись в файл
close (f); \\ закрытие файла

после написания этих функций (а функции добавления и удаления я делал в программах) было проведено несколько тестов, что бы все работало.
Результат — все в порядке.

Оформляем модуль.

синтаксис:


Unit <Имя модуля>;

Interface

Uses  <модули>

<перечисления имен процедур\функций с параметрами>

Implementation

<полное описание процедур и функций>

end.

В итоге получается такой модуль:


Unit Module6;

Interface

Uses
crt;

Procedure OpenFile(var f:text);

Procedure IncludeString(var f:text);

Procedure DelChar(var f:text);

Implementation

Procedure OpenFile(var f:text);
var
err: integer;
str: string;
begin
repeat
Write ('‚ўҐ¤ЁвҐ Ё¬п д ©« : ');
Readln (str);
Assign (F, str);
{$I-}
Reset(F);
err := IOResult;
if err<>0 then
begin
writeln('” ©«  ',str,' ­Ґ бгйҐбвўгҐв.');
end;
{$I+}
until (err=0) and (length(str)>0);
end;

Procedure IncludeString(var f:text);
var
str, str2, includ, str3: string;
len, place: word;
begin
Reset (f);
Read (f, str);
len := length(str);
Writeln ('‚ўҐ¤ЁвҐ ¤®Ў ў«пҐ¬лҐ бЁ¬ў®«(л): ');
Readln (includ);
Writeln ('ЊҐбв® гЄ § вҐ«п');
Readln (place);
if place > len then
Writeln('‡  ЇаҐ¤Ґ« ¬Ё д ©« ');
str2 := copy(str, place, (len - place)+1);
Delete(str,place,(len - place)+1);
str3 := (str + includ+ str2);
Rewrite (f);
Writeln (f,Str3);
close (f);
end;

Procedure DelChar(var f:text);
var
str: string;
len, place: word;
begin
Reset (f);
Read (f, str);
len := length (str);
Writeln('ЊҐбв® гЄ § вҐ«п');
Readln (place);
if place > len then Writeln('‡  ЇаҐ¤Ґ« ¬Ё д ©« ');
Delete (str, place, 1);
Rewrite (f);
Writeln (f,Str);
close (f);
end;

end.

Замечание: За непонятные символы при выводе на консоль простите, это так русский текст копировался из IDE.

Остается написать тестовую программу. Вот ее код:


Program work6;

Uses
Module6,crt;
var
f:text;
C:char;
begin
Openfile(f);
Repeat
clrscr;
Writeln ('A - Вставить символ / D - удалить символ / Esc - выход');
C := Readkey;
case Ord(C) of
65,97: IncludeString(f);
68,100: DelChar (f);
end;
until

Ord(C) = 27;

End.

в блоке Uses подключены 2 модуля — штатный crt и наш новонаписанный module6
Здесь, к счастью, можно использовать переменные глобального типа. у нас их 2.
F: Text = хранит файл (точнее указание на него)
C: Char = Хранит код клавиши нажатой клавиши.

Все делается в цикле — чтобы можно было делать несколько попыток. Выход из цикла = клавише номер 27, по коду ASCII это esc.

на первом этапе вызывается процедура открытия файла.
clrscr; \\ очистка экрана
Writeln (‘A — Вставить символ / D — удалить символ / Esc — выход’); \\ вывод подсказки
и дальше многоальтернативный выбор. Оператор Case.

Если пользователь нажал A или a (коды : 65 или 97) то выполнить функцию IncludeString(f);
Если пользователь нажал D или d (коды : 68 или 100) то выполнить функцию DelChar (f);
Если был нажат esc (27) выйти из программы.

1 Response

Добавить комментарий