Целью данного проекта было изучение графического интерфейса. В частности, считывание введенной пользователем информации и вывод полученного результата в другой элемент управления. Еще одной особенностью, на мой взгляд, является то, что на кнопки нагружен дополнительный функционал.   Математическая часть этого проекта, хоть и является ядром проекта, не самая большая его часть.

 pr2.1

pr2.2

Проанализировав исходный код, можно понять,  как переплетаются графическая и вычислительная части проекта.

Решение кубического уравнения происходит в отдельной функции, принимающей на входе коэффициенты уравнения.

// Функция cubic(...) предназначена для решения кубического уравнения
// 
// a3*x^3 + a2*x^2 + a1*x + a0 = 0
//

int
cubic(
      // НА ВХОДЕ:
      double a0,double a1,double a2,double a3, // коэффициенты уравнения                                              
      // НА ВЫХОДЕ:
      double &x1, // Всегда первый действительный корень
      double &x2, // Если уравнение имеет 3 действительных корня -
                  // это второй корень уравнения;
                  // в противном случае x2 - это действительная часть
                  // комплексно-сопряженной пары корней
      double &x3, // Если уравнение имеет 3 действительных корня -
                  // это третий корень уравнения;
                  // в противном случае x3 - это модуль мнимой части
                  // комплексно-сопряженной пары корней
      double eps
     )
// ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: 
//                             *         *         *
//  0 - корни действительные (x1  = x1, x2  = x2, x3  = x3);
//  1 - один действительный и два комплексно сопряженных корня
//        *         *                *
//      (x1  = x1, x2  = x2 + x3*i, x3  = x2 - x3*i);
// -1 - это не кубическое уравнение, т.к. a3 == 0.
{ 
    double z, f, A, B, C, D, x_prev;
	int k_iter;
	if (a3 == 0) return -1;
	if (a3 < 0) 
	{
		a3 = -a3;
		a2 = -a2;
		a1 = -a1;
		a0 = -a0;
	}
    x_prev = x1 = a0/3;
	k_iter = 0;
    // Находим действительный корень x1 методом Ньютона:
    for (;;)
    {
     f = (x1*(x1*(a3*x1 + a2)+a1)+a0);
     if (fabs(f) < eps) break;
     z = x1*(3*a3*x1+2*a2)+a1;
     if (fabs(z) <= 2.2e-16) 
     {
      x1 *= 2;
      if (x1 == 0) x1 += 1;
     }
     x1 = x1 - f/z;
	 if (x_prev == x1)
	 {
		 k_iter++;
		 if (k_iter > 5)
		 {
			 k_iter = 0;
			 eps *= 5;
		 }
	 }
	 x_prev = x1;
    }
	A = a3;
	B = a2+A*x1;
	C = a1+B*x1;
	// A,B,C - коэффициенты квадратного уравнения
	D = B*B-4*A*C; // его дискриминант
	A *= 2;
	if (D >= 0)
	{
		// два остальных корня кубического уравнения - действительные
		D = sqrt(D);
		x2 = (-B-D)/A;
		x3 = (-B+D)/A;
		return 0;
	}
	D = sqrt(fabs(D));
	x2 = -B/A;
	x3 = fabs(D/A);
    return 1;
}

Отличительной особенностью в данном проекте является работа со шрифтом: задание его параметров и дальнейшее использование для вывода текста в многострочное текстовое поле ListBox

font.CreateFont(
	-10, // nHeight
	 0,  // nWidth
	 0,  // nEscapement
	 0,  // nOrientation
	 FW_NORMAL,  // nWeight
         FALSE,  // bItalic
         FALSE,  // bUnderline
	 0,  // cStrikeOut
         RUSSIAN_CHARSET,  // nCharSet
         OUT_DEFAULT_PRECIS,  // nOutPrecision
         CLIP_DEFAULT_PRECIS,  // nClipPrecision
	 DEFAULT_QUALITY,  // nQuality
         DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
         "Condensed");              // lpszFacename
         
((CListBox *)GetDlgItem(IDC_LIST1))->SetFont(&font);

