Полюбуйтесь, во что превратила эта программа один из файлов на Паскале (приведен небольшой фрагмент).
}"Rtqi2420rcu"
xct"Ocp"<"uvtkpi=
}///"░гьёднзпкз"▒т░шзжхтэ"///
rtqegfwtg"Rcwug=
dgikp
"""""Ytkvgnp*)Пвиокфз"Gpvgt<)+=""Tgcfnp=
Как говорится, родная мама не узнает! Все, что попадает в «мясорубку» нашего шифровальщика, обращается в фарш. Однако последующая расшифровка «перемолотого» файла в точности восстановила его.
Примененный нами метод шифрования не так уж крут, опытный взломщик легко раскроет его. Но фундамент заложен, и когда-нибудь вы придумаете изощренные методы шифрования. Например, ключ шифра можно сделать переменным и зависящим от номера символа в строке или файле. Подумайте над этим. Если же вы намерены заняться криптографией всерьез, изучайте математику! Для программиста это наука номер один.
Итоги• Для записи в текстовый файл, как и для чтения, требуется файловая переменная типа TEXT.
• Перед записью выполняют два действия: связывание переменной с файлом процедурой Assign и открытие файла для записи процедурой Rewrite.
• Вызов процедуры Rewrite либо создаёт новый файл, либо очищает существующий (вся бывшая в нём информация теряется!).
• Запись отдельных строк в файл выполняют процедурой Writeln, первым параметром здесь указывают файловую переменную.
• По окончании записи файл закрывают процедурой Close, – это гарантирует сохранение данных на диске.
А слабо?А) Программа создает файл, печатает в него несколько строк с числами, а затем выводит этот файл на экран. Воспользуйтесь одной файловой переменной.
Б) Программа для нумерации строк файла. Строки исходного файла должны копироваться в конечный файл с добавлением перед каждой строкой её номера, например:
Исходный файл:
В лесу родилась елочка,
В лесу она росла.
Зимой и летом стройная,
Зеленая была.
Конечный файл:
1
В лесу родилась елочка,
2
В лесу она росла.
3
Зимой и летом стройная,
4
Зеленая была.
В) Скопировать один файл в другой:
• с перестановкой местами четных и нечетных строк;
• с перестановкой строк в обратном порядке (см. условие задачи «Е» к 25-й главе).
Г) Для передачи по интернету секретного текстового файла разбейте его на два других: в первый запишите нечетные строки исходного файла, а во второй – четные. Напишите для этого программу, или слабо?
Д) Создайте программу для объединения двух файлов (см. условие предыдущей задачи). Из первого составьте нечетные строки конечного файла, а из второго – четные.
Глава 27Дайте кораблю минутный отдых!
Ой, что мы с вами натворили! Могучая программа шифрования файлов дает нам право если не на медаль, то хотя бы на передышку. Пощадим наши серые клеточки и отправимся на экскурсию по своему кораблю – среде программирования Free Pascal. Ведь мы обошли ещё не все палубы этого лайнера. Сейчас рассмотрим настройку компилятора, а в следующей главе обсудим возможности текстового редактора и справочной системы.
Ошибка ошибке розньГде найти безгрешных программистов? Нет таковых! Лихорадочно барабаня по клавишам в попытке изваять очередной проект, мы то и дело ошибаемся. Часть этих ошибок отлавливает компилятор, – он видит синтаксические ошибки – нарушения правил языка. Вы споткнулись на ключевом слове или забыли объявить переменную? – нажмите клавишу F9, и компилятор «ткнет носом» в место ошибки. И пока не исправите свои огрехи, не надейтесь получить исполняемый файл. Зато и работают такие программы, «непосильным трудом нажитые», весьма надежно. Восхищенный новичок однажды породил афоризм: «компилируется – значит работает». Увы! если бы так! Некоторые ошибки проявляются лишь во время работы программы, – это ошибки времени исполнения – Runtime errors.
Фатальные ошибкиДа, компилятор Паскаля способен уберечь от многих ошибок, но посмотрите на следующий пример.
var X : integer;
begin
Readln(X);
Writeln(100 div X);
end.
Программа печатает результат деления числа 100 на переменную X. Здесь нет синтаксических ошибок. И все работает прекрасно, пока пользователь не введет число ноль. Тогда вместо результата деления вы получите неприятное сообщение «Runtime error 200», и программа прервется. Иначе говоря, деление на ноль не позволено никому, даже компьютеру.
Выручит ли здесь компилятор? Ведь это логическая ошибка, то есть ошибка в алгоритме. Нет, тут поможет лишь исправление программы, например, так:
var X : integer;
begin
Readln(X);
if X<>0
then Writeln(100 div X)
else Writeln(’Не делите на ноль, умоляю Вас!’);
end.
Деление на ноль – это фатальная, то есть неисправимая ошибка, она приводит к аварийной остановке программы. Но случаются и ошибки иного рода.
«Простительные» ошибкиВот пример по части обработки файлов, – на этой «кухне» мы уже побывали. Попытка открыть для чтения несуществующий файл влечет ошибку вода/вывода (по-английски – «I/O Error»), – это тоже ошибка времени исполнения. Кто виноват? Разумеется, пользователь, – данные надо вводить внимательней. Но программе от этого не легче, – она обязана как-то реагировать. Как? Проще всего аварийно завершиться. Но можно поступить мягче – разобраться в ситуации и подсказать пользователю, где он неправ.
И здесь компилятор поддержит вас, позволив настроить реакцию программы на некоторые ошибки времени исполнения. По сути, способов реагировать только два: прервать программу при появлении ошибки, либо нет. Вариант реакции настраивают через опции компилятора. Рассмотрим выгоды такой настройки на примере ошибок ввода/вывода.
Опции компилятораОбратимся к настройкам компилятора. Щелкните по пункту меню Options –> Compiler… (рис. 60), и перед вами появится окно для настройки опций (рис. 61).
Рис.60 – Выбор пункта меню для настройки опций компилятора
Рис.61 – Окно настроек опций компилятораВкладка «Generation code» содержит нужную нам группу флажков «Code generation». Флажок «I/O checking» заведует реакцией программы на ошибки ввода-вывода («I/O» – это сокращение от Input/Output – «ввод/вывод»). При установленном флажке компилятор будет создавать исполняемые EXE–файлы так, что ошибки ввода-вывода аварийно завершат программу. А если сбросить флажок и снова откомпилировать ту же программу, она поведет себя иначе, – программа не погибнет, однако и работать, как следует, не будет. В чем же смысл настройки?
Обработка ошибок ввода-выводаСмысл в том, чтобы самому следить за вероятными ошибками. Для слежки используют функцию IOResult, которая не имеет параметров и возвращает ноль, если ошибок ввода-вывода не произошло. А если эта неприятность все же случилась, функция вернет ненулевой код ошибки, по которому легко выяснить её причину. Обратите внимание: функция возвращает состояние последней выполнявшейся операции ввода-вывода. При ошибке дальнейшая работа с файлом автоматически блокируется до его повторного открытия.
Рассмотрим способ безаварийного определения наличия файла на диске (здесь имя файла содержится в переменной FileName).
Assign(F, FileName); Reset(F);
if IOResult=0
then Writeln (’Нашелся файл ’+ FileName)
else Writeln (’Файл ’+FileName+’ не обнаружен!’);
Этот фрагмент надёжно сработает только при отключенном флажке «I/O checking», иначе программа может прерваться аварийно. Стало быть, перед компиляцией надо проверять состояние флажка, а это хлопотно и ненадежно.
В настройках опций компилятора через меню есть и другой изъян. Как быть, когда в разных местах программы требуется по-разному реагировать на ошибки: где-то включить этот контроль, а где-то нет? Но флажок действует на всю программу в целом, глобально, – он не допускает выборочной настройки. Что делать?