
Информатика
.pdf
61
элементы матрицы системы, делятся соответствующие уравнения на эти элементы (вместе с правой частью) и, далее, эти уравнения (теперь уже с единичным элементом на диагонали) вычитаются из других уравнений с тем, чтобы в соответствующих столбцах получились нули. В результате матрица системы уравнений становится единичной, а правая часть содержит решение. Алгоритм в таком простейшем виде содержит два "подводных камня". Первый – на диагонали в результате преобразований может оказаться нуль, и алгоритм "сломается". Второй – на диагонали может оказаться довольно маленький, но отличный от нуля, элемент, деление на который может привести к большим ошибкам результата (т.н. неустойчивость). В практической реализации алгоритма Гаусса поступают так: при выборе очередного столбца в нем находится максимальный по абсолютной величине элемент. Он и его строка становятся "ведущими" и переставляются со строкой, в которой берется диагональный элемент. Это снимает оба "камня": если ведущий элемент ноль, то система уравнений вырождена и решать нечего, и, поскольку ведущий элемент максимальный, то возможная ошибка минимизируется. Вот и все – в чистом виде алгоритм А: "выбор главного элемента". Приведем алгоритм с учетом указанных поправок в Mcd. Здесь удобно переставлять столбцы матриц (индексированные в верхних угловых скобках, см. рис. 6), поэтому расширенную матрицу системы (с присоединенной с помощью функции augment правой частью) полезно представить в транспонированном виде.
Gauss(A, b) : = A ← (augment(A, b))T, n ← cols(A) - 1
for i 0 .. n
p ← 0, m ← -1
for j i .. n
q ← |Ai, j| if q > p
p ← q, m ← j if m < 0
return "degenerate", break
p ← (Ai, m)-1, b ← A‹i›, A‹i› ← A‹m›∙p A‹m› ← b if m > i
for j 0 .. n
A‹j› ← A‹j› - Ai, j∙A‹i› if j ≠ i
(AT)‹n + 1›
(помните, что каждый оператор следует писать в отдельной строке). Упражнение 2. Запишите соответствующий код в VBA. Упражнение 3. С помощью приведенного алгоритма Гаусса за-
пишите программу вычисления определителя квадратной матрицы. Заметим, что в Mcd системы линейных уравнений с матрицей А и
правой частью b можно решать с помощью встроенной функции
62
lsolve (A, b). Матрица может при этом не быть квадратной (для переопределенных систем уравнений реализован метод наименьших квадратов или псевдообратной матрицы, которую можно получить также с помощью функции geninv). Определитель матрицы A вычисляется с помощью прямых скобок |A| (для числа это абсолютная величина, для вектора – длина).
1.8. ФАЙЛЫ
Файл - это последовательность записей на внешнем носителе информации. Обычно каждая информационная система организует файлы своим специальным образом, присоединяя к имени файла отличительную "типовую" добавку - расширение. Например, файлы в DOS часто имеют расширение .com, .sys, .exe и др., файлы в WORD имеют расширение .doc, . rtf, .htm и др., в EXCEL - расширение .xls, в PAINT -.bmp, в MULTIMEDIA -.avi, .wav, и т.д. В Бейсике, в основном, созда-
ются текстовые и двоичные файлы - без расширения (или с расширением, определяемым пользователем), либо файлы программ с расширением .bas. Visual Basic позволяет компилировать программы в файлы с расширением .exe, но в приложениях они остаются в формате приложения. Mcd позволяет сохранять данные с расширением .prn,
.txt, а также обрабатывать некоторые графические и медиафайлы.
1.8.1 Файлы в VBA
По типу доступа в VBA организуются файлы последовательные (включая бинарные) и файлы прямого доступа.
В последовательных файлах записи могут иметь произвольную длину и разделены на носителе специальным признаком конца. Каждое обращение к такому файлу либо добавляет запись к уже существующим, либо считывает записи по очереди, начиная с первой. При работе с такими файлами используются операторы открытия, работы, закрытия файла.
Открытие файла осуществляется строкой
Open "устройство: \ имя" For ‹ действие › As # N,
|
|
input |
|
где действие = |
|
|
, т.е. ввод (считывание из файла), вывод |
|
output |
||
|
|
|
|
|
append |
|
(запись в файл), добавление (к записям в файле), N -номер, присвоенный файлу в программе. Если файла для вывода не существовало, то оператор Open создает указанный файл.
Работа с файлами:
Input # N,‹ имя переменной › - считывание записи из файла N,
63
Print # N,‹ имя переменной › - запись в файл с номером N.
Иногда употребляются также операторы Write #N (записи разделяются запятыми, текстовая информация оформляется в кавычки - это удобно, когда текст содержит знаки препинания) и LineInput # N для чтения информации, записанной оператором Write.
Функции Loc и Lof возвращают номер записи и длину файла в байтах. Логическая функция Eof(N) возвращает значение True, если обработана последняя запись файла с номером N, иначе - значение
False.
Закрытие файла:
Close # N - закрывает файл с номером N. Если номер файла не указан, то этот оператор закрывает все файлы.
Обмен с файлами происходит через буфер, в котором после работы может остаться информация, поэтому полезно в конце работы закрывать все файлы, чтобы не оставлять информацию в буфере обмена. Оператор End заканчивает программу, закрывая все открытые файлы. Оператор Kill # N уничтожает (закрытый) файл с номером N (освобождает его место в памяти, убирает его имя из каталога).
Пример 1. В последовательном файле My_inf требуется оста-
вить только числа z, удовлетворяющие условию: z (0, ), e -z + 1 < 2. sin(z)
Откроем временный файл с именем Tempo в папке C:\Temp одновременно для записи и чтения, затем его уничтожим:
Sub Cons_File_Test() Dim z A Single
Const pi As Single = 3.1415926
Open "C: \ Temp \ My_Inf" For Input As #1
Open "C: \ Temp \ Tempo" For Output As #2
Open "C: \ Temp \ Tempo" For Input As #3 Do: Input #1, z
If (z > 0) And (z < pi) And ((Exp( - z) + 1) / Sin(z) < 2) Then Print #2, z Loop Until Eof(1)
Close #1: Open "C: \ Temp \ My_inf" For Output As #1 Do
Input #3, z: Print #1, z Loop Until Eof(3)
Close: Kill #2, #3 End Sub .
В бинарных (двоичных) файлах обмен осуществляется по байтам и, следовательно, необходимо аккуратно отслеживать объем обмениваемой информации. С другой стороны, эти файлы позволяют более свободно распоряжаться структурой данных.

64
В файлах прямого доступа хранится только текстовая информация (так что можно создавать файл с расширением .txt), при этом каждая запись имеет фиксированную длину, определяемую полем записи в буфере.
Открытие файла:
Open " устройство : \ имя" For Random As # N Len = M,
где N - номер, присвоенный файлу в программе, М - длина записи в байтах. Закрывается файл стандартно оператором Close.
В Dos-Бейсике пользователь должен был сам определять структуру и размер буфера с помощью директивы
Field # N,‹ поле 1› AS ‹ имя 1›, ‹ поле 2› AS ‹ имя 2›, и т.д.,
где N -номер файла, ‹ поле i › - размер памяти в байтах, отводимой буферной переменной ‹ имя i ›, i = 1,2,..., сумма полей равна М.
В VBA эта директива отменена, и пользователь создает переменную типа String необходимого размера, либо указывает соответствующий пользовательский тип.
Работа:
Get # N, m, A -считывание записи с номером m из файла с номером N в переменную А (либо в буфер).
Put # N, m, A - запись значения переменной А (или содержимого буфера обмена) в файл (m –я запись) с номером N.
Так как здесь обменивается информация только в символьном виде, то числовую информацию полезно предварительно переводить в символьную, а при считывании снова переводить в числовую форму. Если информация обменивается в пользовательском формате, то эти преобразования выполняются автоматически с помощью встроенных функций, в противном случае это нужно делать самостоятельно.
Пример 2. Пусть нас интересует информация (фамилия, возраст, пол, телефон) о некоторых конкретных людях. Определим (в дополнительном модуле) пользовательский тип (см. п. 1.7.2)
Type Person
Name As String * 10
Age As Byte
Sex As Boolean
Tel ef As Long
End Type
65
и организуем ввод данных в файл прямого доступа с именем Test.txt в
папке C:\Temp.
Sub Create_File()
Dim friends As Person, m As Integer, s As String
Open "C:\Temp\test.txt" For Random As #1 Len = Len(friends) With friends
Do: s = InputBox("input a name", "", "") If s = "" Then Exit Do
.Name = s
.Age = Val(InputBox("input age", "", 0))
.Sex = InputBox("input sex: true as male", "", True)
.Telef = Val(InputBox("telefon", "", 0)): i = i + 1 Put #1, i, friends
Loop End With Close
End Sub .
Введем такую информацию: Николаев, 23, True, 648297, Спинстер, 16, False, 909581, Трафф, 35, False, 635014, Васин, 27, True, 810071, Лимо-
нов, 81, True, 375573. В результате получим файл следующего содержания:
Николаев яяiд |
Спинстер б |
Трафф # †° Васин |
яяW\♀ Лимонов Qяя» |
- вся информация, кроме текстовой, нечитабельна, выполнена конвертация числовых данных в текстовый формат. При чтении все, тем не менее, становится на свои места. Если же последнюю строчку цикла в предыдущей программе заменить на
s = s & ", " & Format(.Age) & ", "
If .Sex Then s = s & "муж." Else s = s & "жен." s = s & ", " & Format(.Telef)
Put #1, i, s
(преобразование к текстовому формату), и длину записи указать не меньше 26, то содержание файла будет вполне информативным:
__Николаев, 23, муж., 648297__Спинстер, 16, жен., 909581__Трафф, 35, жен., 635014_____Васин, 27, муж., 810071_____Лимонов, 81, муж., 375573 .
В отдельных приложениях есть свои особенности работы с файлами, о них будет сказано в своем месте.
1.8.2. Файлы в Mcd
Для обмена числовой и текстовой информацией в Mcd имеются лишь три функции: WRITEPRN("путь к файлу"), которая помещается слева от знака присваивания (справа – объект для записи), и функция
66
READPRN("путь к файлу"), которая записывается справа от знака присваивания. Информация записывается, как правило, в том же виде, в каком она представлена на рабочем листе (кроме ранжированных переменных). Каждая запись производится в отдельный файл (после очистки от предыдущей информации). Если необходимо дополнить данные в файле информацией такого же формата, то можно использовать функцию APPENDPRN("путь к файлу"), стоящую слева от знака присваивания. Например, в рабочем листе Mcd записана инфор-
|
|
"test" |
|
1 |
2 |
3 |
4 |
|
||
мация: b : (-6 8 3 0) |
c : |
|
13 |
|
d : |
4 |
3 |
2 |
1 |
, то присваивание |
= |
= |
|
2 |
|
= |
3 4 1 2 |
|
WRITEPRN("C:\Temp\Test.txt") := b
поместит в файл Test.txt запись: -6 8 3 0 . Присваивание
WRITEPRN("C:\Temp\Test.txt") := с
поместит в файл Test.txt запись:
//Datafile written by Mathcad
//12/14/11 20:07:05
.MATRIX 0 0 3 1 "test" 13 2
Наконец, присваивание |
|
WRITEPRN("C:\Temp\Test.txt") := d |
|
поместит в файл Test.txt запись: |
|||
1 |
2 |
3 |
4 |
4 |
3 |
2 |
1 |
3 |
4 |
1 |
2 |
Таким образом, запись числовой информации сохраняет в файле структуру данных рабочего листа. Если же массив содержит разнородную информацию, то файл оформляется "шапкой", оговаривающей структуру даннах. Чтение из файлов данных выполняется просто операцией присваивания (таким образом сразу создается рабочий объект). Напри-
мер, присваивание А := READPRN("C:\Temp\Test.txt") создает объ-
ект со структурой данных файла, т.е. число, текст, вектор, матрица.
67
1.9. РАБОТА С ГРАФИЧЕСКОЙ ИНФОРМАЦИЕЙ
Dos-версии Бейсика (да, собственно, и других языков программирования) с возможностью непосредственного управления экраном дисплея позволяли устанавливать специальный графический режим отображения информации. В Бейсике это оператор Screen N, где N – номер режима, определяющий возможность цветного отображения и плотности (число пикселей по ширине и высоте экрана). Некоторые специальные дополнительные операторы позволяли изображать на экране определенный класс линий. Перечислим некоторые из них.
Cls – очищает экран.
Circle(x,y),R[,c[, , [,S]]] - изображает окружность (или дугу) с центром в точке (х, у) (счет точек начинается слева направо и сверху вниз) радиуса R цветом с кодом с, и - угловые меры начала и конца дуги (если изображается не вся окружность), S степень сжатия (если изображается эллипс или его дуга).
Сolor [b[,f]] - выбор цвета фона и палитры.
Draw"‹текстовая информация›"- изображение произвольной ломаной в соответствии со строкой информации, где указываются команды:
Un - движение вверх на n позиций, Dn - движение вниз на n позиций,
L,R,E,F,G,H соответственно указывают на движение влево, вправо на северо-восток, юго-восток, юго-запад, северо-запад.
Mx,y - команда перехода к точке с координатами (х, у).
Префикс В команд движения указывает на перемещение без изображения линии (просто "перенос пера"), префикс N указывает на движение с возвратом в исходную точку.
An - разрешает поворот фигуры на n прямых углов,
TAn - разрешает поворот на n градусов (против хода часов), Сn - устанавливает код n цвета линии,
Pn,m - закрашивает область цветом с кодом n вплоть до границы цвета с кодом m,
Sn - введение масштабного коэффициента n.
Line(a, b) - (c, d) [,c[,B[F]]] - изображение прямой, соединяющей точки (a, b) и (c, d), цветом с кодом с. Признак В означает изображение прямоугольника с вершинами (a, b), (c, d), признак F (вместе с В) закрашивает прямоугольник указанным цветом. Если предыдущая точка предполагается фиксированной (оператором Line или Pset), то первый операнд можно опустить, оператор
Line принимает сокращенную форму: Line - (c,d) [,c[,B[F]]]. Get (a,b) - (c,d), A - пересылает экранное содержимое прямоугольника

68
с вершинами (a,b), (c,d) в ранее определенный массив А. Put (x,y), A [,характер] - пересылает графическую информацию из
массива А на экран, начиная с точки (х,у). Характер указывает взаимодействие информации с экраном : Pset, Preset, Xor, Or, And.
Paint(x,y),c1,c2 - окрашивает область экрана, содержащую точку (х,у), цветом с кодом с1 до границы цвета с кодом с2.
Pset(x,y),c - изображается на экране точка (х,у) цветом кода с. Preset(x,y) - убирает точку (х,у) с экрана.
Point(x,y) - возвращает атрибут цвета точки (х,у).
Visual Basic оставил лишь некоторые из традиционных операторов, такие как Circle, Cls, Line, Pset, добавив к ним возможность масштабирования (оператор Scale) и установку толщины линии (Draw Width). На специальных элементах управления (Form, Picture, Image) можно помещать прямоугольники, эллипсы, круги (элементы Shape), рамки (Frame), совмещать изображения (PaintPicture), печатать текст (Print) с выбором шрифта, размера и цвета текста.
В приложениях, как правило, имеется возможность внедрения любого графического объекта (в том числе и объекта другого приложения). Кроме того, разрешается использование художественного текста (панель меню WordArt) и изображение разнообразных автофигур (панель меню Рисование). В Excel, например, имеется возможность автоматического построения всевозможных графиков и диаграмм. В меню "мас-
тер диаграмм" (иконка ) представлен богатый выбор графических изображений функциональных зависимостей (см. рис. 9). Допускается также использование графических возможностей других па-
кетов (StatGraf, MatLab,
Mcd, и др.). Word и другие офисные приложения разрешают использовать графические возможности Excel, а также имеют свою
панель рисования. Все это значительно расширяет графические возможности приложений и в значительной степени снижает необходимость

69
программирования изображений. Некоторые особенности графики в Excel и Word, тем не менее, будут оговорены позже.
Mcd не имеет своей собственной панели рисования, но позволяет загружать произвольные рисунки из файлов, внедрять элементы Paint, Excel, Word, и др. К собственной панели "графика" можно добраться, щелкнув мышкой по иконке . В результате появится меню графических возможностей (рис. 10). В этом меню (по порядку слева направо): построение плоских графиков, масштабирование (лупа) выбранного участка диаграммы, оцифрование отдельных точек графика, график в полярной системе координат, график поверх-
ности (3D), линии уровня, столбчатая диаграмма, построение пространственных кривых и векторного поля. Ко всему прочему, Mcd имеет несколько встроенных функций обработки изображений таких,
например, как загрузка массива цветовой палитры файла изображения, построение полиэдра, чтение и запись цветовых оттенков изображения, и т.д. Это позволяет в рамках Mcd выполнять анализ, фильтрацию, преобразование некоторых распространенных типов графических файлов (см. также п. 6.1).
1.10. ОТЛАДКА И ТРАССИРОВКА
Основная проверка синтаксиса VBA происходит в процессе компиляции программы, окончательная – при запуске. Синтаксически правильный программный продукт может содержать алгоритмические и другие ошибки, не видимые невооруженным глазом. Редактор VBA (меню Debug, см. рис. 11) позволяет уста-
новить в проблемных местах точки оста-
новки (Toggle Breakpoint, F9) и выпол-
нить участок программы по шагам (F8). В этом режиме при наведении курсора на переменную высвечивается ее текущее значение, что позволяет отслеживать процесс вычисления. Кроме того, в меню View (см. рис. 12) можно открыть дополнительное окно (Watch Window) для текущего просмотра значений различных объектов (их можно туда поместить, выбрав пункт Add Watch в меню Debug). Нажатие клавиш Shift + F8 позволяет избежать пошаговой трассировки при ссыл-

70
ках на функции и подпрограммы. Вернуться к нормальному режиму можно, нажав клавишу F5. Непосредственные вычисления можно провести в окне прямых расчетов (Immediate Window, см. рис. 12), используя DOS-овский оператор Print. Например, если нас интересует ASCII-код символа "#" клавиатуры, в этом окне можно набрать код:
print "Код # = ";ASC("#")
и нажать "Enter", получим
Код # = 35.
В некоторых случаях избежать сложной ситуации позволяет техника "захвата ошибки" с помощью оператора
On Error GoTo ‹метка›.
При возникновении конфликта компилятор передает управление указанной метке, где пользователь сможет на нее прореагировать. Если реагировать на ситуацию не нужно, можно использовать оператор
Resume Next.
Пусть, например, в программе требуется считывание информации из файла, ко-
торый может отсутствовать. Если файла нет, программа может использовать значения по умолчанию и продолжать работать.
...
On Error GoTo Check '***переход к метке Check при аварийной ситуации
Open ‹путь к файлу› For Input As #n
...
Exit Sub
Check: MsgBox "Файл не найден," & Chr(13) & _
"используются данные по умолчанию.", vbExclamation, "Error!"
... ‹восстанавливаются умолчания›
Resume Next End Sub .
(такой обработчик ошибок следует помещать в конце программы, перед ним можно поставить выход из программы, чтобы предотвратить обработку несуществующей ошибки в конце работы).
В Mcd, начиная с версии 13, также имеются средства отладки и трассировки программ. В период компиляции или вычислений проблемное выражение или имя функции отмечается красным цветом, обозначая ошибку. Например, при попытке вычислить значение функции