Также интересна функция rfp(). Эта функция работает с входными данным, проверяет их достоверность, преобразует из строк в числа. После получения решения  в строке int ier = cubic(a0,a1,a2,a3,x1,x2,x3,1e-6); формирует строку нужного формата и преобразует числа в строку.  Указатель типа void * необходим для указания на определенную область памяти, в которой размещены данные неопределенного типа. Проще говоря, можно  только запомнить область памяти. Но через  подобный указатель нельзя вызывать никакие методы и члены класса.

UINT rfp(void *)
{
	CString s;
	double a3,a2,a1,a0;
	double x1,x2,x3;
	double pr;
	unsigned long kp, i;
	stopper = FALSE;
	// Осуществляем проверку:
	int ier9 = _stscanf(o->m_pr,_T("%le"),&pr);
	int ier10= _stscanf(o->m_kp,_T("%lu"),&kp);
	int ier3 = _stscanf(o->m_a3,_T("%le"),&a3);
	int ier2 = _stscanf(o->m_a2,_T("%le"),&a2);
	int ier1 = _stscanf(o->m_a1,_T("%le"),&a1);
	int ier0 = _stscanf(o->m_a0,_T("%le"),&a0);
	int ier  = ((CListBox *)o->GetDlgItem(IDC_LIST1))->InitStorage(100000, 100);
        //ASSERT(n != LB_ERRSPACE);

	((CListBox *)o->GetDlgItem(IDC_LIST1))->ResetContent();
	// В ier0, ier1 , ... - коды возврата функции _stscanf(...)
	// Если ier0 == 0 => чтение прошло неудачно.
	if ( !ier0 || !ier1 || !ier2 || !ier3 || !ier9 || !ier10 )
	{
		AfxMessageBox(_T("Проверьте поля ввода !"));
		return 0;
	}
	//s.Format("%lu",kp);
	//AfxMessageBox(s);
	for (i=0;i<kp;i++)
	{
		if (stopper) break;
		a0=(1+(pr/100)*rand()/(double)RAND_MAX)*a0;
		a1=(1+(pr/100)*rand()/(double)RAND_MAX)*a1;
		a2=(1+(pr/100)*rand()/(double)RAND_MAX)*a2;
		a3=(1+(pr/100)*rand()/(double)RAND_MAX)*a3;			
		// Решаем уравнение
		int ier = cubic(a0,a1,a2,a3,x1,x2,x3,1e-6);
		if (ier == 0) // Корни все действительные
		{
			s.Format(_T("%lg %lg %lg"),x1,x2,x3);
		}
		else // Один корень дейстивтельный, два других - комплексно-сопряженные
		{
			s.Format(_T("%lg %lg+(%lg)*i %lg+(%lg)*i"),x1,x2,x3,x2,-x3);
		} // %6.3lf
		ier = ((CListBox *)o->GetDlgItem(IDC_LIST1))->AddString(s);
		if (ier == LB_ERR || ier == LB_ERRSPACE)
		{
			AfxMessageBox("Error");
			break;
		}
		s.Format("%lu",kp);
		o->SetDlgItemText(IDC_STATIC_TMP,s);
	}	
    s.Format("%lu",i);
    AfxMessageBox(s);

    return 0;
}

При нажатии кнопки Button5 меняется только заголовок кнопки.

void CZ1Dlg::OnButton5() 
{
	if (m_switch) 
	{
		GetDlgItem(IDC_BUTTON5)->SetWindowText(_T("Пауза"));
	}
	else
	{
		GetDlgItem(IDC_BUTTON5)->SetWindowText(_T("Продолжить"));
	}
	m_switch = !m_switch;
}

Перед закрытием, если поток существует, его надо приостановить:

	if (m_potok) m_potok->SuspendThread();

Запись результатов итераций в текстовый файл.

void CZ1Dlg::OnButton4() 
{
	FILE *f = fopen("tmp.txt","a");
	int  ier = 10000, i;
	CString s;
	int n;
	n = ((CListBox *)GetDlgItem(IDC_LIST1))->GetCount();
	for (i = 0; i < n; i++) 
	{
		// Получили очередную строку из listbox'а:
		((CListBox *)GetDlgItem(IDC_LIST1))->GetText(i,s);
		fprintf(f,"%s\n",(const char *)s);
	}
	fclose(f);
}