Здравствуйте, уважаемые
подписчики!
Это письмо желательно читать в броузере
или развернуть на весь экран, тогда легче ориентироваться и приятнее
читать!
Юбилей. Нам с вами уже двадцать выпусков! Много или мало?
Это решать вам. Я же со своей стороны постараюсь подвести
итоги выполненной работы, при этом немножко заглянуть в
будущее. Итак, чему же мы научились за двадцать выпусков?
А научились мы довольно многому. Пусть даже и не прошли
всю теоретическую часть Паскаля, зато написали уже довольно
много программ, а также на 90% прошли HTML. С полной уверенностью
могу сказать, что та часть гипертекстового языка, которую
мы завершили, позволит вам самостоятельно выполнить любой
сайт, который вам придет в голову. За исключением Cgi и
Dhtml, конечно, а также некоторых, связанных с этими технологиями
инструментов - будь то заполняемые формы или элементы Java
Script. Все это - еще впереди, в самом ближайшем будущем.
Паскаль. Что вы сейчас сможете написать на Паскале? В
принципе, решить любую математическую или физическую задачу,
работать с массивами, записями, создавать собственные процедуры.
Хотя в этом плане мы затронули только вершину айсберга,
этой огромной глыбы под названием программирование.
Узнали немало, предстоит еще больше. Для начала, мы должны
будем научиться работать с внешними файлами и добить типы
данных. На это все уйдет не более двух-трех выпусков, которые
я сейчас постараюсь делать как можно более частыми.
Далее - перейдем к динамических структурам данных, которые
уже применяются в более продвинутом программировании. Затем
начнем шагать по таким аспектам программирования как работа
с графикой и системными средствами компьютера. Займемся
объектно-ориентированным программированием, напоследок переключившись
на искуственный интеллект. Здесь смоделируем несколько примитивов,
которые будут прототипами реального интеллекта, наподобие
поведения мухи или таракана :)), если дело пойдет без особых
затруднений, создадим небольшой движок с несколькими объектами,
которые будут генериться в реальном времени и уже кой-чего
соображать :))
В общем, по ходу изучения Паскаля познакомимся с самыми
наинтереснейшими аспектами программирования. Заглянем внутрь,
так сказать.
Что дальше? Лично я считаю, что немаловажным шагом на
пути начинающего программиста является переход от DOS к
Windows. Здесь открываются новые горизонты программирования.
Ну а дальше... дальше будет не то, чтобы скоро :)) там и
будет видно. Я имею некоторые планы, но не знаю, как пойдет
дело - если все сложиться удачно, то мы сможем узнать и
основить очень много интересных вещей.
Думаю, общая картина ясна. Теперь хотелось бы отметить
новые планы, которые у меня образовались во время своего
непредвиденного отпуска. Сразу скажу, что в эти планы входит
ваше самое активное участие в проекте, и не только в работе
над сайтом Клуба, но и над рассылкой. Что же это за участие?
Рассказываю по порядку.
Самое главное что отличает рассылку от обычной книги -
это интерактивность. То есть читая рассылку вы получаете
авторский материал, который составляется с учетом ваших
же пожеланий и предложений. Далее - вы можете задать вопрос
непосредственно автору материала, чот тоже немаловажно.
При этом чем выше интерактивность, тем лучше и интереснее
выходит наше с вами общение. В идеале вам было бы гораздо
интереснее учавствовать в процессе не только в качестве
вопрошающего, но и в качестве соавтора. К примеру, вы не
понимали какую-то вещь - пусть это будет сортировка массива
методом пузырька. Не понимали долго и интенсивно разбирались.
В итоге собрали материал, выполнили злополучную сортировку
и разом все прояснилось. Задумайтесь - ваш уровень мгновенно
повысился, у вас появилась интересная авторская информация,
которой вы можете поделиться с народом, причем не просто
с группой человек, а даже с небольшим городком - с более
чем 20000 жителей нашей рассылки. Разве вам это не интересно?
Что для этого нужно? Все очень просто и достаточно изложить
свой материал в электронном виде и предоставить на всеобщее
обозрение.
ВСЕ! Вы уже участник проекта и соавтор нашего интерактивного
процесса обучения. А проблемы типа приведенной мной сортировки
массива возникают у всех - и не только на Паскале, а и на
Си, и на Ассемблере, и в работе с Windows, в установке и
настройке Linux, в создании сайта.
Собственно говоря, в этом и состоит цель проекта. Объединение
авторских материалов для того, чтобы каждый мог найти решение
своих проблем. Создание интерактивных справочников и учебников,
возможно, внедрение дополнительных курсов по другим языкам
и системам программирования. Создание интерактивной системы
помощи Консультант, в развитии которой вышла задержка,
кстати, из-за тех же проблем с монитором.
Когда мне пишут новички с вопросом "как мне можно принять
участие в создании клуба" и я им отвечаю "изложите что-нибудь
полезное для других, поделитесь опытом", за этим обычно
следует сообщение "а я ничего не знаю... у меня-то и опыта
нет...". Так вот, дорогие друзья, всем вышеизложенным материалом
я хочу доказать, что не существует людей, у которых нет
опыта или совершенно ничего не знающих. Если ничего не приходит
в голову, вы не решаете никаких проблем - так начинайте!
Задумайтесь, а что вас интересует? Вот кому, например, не
интересно, как работает архиватор ZIP или каким образом
можно программно открыть дверцу CD-ROM'а? А нарисовать свое
имя в трехмерном простанстве, крутящимся вокруг какой-нибудь
из осей?
В общем, призываю всех (!) к участию, ваши мысли и решение
проблем, изложенных с виде электронной статьи увидят десятки
тысяч людей! Глядишь, среди них пару тысяч найдут решение
среди предоставленных материалов :))
Лично я постараюсь приложить все усилия по объединению
и публикации вашего материала в рассылке и на сайте, для
чего будут открываться новые разделы и пополняться имеющиеся.
Насколько мне известно, таких проектов в Сети насегодня
не существует. И самая главная причина, на мой взгляд, это
отсутсвие достаточно большой группы людей, которые, объединившись,
смогут создать такой Клуб. Надеюсь, у нас получиться команда,
главное - чтобы кому-то это было интересно и возникало желение
учавствовать в проекте. Пишите!
Немножко позже я еще напишу о том, что уже сделано и о
других аспеках развития Клуба. Будьте уверены, вас ждет
много интересной информации!
Наконец-то! Возвращаемся к нашему Паскалю. Теперь, после
столь продолжительного отпуска необходимо наверстывать упущенное
и как можно усиленнее заниматься. Если вы помните, в прошлом
выпуске мы с вами начали писать программу, которая и должна
была стать основопологающей в наших дальнейших действиях.
Программа называлась "Записная книжка", манипулировала с
типом record и еще содержала маленькую ошибочку,
которую, кстати, многие заметили.
Обратите внимание на этот код:
......
C := ReadKey;
case C of
'1'..'9': begin
Val(C, I, Code);
List_Item(I);
end;
'a': New_Item;
#27: Quit := true;
end;
......
|
В этом вся собака зарыта. Дело в том, что в условии упоминается
о работе с 10-ю записями, а этот алгоритм позволяет использовать
всего девять, так как вообще не умеет читать двухзначные
числа. Как решить этот вопрос - Ваша задача! Программирование
вообще без задач, которые нужно решать, не обходиться...
Ну а мы интенсивно двигаемся дальше. Сегодня - как и
было обещано, файлы. Пока только теория, которую вам нужно
усвоить (ее довольно много), практика будет в следующем
выпуске.
В паскале работа с файлами осуществляется через специальные
типы, доселе нам не известные. Это файловые типы, которые
определяют тип файла, то есть фактически указывают его
содержимое. С помощью этой переменной, которой присвоен
необходимый тип, и осуществляется вся работа с файлами
- открытие, запись, чтение, закрытие и т.п.
При работе с файлами существует определенный порядок
дейтвий, которого необходимо придерживаться. Вот все эти
действия:
- Создание (описание) файловой переменной;
- Связывание этой переменной с конкретным файлом на
диске или с устройством ввода-вывода (экран, клавиатура,
принтер и т.п.);
- Открытие файла для записи либо чтения;
- Действия с файлом: чтение либо запись;
- Закрытие файла.
Первое, на что хочу обратить внимание, это возможность связать
файловую переменную не только с физическим файлом на носителе
информации, но и с устройством. В качестве такового используются
обычные псевдонимы устройств DOS. Вот основные два:
- CON - консоль (экран-клавиатура), то есть по
записи в это устройство мы будем получать информацию
на экран, при чтении информации из этого устройства,
будем читать данные с клавиатуры.
- PRN - принтер. При записи в это устройство
вы получите информацию на принтер.
Далее хочу обратить внимание на последний этап - закрытие
файла. В принципе, не обязательное условие для файлов, из
которых мы читаем данные. Если не закроем - ошибки это не
вызовет, последствий тоже. Однако обязательно закрывать
файл, если мы осуществляли в него запись. Дело в том, что
если мы пишем данные в файл на диске и забываем его закрыть
- информация не сохраниться. Она (информация) помещается
во временный буфер, который запишется на диск только при
закрытии файла.
Перед тем, как начинать работу с файлами, давайте посмотрим,
какие существуют переменные для работы с ними. В Turbo
Pascal имеется три типа таких переменных, которые определяют
тип файла. Вот эти типы:
- Text - текстовый файл. Из переменной такого типа
мы сможем читать строки и символы.
- File of _любой_тип_ - так называемые "типизированные"
файлы, то есть файлы, имеющие тип. Этот тип определяет,
какого рода информация содержится в файле и задается в
переметре _любой_тип_. К примеру, если мы напишем так:
F: File of Integer;
То Паскаль будет считать, что файл F содержит числа
типа Integer; Соответсвенно, читать из такого файла
мы сможем только переменные типа Integer, ровно как
и писать. Напишем так:
type
A = record
- I,J: Integer;
- S: String[20];
end;
var
- F: File of A;
То получим очень интересную картину, когда файл содержит
в качестве элементов записи. Мы сможем их читать, писать
и производить с ними действия. Именно этим мы и займемся
в процессе модификации нашей программы "Записная книжка".
- File - нетипизированный файл. Когда мы указываем
в качестве типа файла просто File, то есть без типа:
F: File;
То получаем "нетипизированный" файл, чтение и запись в который
отличается от работы с файлами других типов. Эти действия
производятся путем указания количества байт, которые нужно
прочитать, а также указанием области памяти, в которую нужно
прочитать эти данные. Это тема будущих выпусков.
Итак, разобрались с типами файлов. Теперь давайте по порядку
разбирать действия, применяемые для работы с файлами. Я
говорил о них выше.
Связывание переменной с файлом |
Самый универсальный шаг. Выполняется одной и той же процедурой
для всех типов файлов, а именно процедурой Assign:
Assign(_переменная_файлового_типа_,
'путь к файлу');
Как видите, в качестве параметров задаются переменная либого
файлового типа и строка - путь к файлу, который, по правилам
DOS, не может быть длиннее 79 символов. Вот пример использования
assign:
var
T: Text;
F1: File of Byte;
F2: File;
begin
Assign(T, '1.txt');
Assign(F1, 'C:\Programm\Tp\2.txt');
Assign(F2, 'F:\usr\bin\apache\conf\httpd~1.con');
..........
|
Как видите, это очень просто и сама процедура Assign
проблем не вызывает. Давайте теперь рассмотрим следующий
этап.
Открытие файла - это уже более усложненный процесс, нежели
связывание с ним переменной. Здесь учитывается, зачем открывается
файл - для записи или чтения, а также в зависимости от типа
файла процедуры выполняют различные действия.
Тем не менее этот процесс не сложен и заключается в использовании
одной из трех имеющихся процедур:
- Reset(_любая_файловая_переменная_);
Открыват файл на чтение. В качестве параметра - файловая
переменная любого из перечисленных выше типов. Это может
быть текстовый, типизированный либо не типизированный
файл. В случае с текстовым файлом, он открывается только
на чтение. В случае с типизированным и нетипизированным
файлом - он открывается на чтение и запись.
- Append(T: Text);
Эта процедура открывает текстовый файл (только текстовый!)
на запись. Выше я сказал, что Reset при задании
параметра типа Text не позволит писать в него данные,
открыв файл лишь для чтения. То есть если вы используете
текстовый файл и хотите производить в него запись, нужнo
использовать Append. Если чтение - Reset.
В остальных случаях дело обходиться одной процедурой Reset.
Также обратите внимание, что если вы до этого уже открыли
файл на чтение, вам не нужно закрывать его и открывать
снова на запись. В этом случае файл закрывается сам и
открывается заново. При записи данных в файл при открытии
его с помощью этой процедуры они записываются в конец
файла.
- ReWrite(F) - создает новый файл либо перезаписывает
существующий. Будьте осторожны, если не хотите случайно
удалить нужный файл. Напомню, файл, открытый с помощью
этой процедуры будет полностью перезаписан.
В использовании процедур, думаю, проблем не будет. Однако
возникает другой вопрос - что, если файла, который открыватся,
нет? Если он не существует на диске, то как мы сможем из него
читать информацию? Программа выбъет ошибку в такой ситуации.
Это реальная проблема, которая, кстати, очень просто решается.
Способ проверки заключается в двух этапах: использовании
ключей компилятора и функции IOResult, которая возвращает
значение от только что выполненной операции ввода-вывода.
С функцией разберемся быстро, а вот с такой штукой как ключи
компилятора мы еще не сталкивались, поэтому остановимся
подробнее.
Ключи компилятора - это обыкновенные переключатели,
которые контролируют ход выполнения программы исключая или
включая реакцию на какие-нибудь условия. В нашем случае
нас интересует условие, когда физически отсутсвует нужный
нам файл, либо не удалось открыть его по другим причинам.
Ключей у Паскаля довольно много, мы пока изучим один, необходимый
нам на данный момент.
Оформляются ключи следующим образом: в скобках комментариев
"{}" первым символом после открывающей скобки "{" ставиться
знак доллара "$", после чего указывается имя ключа и его
значение. Нас интесует ключ, который выключает вывод ошибок
ввода-вывода, называется он "I". Выглядит все это
следующим образом:
{$I+} - включение вывода ошибок
{$I-} - выключение вывода ошибок
По сути дела осутствие файла - это ошибка, которая возвращается
функцией IOResult. Если же эта функция возвращает 0,
то файл успешно открыт, без ошибок. Вот и вырисовывается последовательность
действий, необходимых для проверки на наличие файла:
- Связываем переменную с файлом;
- Выключаем вывод ошибок на экран - {$I-}
- Окрываем файл необходимой нам процедурой;
- Включаем вывод ошибок {$I+} - пусть будет для
дальнейшего отслеживания таковых;
- Проверяем, если IOResult возвращает нуль, то
все было путем и файл открыт. Иначе выводим ошибку.
Вот пример такой программы:
var
T: Text;
S: String;
begin
Write('Enter filename: ');
Readln(S);
Assign(T, S);
{$I-}
Reset(T); { открываем файл для чтения }
{$I+}
if IOResult <> 0 then { если не нуль, то была ошибка }
begin
Write('Error when open file!');
Halt;
end;
{ иначе все в порядке, продолжаем }
..........
end.
|
Выше я говорил о том, зачем нужно закрывать файл и когда
надо это делать. Закрытие файла производиться с помощью
процедуры Close(F), где F - это переменная файлового
типа. Эта процедура одна для всех типов файлов.
Запись и чтение файлов, часть I. |
Сегодня я хочу рассказать о записи и чтении текствых и
типизированных файлов, в следующем выпуске рассказ пойдет
о чтении файлов без типа. Итак, переходим к непосредственной
обработке файловой информации.
Чтение файлов. Чтение файлов производится с помощью
отлично известных нам процедур Read и Readln.
Они используются также, как и при чтении информации с клавитуры.
Отличие лишь в том, что перед переменной, в которую помещается
считанное значение, указывается переменная файлового типа
(дескриптор файла):
Read(F, C);
Здесь F - дескриптор файла, C - переменная (Char, String
- для текстовых, любого типа - для типизированных файлов).
Также сразу хочу упомянуть о одной, пожалуй самой главной
функции при чтении файлов. Это функция поверки на конец
файла - Eof(F): Boolean;. В качестве параметра -
файловая переменная любого типа. Функция возвращает TRUE
если достигнут конец файла и FALSE иначе.
Здесь все очень просто, демонстрации ради давайте напишем
небольшую программку. Пусть имеем текстовый файл. Давайте
его распечатаем и заодно посчитаем, например, количество
пробелов:
var
T: Text;
С: Char;
Spaces: Word;
S: String[79]; { 79-макс. длина пути в DOS }
begin
Write('Enter filename: ');
Readln(S);
Assign(T, S);
{ открываем файл для чтения }
{$I-}
Reset(T);
{$I+}
{ если не нуль, то была ошибка }
if IOResult <> 0 then
begin
Write('Error when open file ', S, ' !');
Halt;
end;
{ иначе все в порядке, продолжаем }
{ ЦИКЛ: пока НЕ КОНЕЦ ФАЙЛА }
While (not Eof(T)) do
begin
{ читаем из файла переменную }
Read(T, C);
{ если пробел, увеличиваем счетчик }
If C = ' ' then Inc(Spaces);
Write(C);
end;
Writeln('КОЛИЧЕСТВО ПРОБЕЛОВ: ', Spaces);
Readln;
end.
|
Думаю, здесь все ясно. Продолжаем двагаться дальше и посмотрим,
как производиться запись в файлы.
Запись в файлы. Вы еще не догадались? Запись в файлы
производиться точно так же, как и запись на экран - с помощью
процедур Write и Writeln. Как и в случае с
чтением, перед записываемой в файл переменной указывается
тескриптор файла:
Write(F, S);
Здесь F - дескриптор, S - переменная.
При этом, естественно, переменная должна соответсвовать
типу файла. Примера ради давайте составим еще одну небольшую
программку, которая покажет работу с файлами. На сей раз
уже используем типизированные файлы, а имеено состоящие
из чисел. Итак, мы имеем файл, в котором содержаться числа
типа Integer. Давайте отсортируем эти числа в файле
по возрастанию.
План дейтсвий:
- Отрываем типизированный файл из Integer; (проверяем
на ошибку и т.п.)
- Читаем все числа в массив (считываем, пока не конец
файла)
- Сортируем массив по возрастанию;
- Записываем отсортированный массив обратно в файл.
Получается такая программа:
Program Sorting;
uses Crt;
var
F: File of Integer;
I, J, M: Word;
Mas: Array[1..500] of Integer;
S: String;
begin
ClrScr;
Write('Enter filename: ');
Readln(S);
{ открываем файл }
Assign(F, S);
{$I-}
Reset(F);
{$I+}
if IOResult <> 0 then
begin
Write('Error when open file!');
Halt;
end;
{ пока не конец файла, читаем массив }
While (not Eof(F)) do
begin
Inc(M);
Read(F, Mas[M]);
Write(Mas[M], ' ');
end;
{ сортируем массив по возрастанию }
For I := 1 to M do
For j := 1 to M do
if Mas[I] < Mas[J] then
begin
inc(mas[j], mas[i]);
mas[i] := mas[j]-mas[i];
dec(mas[j], mas[i]);
end;
Writeln; Writeln('=============================================');
{ перезаписываем файл }
ReWrite(F);
For I := 1 to 100 do
begin
Write(Mas[I], ' ');
Write(F, Mas[i]);
end;
Writeln; Write('Elements in file: ', M);
Close(F);
Readln;
end.
|
Программа очень проста и хорошо демонстрирует работу с
типизированными файлами. В качестве сортировки массива я
использую метод пузырька, чтобы перезаписать файл использую
ReWrite. Вроде не должно возникать никаких сложностей...
Будут проблемы, пишите.
Ну а на сегодня, пожалуй, все. Этой информации вам будет
достаточно, в следующем выпуске займемся, как я уже сказал,
нетипизированными файлами и продолжим писать программу "Записная
книжка".
До встречи!
|
|
|