Разработка полноценных Windows-приложений
4. Вывод результатов и их сохранение
Описание вывода результатов частично затронуто в предыдущем пункте. Теперь рассмотрим вывод форматированного текста в файл. Для этого создадим пункт меню File Save as…, и обработаем нажатие на него. Но прежде добавим в файл ChildView.h строку:
protected: static DWORD CALLBACK FileStreamOutCallback(DWORD dwCookie, LPBYTE pbBuf, LONG cb, LONG *pcb); //Функция обратного вызова для записи данных в файл
и определим объявленный метод в файле ChildView.cpp:
DWORD CALLBACK CChildView::FileStreamOutCallback(DWORD dwCookie, LPBYTE pbBuf, LONG cb, LONG *pcb) { CFile *pFile = (CFile*) dwCookie; pFile->Write(pbBuf,cb); *pcb = cb; return 0; }
Обработчик пункта меню File Save as…
void CChildView::OnFileSaveas() { CString strFilter; //Строка для поддерживаемых форматов данных CString strFileName; //Строка для имени файла CString strExtension; //Строка для расширения файла strFilter = "Text file|*.txt|Rich text format file|*.rtf||"; //Инициализация строки поддерживаемыми форматами CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER,strFilter); //Создание диалога сохранения if(dlg.DoModal() == IDOK) //Если нажата кнопка Ok { strFileName = dlg.m_ofn.lpstrFile; //Инициализируем строку с именем файла if (dlg.m_ofn.nFileExtension == 0) //Если пользователь не ввел расширение { switch (dlg.m_ofn.nFilterIndex) //В зависисмости от выбранного формата { case 1: strExtension = "txt"; break; //Инициализируем строку case 2: strExtension = "rtf"; break; //с расширением default: break; } strFileName = strFileName + '.' + strExtension; //Окончательно записываем путь имя и расширение файла } EDITSTREAM es; //Создаем структуру потока CFile OutFile(strFileName,CFile::modeCreate|CFile::modeWrite); //Открываем файл для записи es.dwCookie = (DWORD) &OutFile; //Определяем поле структуры, указывающее куда записывать данные es.pfnCallback = FileStreamOutCallback; //Задаем функцию записи switch(dlg.m_ofn.nFilterIndex) //В зависимости от выбранного формата { case 1: m_Rich.StreamOut(SF_TEXT,es); break; //Записываем данные case 2: m_Rich.StreamOut(SF_RTF,es); break; //в файл default: break; } } }
Процедура записи данных в файл похожа на процедуру чтения. Мы пользуемся методом StreamOut(int nFormat, EDITSTREAM &es) класса CRichEditCtrl, который требует аргументами формат записываемых данных и структуру потока. Структура потока EDITSTREAM определяется заданием пункта назначения и функции записи. Добавим строку:
#include <algorithm>
в конец файла stdafx.h. Скомпилируем и запустим приложение. В результате, в соответствии с открытым текстовым документом, получается следующее: рис. 5.6 рис. 5.7 рис. 5.8
Приложение "Метод наименьших квадратов "
В данном параграфе, на примере создания приложения "Метод наименьших квадратов (МНК) ", рассматриваются следующие вопросы: диалог в качестве основного окна приложения, элемент управления CListCtrl, элемент управления CRichEditCtrl, класс CArray, работа с матрицами.
Постановка задачи. Теоретический материал
Пусть у нас есть следующая таблица:
![\begin{tabular}{|r||r||r||r|}
\hline
X & x_1 & ... & x_n\\
\hline
Y & y_1 & ... & y_n\\
\hline
\end{tabular}](/sites/default/files/tex_cache/7ef250d7514e9325ff69820ac203f3bb.png)
![\{x_1,...,x_n,y_1,...,y_n\}](/sites/default/files/tex_cache/8e84ad76c01d774e5db48d13744f5ac4.png)
Требуется построить полином y=f(x) заданной степени k: k меньше n-1 такой, что сумма квадратов расстояний от точек таблицы до графика полинома была наименьшей. Для поиска коэффициентов полинома составим следующий функционал:
![\sum_{i-1}^n(y_i-f(x_i))^2](/sites/default/files/tex_cache/6d64ee70c9f59f908d2de99eaff3a003.png)
и поставим задачу минимизации этого функционала F -> min. Полином запишем в виде
![f(x)=a_0+a_1{x}+...+a_k{x^k}](/sites/default/files/tex_cache/674bfc3d432e10469486ace45e70633d.png)
тогда необходимое условие минимума запишется в виде:
![\left\{
\begin{array}{l}
\frac{\parial F}{\partial a_0}=\sum_{i=1}^n(y_i-a_0-a_1{x_i}-...-a_k{x_i^k})=0\\
\frac{\parial F}{\partial a_1}=\sum_{i=1}^n(y_i-a_0-a_1{x_i}-...-a_k{x_i^k})(x_i)=0\\
\vdots\\
\frac{\parial F}{\partial a_k}=\sum_{i=1}^n(y_i-a_0-a_1{x_i}-...-a_k{x_i^k})(x_i^k)=0
\end{array}](/sites/default/files/tex_cache/c0b278562c2c3beee224c2c2edebe4f6.png)
![\left(
\begin{array}{ccc}
1 & \frac{\sum_{i=1}^n{x_i}}{n} &\ldots & \frac{\sum_{i=1}^n{x_i^k}}{n}\\
\frac{\sum_{i=1}^n{x_i}}{n} & \frac{\sum_{i=1}^n{x_i^2}}{n} &\ldots & \frac{\sum_{i=1}^n{x_i^k+1}}{n}\\
\vdots\\
\frac{\sum_{i=1}^n{x_i^k}}{n} & \frac{\sum_{i=1}^n{x_i^{k+1}}}{n} &\ldots & \frac{\sum_{i=1}^n{x_i^2k}}{n}
\end{array}
\right) \cdot
\left(
\begin{array}{c}
a_0\\
a_1\\
\vdots\\
a_k
\end{array}\right)=
\left(
\begin{array}{c}
\frac{\sum_{i=1}^n{y_i}}{n}\\
\frac{\sum_{i=1}^n{y_i\cdot x_i}}{n}\\
\vdots\\
\frac{\sum_{i=1}^n{y_i \cdot x_i^k}}{n}
\end{array}\right)](/sites/default/files/tex_cache/5af31c5fbb910ecf394dd9cb95bc8803.png)
Данная система имеет единственное решение, если k<n-1. Значит, существует единственный полином доставляющий минимум этому функционалу, с коэффициентами представимыми решением указанной системы. Напишем программу для нахождения коэффициентов полинома.