Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование в среде Visual C++ 6. Учебное пособие
.pdf
ления. Для этого левой кнопкой манипулятора воздействуем на пункт меню View — ClassWizard, в ответ на экране
монитора появится знакомое нам окно MFC ClassWizard.
Выберем класс CDiurDoc, пункт меню Message Maps, азатем в окне Object IDs выделим идентификатор IDD_PUSK
и в окне Messages щёлкнем левой кнопкой манипулятора
на пункт COMAND, а затем на пункт Add Function. Вот-
вет наэто появится окно спредложением назвать функцию
именем OnPusk Нужно сэтим согласиться ищёлкнуть левой
кнопкой манипулятора накнопку OK этого окна иобязательно окна MFC ClassWizard.
В окне Workspace— Classview раскроем класс CDiurDoc,
и там среди функций встретим новую OnPusk, щёлкнем
наней левой кнопкой манипулятора, ина экране монитора
появится эта функция. Вся программа будет состоять только
издвух операторов:
nm=0;
UpdateAllViews (NULL);
Первый оператор разрешит интегрирование уравнения,
авторой передаёт выполнение программы функции OnDraw
класса CDiurView/.
И последнее. Когда формировался класс CDialogEdit,
вместе сним организовался файл собъявлениями иописаниями. Нужно этот файл присоединить кклассу CDiurDoc.
Для этого, находясь внутри какой-либо функции класса
CDiurDoc, нужно курсор поднять наверх и среди предпроцессорных операций присоединения #include вставить
строку:
#include “DialogEdit.h”
В кавычках как раз иесть имя файла сописаниями иопределениями класса CDialogEdit. Наименование файла— это
— 71 —

наименование соответствующего класса без первого символа. Вот теперь класс CDiurDoc полностью сформулирован.
Можно провести первое промежуточное компилирование
путём воздействия левой кнопкой манипулятора на пункт
меню Build — RebuildAll. Если в нижнем окне появится
сообщение, что нет ошибок и предупреждений, наша программа работоспособна. Достаточно левой кнопкой манипулятора щёлкнуть напункт Build— Execute Diur.exe, как
наэкране монитора появится окно снашим меню и нашей
панелью управления. Интегрировать она ещё неумеет, выводить результаты тоже неможет, номожно проверить пункт
— , появится окно с сообщением
о программе. Если щёлкнуть левой кнопкой манипулятора
накнопку , это окно исчезнет. Если воздействовать левой кнопкой манипулятора напункт Ввод, на экране монитора появится диалоговое окно для ввода исходных данных.
Если щёлкнуть левой кнопкой манипулятора на пункт -
, окно исчезнет. Аесли щёлкнуть левой кнопкой манипулятора напункт меню , наша программа закроется.
Теперь чтобы следить заходом выполнения нашей задачи,
нужно поработать склассом CDiurView.
8.10. Вывод результатов наэкран монитора
Результаты вычислений можно вывести на экран мони-
тора с помощью класса представления, в нашем случае это
класс CDiurView. А следовательно, и основные вычис-
ления нужно выполнять в этом классе. Для начала нужно
определить и описать необходимые переменные. Для этого
необходимо вокне Workspace во вкладке Classes в перечне
классов выделить класс CDiurView и дважды щёлкнуть
на нём левой кнопкой манипулятора. На экране монитора
— 72 —

раскроется файл с определениями и описаниями. Найдите
свободный пункт Protected. Вклассе CDiurDoc мы искали
пункт Public, так как переменные этого класса должны быть
доступны другим классам. Переменные класса CDiurView
другим классам не нужны, поэтому и переменные объявим
иопишем под пунктом Protected. Какие это переменные? Вопервых, это переменные изкласса документов. Для удобства
целесообразно переписать переменные изкласса документов
втекущий класс. Это приведет к тому, что кэтим переменным ненужно писать префикс pDoc. Правда, это для настоящих компьютеров нетак критично, новсё-таки это проще
ибыстрее. Это касается идентификаторов a1, a2, x0, xk, y0,
n. Далее введём двумерный массив xy [2] [40], куда будем помещать вычисленные значения x иy. Количество строк пока
указали равным 40, хотя внашей задаче их 21 (20— количество интервалов). Ноесли появится желание увеличить количество интервалов, тоне нужно будет вносить изменения
всаму программу, атолько ввести число интервалов вместе
с остальными исходными данными. Введём идентификатор
h— шаг интегрирования по переменной x. Кроме того, для
вычисления правой части нашего уравнения нужны переменные аргументы изначение вычисленной функции, назовём их xn, yn, fn. Для вычисления промежуточных значений
втаблице 8.1 введём переменные тогоже наименования k1,
k2, k3 иk4. Для построения графика функции нужно знать
количество пикселей наэкране монитора на единицу переменных x иy, назовём их как dxx иdyy. Координаты точек бу-
дущего графика обозначим xx иyy. Для вывода символьных
строк наэкран монитора введём переменную s. Нуидля организации цикловых операторов введём переменную i. Обычно
перед оставлением программы далеко невсегда удаётся пред-
— 73 —

усмотреть иобъявить все необходимые переменные. Поэтому
впроцессе составления программы приходится многократно
обращаться кэтому файлу ивносить добавления иизменения вэтот список переменных.
Итак, после слова Protected наследующей строчке пишем
операторы:
double a1, a2, x0, xk, y0, xy [2] [40], h, xn, yn, fn, k1, k2, k3, k4,
dxx, dyy;
int n, i, xx, yy;
char s [40];
Теперь вокне Workspece вовкладке Classes щёлкнем левой
копкой манипулятора накрестик слева откласса CDiurView,
появится список всех его членов-функций. Выберем имя функции OnDraw ищёлкнем дважды левой кнопкой манипулятора
наэто имя. Наэкране монитора раскроется содержание этой
функции. Это основная функция для программирования многих задач. Пока что вэтой функции только два оператора. Первый оператор указывает, что как только программа встретит
префикс pDoc, открывается созданный нами документ, авторой оператор указывает, что сэтим префиксом доступны все
члены-данные класса документа, вданном случае CDiurDoc,
описанные под пунктом Public. Обратим внимание на аргументы функции OnDraw (CDC*pDC). Здесь CDC — это
класс, включающий в себя множество функций. Вызывать
любую из этих функций необходимо через префикс pDC->.
Последние два символа указывают напринадлежность кклассу CDC.
Теперь приступим непосредственно к заполнению тела
функции OnDraw. Первое, что мы сделаем, это составим заго-
ловок нашей программы поеё назначению. Это будет текстовая строка, для вывода которой наэкран монитора предусмо-
— 74 —

трена функция TextOut (вывести текст) стремя аргументами.
Первый аргумент — координата начала текста по горизонтальной оси, второй аргумент— координата строки повертикали. Третий аргумент— это сам текст нарусском или английском языках, заключённый в двойные кавычки. Итак, после
второго оператора вставим оператор типа (водну строку):
pDC->TextOut (50,20,”Интегрирование дифференциального уравнения методом Рунге-Кутта”);
Обратите внимание, что после набора первого символа
функции появляется список всех функций класса CDC. Те перь дальше можно вместо набора остальных символов названия функции дважды щёлкнуть левой кнопкой манипулятора наназвании функции. Теперь следовалобы выделить
заголовок путём подчёркивания. Но если сейчас вставить
функции для подчёркивания, тозаголовок будет подчёркнут
линией толщиной водин пиксель. Это тонкая линия, итакое
подчёркивание выглядит довольно неубедительно. Нужно
изменить толщину линии. Для изменения толщины линии
(иногда называют толщину пера) введём следующие два оператора:
CPen pen (PS_SOLID,3, RGB (0,0,0));
CPen* oldPen=pDC->SelectObject (&pen);
Здесь функция pen изкласса CPen имеет три аргумента.
Первый аргумент— это тип линии, вданном случае линия непрерывная. Второй аргумент— толщина линии (пера) впикселях. Третий аргумент, сложный, указывает цвет линии.
В аргументе RGB первое число — яркость красного цвета,
второе число— яркость зелёного цвета итретье число— яркость синего цвета. Вданном случае яркость всех цветов равны нулю, это значит, что цвет линии остаётся чёрным. Следует отметить набудущее, что для изменения цвета только
— 75 —

