| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Статья написана для людей которые программируют
изредка. Для души так сказать.
Одна из относительно старых моих наработок в программирование. Программа
выводящая свой исходник. Некоторые считают, что такую написать нельзя. Я знаю
по крайней мере два способа. Первый - мой, который приведён здесь. Есть ещё
один способ - он более подробно описан в moon_bug в 6 или 7 номере.
Тема: Написание программы выводящей свой исходный текст.
Собственно статья ниже.
Автор: p0st[[email protected]]
1. Введение.
2. Алгоритм работы программы.
3. Собственно написание.
4. Напоследок.
5. Прикрёплен мой листинг.
Введение:
Иногда нужно написать программу, выводящую свой листинг. Часто такие (или
похожие) задачи бывают на различных конкурсах, соревнованиях и т.д. Часто
встречая такие задачи в различных задачниках по программированию (в учебниках
по нему же они встречаются, что-то заметно реже :)). Бывает не сразу понятно
как подступиться к такой задаче. Я расскажу алгоритм, по которому можно самому
написать программу выводящую свой листинг. Пример для Turbo Pascal 7.0 (delphi
должен открыть как консольное приложение и всё будет работать). Вывод
осуществляется в стандартный поток output.
Алгоритм работы программы:
Будем использовать следующий метод: в программе объявлена константа как массив
типа string. В нём будет храниться код программы. Тогда нам для вывода
исходника потребуется вывести константу и потом сделать тоже самое ещё раз.
При выводе константы будут небольшие трудности, но с ними легко справиться по
ходу написания.
Собственно написание:
Сначала примерный текст того, что должно быть(потом доредактируем по написанию,
исправим ошибки какие будут. Сейчас главное накидать основу):
--------------------------------Start---------------------------------
program outsource;
const
N=15;{Примерное количество строчек. потом исправим на какое надо}
mas:array[-3..N]of string=(
'program outsource;',{Массив объёвлен с отрицательными индексирование для
более удобного использования по тексту}
'const',
'N=15;',
'mas:array[-1..N]of string=(',
{Здесь будут ещё строки всего пока N+4 строк, можно пока встывить пустышки.
Мне лень.}
);
var
i:integer;
begin
for i:=-3 to 0 do {Выводим то что перед константой}
writeln(mas[i]);
for i:=-3 to N do
writeln(#39,mas[i],#39,#44);
{Выводим саму константу, кавычки при выводе использовать не рекоменуеться
так как будут проблемы для вывода формирования того же в константе}
writeln(#39,mas[N],#39);{Вывод последней строки константы без запятой}
writeln(#41,#59);{Конец константы}
for i:=1 to N-1 do {Выводим сам текст программы}
writeln(mas[i]);
writeln(mas[N],#46); {И end с точкой в конце}
end.
--------------------------------End-----------------------------------
Далее требуется перенести весь получившийся исходник в константу.
Получившаяся константа должна иметь вид примерно следующий:
--------------------------------Start---------------------------------
mas:array[-3..N]of string=(
'program outsource;',
'const',
'N=13;',
'mas:array[-3..N]of string=(',
'var',
'i:integer;',
'begin',
'for i:=-3 to 0 do',
'writeln(mas[i]);',
'for i:=-3 to N-1 do',
'writeln(#39,mas[i],#39,#44);',
'writeln(#39,mas[N],#39);',
'writeln(#41,#59);',
'for i:=1 to N-1 do',
'writeln(mas[i]);',
'writeln(mas[N],#46);',
'end'
);
--------------------------------End-----------------------------------
Теперь объединяем куски в одну программы. Проверяем ,чтобы в константе было
нужное число строчек и всё в таком духе.
Проверяем(1.pas - наша программа, запускать из каталога, в котором tpc):
tpc.exe 1.pas
1.exe > 2.pas
tpc.exe 2.pas
2.exe > 3.pas
fc 2.pas 3.pas
Напоследок:
Если получаем что ошибок не найдено то всё хорошо, иначе смотрим получившийся
исходник, находим разницу и правим по месту. Идея решения была объяснена в
самом начале статьи. Сравнивать вывод программы надо не с первоначальным
исходником (в котором могут быть комментарии и другие вещи для понимания
решения) , а с тем что получиться в конечном итоге.
p.s. Для заинтересовавшихся - можно попробовать вывод в файл. Создаёт небольшие
проблемы, но помогает лучше разобраться в принципе работы программы.
p.p.s. Используя этот же алгоритм мы можем написать программу выводящую свой
листинг на любом (ну почти на любом) языке программирования. У меня есть
реализация на ассемблере :).
Приложение 1.pas(с моими коментариями):
(*--------------------------Start-----------------------------------*)
program outsource;
const
N=13;{Количество строчек в константе.}
mas:array[-3..N]of string=(
'program outsource;',{Массив объёвлен с отрицательными индексирование
для более удобного использования по тексту}
'const',
'N=13;',
'mas:array[-3..N]of string=(',
'var',
'i:integer;',
'begin',
'for i:=-3 to 0 do',
'writeln(mas[i]);',
'for i:=-3 to N-1 do',
'writeln(#39,mas[i],#39,#44);',
'writeln(#39,mas[N],#39);',
'writeln(#41,#59);',
'for i:=1 to N-1 do',
'writeln(mas[i]);',
'writeln(mas[N],#46);',
'end'
);
var
i:integer;
begin
for i:=-3 to 0 do {Выводим то что перед константой}
writeln(mas[i]);
for i:=-3 to N-1 do
writeln(#39,mas[i],#39,#44);
{Выводим саму константу, кавычки при выводе использовать не рекоменуеться
так как будут проблемы для вывода формирования того же в константе
#39 - кавычка "'" #44 - запятая ","}
writeln(#39,mas[N],#39);{Вывод последней строки константы без запятой}
writeln(#41,#59); {Конец константы #41 - скобка ")", #59 - ";"}
for i:=1 to N-1 do {Выводим сам текст программы}
writeln(mas[i]);
writeln(mas[N],#46); {И "end" с точкой в конце }
end.
(*--------------------------End-------------------------------------*)
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |