Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование в среде Visual C++ 6. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
ления. Для этого левой кнопкой манипулятора воздейству­ем на пункт меню View — ClassWizard, в ответ на экране монитора появится знакомое нам окно MFC ClassWizard. Выберем класс CDiurDoc, пункт меню Message Maps, аза­тем в окне Object IDs выделим идентификатор IDD_PUSK и в окне Messages щёлкнем левой кнопкой манипулятора на пункт COMAND, а затем на пункт Add Function. Вот- вет наэто появится окно спредложением назвать функцию именем OnPusk Нужно сэтим согласиться ищёлкнуть левой кнопкой манипулятора накнопку OK этого окна иобязатель­но окна MFC ClassWizard.
В окне Workspace— Classview раскроем класс CDiurDoc, и там среди функций встретим новую OnPusk, щёлкнем наней левой кнопкой манипулятора, ина экране монитора появится эта функция. Вся программа будет состоять только издвух операторов:
nm=0;
UpdateAllViews (NULL);
Первый оператор разрешит интегрирование уравнения, авторой передаёт выполнение программы функции OnDraw класса CDiurView/.
И последнее. Когда формировался класс CDialogEdit, вместе сним организовался файл собъявлениями иописа­ниями. Нужно этот файл присоединить кклассу CDiurDoc. Для этого, находясь внутри какой-либо функции класса CDiurDoc, нужно курсор поднять наверх и среди пред­процессорных операций присоединения #include вставить строку:
#include “DialogEdit.h”
В кавычках как раз иесть имя файла сописаниями иопре­делениями класса CDialogEdit. Наименование файла— это
— 71 —
наименование соответствующего класса без первого симво­ла. Вот теперь класс CDiurDoc полностью сформулирован. Можно провести первое промежуточное компилирование путём воздействия левой кнопкой манипулятора на пункт меню Build — RebuildAll. Если в нижнем окне появится сообщение, что нет ошибок и предупреждений, наша про­грамма работоспособна. Достаточно левой кнопкой мани­пулятора щёлкнуть напункт Build— Execute Diur.exe, как наэкране монитора появится окно снашим меню и нашей панелью управления. Интегрировать она ещё неумеет, выво­дить результаты тоже неможет, номожно проверить пункт  —  , появится окно с сообщением о программе. Если щёлкнуть левой кнопкой манипулятора накнопку , это окно исчезнет. Если воздействовать ле­вой кнопкой манипулятора напункт Ввод, на экране мони­тора появится диалоговое окно для ввода исходных данных. Если щёлкнуть левой кнопкой манипулятора на пункт - , окно исчезнет. Аесли щёлкнуть левой кнопкой манипу­лятора напункт меню , наша программа закроется.
Теперь чтобы следить заходом выполнения нашей задачи,
нужно поработать склассом CDiurView.
8.10. Вывод результатов наэкран монитора
Результаты вычислений можно вывести на экран мони-
тора с помощью класса представления, в нашем случае это класс CDiurView. А следовательно, и основные вычис- ления нужно выполнять в этом классе. Для начала нужно определить и описать необходимые переменные. Для этого необходимо вокне Workspace во вкладке Classes в перечне классов выделить класс CDiurView и дважды щёлкнуть на нём левой кнопкой манипулятора. На экране монитора
— 72 —
раскроется файл с определениями и описаниями. Найдите свободный пункт Protected. Вклассе CDiurDoc мы искали пункт Public, так как переменные этого класса должны быть доступны другим классам. Переменные класса CDiurView другим классам не нужны, поэтому и переменные объявим иопишем под пунктом 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 щёлкнем левой
копкой манипулятора накрестик слева откласса CDiurView, появится список всех его членов-функций. Выберем имя функ­ции OnDraw ищёлкнем дважды левой кнопкой манипулятора наэто имя. Наэкране монитора раскроется содержание этой функции. Это основная функция для программирования мно­гих задач. Пока что вэтой функции только два оператора. Пер­вый оператор указывает, что как только программа встретит префикс pDoc, открывается созданный нами документ, авто­рой оператор указывает, что сэтим префиксом доступны все члены-данные класса документа, вданном случае CDiurDoc, описанные под пунктом 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 Diur.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-> указывает напринадлежность сле­дующего идентификатора классу документов CDiurDoc.
На следующих строках монитора запишем значения ко­эффициентов ипараметров нашего уравнения. Для записи каждого числа необходимо перевести его в строку симво­лов, азатем спомощью функции вывода символьной стро­ки вывести это число на экран монитора. Преобразование так называемого машинного числа в строку символов осу­ществляется функцией 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 —
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]