текста существует функция pDC->SetTextColor (RGB (k, z, s),
где аргумент RGB тоже указывает яркости красного, зелёного
исинего цветов впределах от0 до255— максимальной яркости. Второй оператор запоминает прежние параметры линии.
Для рисования прямой линии нужно два оператора. Пер-
вый оператор pDC->MoveTo (x, y) помещает курсор в точ-
ку начала линии с координатами x иy. Авторой оператор
pDC->LineTo (x1, y1) указывает координаты x1, y1 конца линии. Длину линии погоризонтали можно рассчитать примерно 8 пикселей наодин символ. Так что внашем случае оба
выше указанных оператора будут выглядеть как:
pDC->MoveTo (50,45);
pDC->LineTo (540, 45);
Разумеется, эти координаты всегда можно подкорректировать, если они записаны сошибкой. Следующий оператор
должен восстановить запомненные ранее параметры линии
спомощью оператора:
pDC->SelectObject (oldPen);
Теперь можно провести пробное компилирование программы путём двойного щелчка на пункт меню Build —
Rebuild All, если компилятор укажет синтаксические ошибки,
их нужно исправить. Затем дважды щёлкнуть левой кнопкой
манипулятора на пункт меню Build — Execute Diur.exe.
Произойдёт запуск нашей программы, где наэкране монитора будет наименование нашей программы илиния подчёркивания. Выйти изпрограммы можно, щёлкнув левой кнопкой
манипулятора напункт меню — .
На следующей строке монитора запишем вид нашего дифференциального уравнения спомощью знакомой нам функции вывода символьной строки:
pDC->TextOut (50,60,”y’=a1*y*y*exp (x) +a2*y”);
— 76 —

Выше упоминалось, что все исходные данные целесообразно перенести из класса документов вкласс представления. Это можно сделать спомощью следующих операторов:
a1=pDoc->a1;
a2=pDoc->a2;
x0=pDoc->x0;
xk=pDoc->xk;
y0=pDoc->y0;
n=pDoc->n;
Здесь префикс pDoc-> указывает напринадлежность следующего идентификатора классу документов CDiurDoc.
На следующих строках монитора запишем значения коэффициентов ипараметров нашего уравнения. Для записи
каждого числа необходимо перевести его в строку символов, азатем спомощью функции вывода символьной строки вывести это число на экран монитора. Преобразование
так называемого машинного числа в строку символов осуществляется функцией sprintf (B, F.A). B— буфер для записи
результатов, внашем случае им может служить символьная
переменная s, описанная ранее как тип char. F— формат пре-
образования. Это символьная строка, внутри которой указывается способ представления числа. Способ преобразования начинается ссимвола процента, иобычно может иметь
следующие виды:
%m.nf— для представления ввиде десятичной дроби, где
m –минимальное количество выводимых знаков. Если их
окажется меньше, чем нужно, sprintf исправит, аесли больше, токоличество лишних символов слева заполнится нулями или проигнорирует. Число n указывает количество символов после десятичной точки. Здесь число наэкране монитора
будет сошибкой посравнению сдействительным числом. Эта
— 77 —

ошибка, естественно, тем меньше, чем больше символов после десятичной точки.
%md— для представления целого числа (сознаком). Здесь
m тоже минимальное количество знаков. Если их больше
необходимого, символы слева заполняются нулями, а если
меньше, тофункция sprintf его исправит.
%d — для представления целого числа без указания ко-
личества знаков. Функция sprintf выведет столько знаков,
сколько будет необходимо.
%m.ne — для представления числа с плавающей точкой
суказанием показателя степени соснованием 10. Число выводится наэкран монитора вследующем формате: z
d
ddd. Здесь zч— знак числа, если оно отрицательное, d—
nezg
целая часть дроби, d
ние степени соснованием 10, z
… dn— дробная часть числа, e— основа-
1
— знак порядка, ddd— один
g
d.d1d2d3…
ч
или несколько символов значения порядка. Более подробно
смотрите [1], С. 307.
Таким образом, следующие операторы могут выглядеть как:
sprintf (s,”a1=%4.2f,”, a1);
pDC->TextOut (50,80, s);
sprintf (s,”a2=%4.2f,”, a2);
pDC->TextOut (120,80, s);
sprintf (s,”%4.2f <=x<=%4.2f,”, x0, xk);
pDC->TextOut (50,100, s);
sprintf (s,”y0=%4.2f,”, y0);
pDC->TextOut (180,100, s);
sprintf (s,”n=%d.”, a1);
pDC->TextOut (250,100, s);
Естественно, координаты расположения данных наэкране монитора приходится рассчитывать и при необходимости корректировать. Обратите внимание, что в функциях
— 78 —

pDC->TextOut третьим аргументом является просто ссылка
наорганизованную символьную строку s. Теперь можно снова провести пробное компилирование изапуск программы,
где мы можем попробовать вводить исходные данные путём
вызова диалогового окна, воспользовавшись пунктом меню
— или командой командной строки. Есте-
ственно, после прекращения работы программы все введённые исходные данные несохраняются.
8.11. Заполнение таблицы расчёта
Вот теперь можно приступить кразработке основной ча-
сти программы— это интегрирование дифференциального
уравнения. Программа OnPusk приготовит условие начала
интегрирования путём присвоения переменной идентификатора nm=0. теперь нам нужно проверить это условие спомощью оператора:
If (pDoc->nm==0)
{
....
}
На первых порах может быть полезен совет. После открытия фигурной скобки нужно несколькими строками
ниже её закрыть, чтобы потом незабыть это сделать. Впротивном случае компилятор выдаёт ошибку снеправильной
диагностикой, и Вам будет достаточно сложно найти эту
ошибку. По мере заполнения этого составного оператора
эта закрывающая скобка будет всё время перемещаться
вниз. В конце этих действий эту скобку можно поднять
донужной строки.
Первым делом сначала очистим массив переменной xy,
чтобы вслучае несовпадения числа точек интегрирования
— 79 —

ичисла строк выдачи наэкран монитора небылобы выдачи
несоразмерного числа, так как коды этого массива заранее
неопределенны. Хотя при внимательном программировании эту операцию можно ине производить. Мы всё-таки
введём следующие два оператора после открытой фигурной
скобки:
for (i=0; i<45; i++)
xy [0] [i] =xy [1] [i] =0.0;
Теперь создадим таблицу на мониторе для вывода значений рассчитываемой функции. Эту таблицу создадим
вправой части нашего экрана. Нарисуем линию разделения
аргумента ифункции, азатем сверху для создания шапки таблицы.
pDC->MoveTo (900,5);
pDC->LineTo (900,450);
pDC->MoveTo (800,45);
pDC->LineTo (990,45);
pDC->TextOut (850,20,”x”);
pDC->TextOut (930,20,»y»);
Заполним первую строку таблицы начальными условиями:
xy [0] [0] =x0;
xy [1] [0] =y0;
Вычислим шаг интегрирования h:
h= (xk-x0) /n;
Процесс интегрирования выполним циклической программой:
for (i=0; i<n; i++)
{
Не забудьте несколькими строками ниже поставить закрывающую фигурную скобку, чтобы незабыть её поставить
вконце этой части программы.
— 80 —
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
