Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tema_9.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
145.92 Кб
Скачать

5 Примеры программ

5.1 Использование массива структур

Необходимо изменить предыдущую программу, чтобы она позволила вычислять функцию следующего вида:

y = (f0(x) - y0)(f1(x) - y1) ... (fn - 1(x) - yn - 1)

fi(x) = (x - x0)(x - x1) ... (x - xi - 1)(x - xi + 1) ... (x - xn - 1)

так, чтобы пары точек xi и yi хранились в массиве структур. Заголовочный файл будет аналогичен файлу из предыдущего примера:

#ifndef UnitMath_h

#define UnitMath_h

bool getXY(char *fileName);

double y(double x);

bool writeTable(double left, double right, double step, char *fileName);

#endif

Изменения коснутся файла UnitMath.cpp. В частности, в нем необходимо описать тип структуры:

#include <fstream>

#include <vector>

#include "UnitMath.h"

namespace

{

struct Point

{

double x, y;

};

std::vector <Point> v;

}

bool getXY(char *fileName)

{

std::ifstream in(fileName);

if (!in)

return false;

Point p;

while (in >> p.x >> p.y)

v.push_back(p);

return true;

}

double y(double x)

{

double result = 1;

for (unsigned int i = 0; i < v.size(); i++)

{

double f = 1;

for (unsigned int j = 0; j < v.size(); j++)

if (i != j)

f *= x - v[j].x;

result *= f - v[i].y;

}

return result;

}

bool writeTable(double left, double right, double step, char *fileName)

{

std::ofstream out(fileName);

if (!out)

return false;

for (double x = left; x < right + step; x += step)

out << x << "\t" << y(x) << "\n";

return true;

}

Основной модуль программы не изменится:

#include <iostream>

#include "UnitMath.h"

using namespace std;

int main(int argc, char* argv[])

{

if (getXY("points.txt") && writeTable(0, 2, 0.5, "results.txt"))

cout << "OK";

else

cout << "Error!";

return 0;

}

5.2 Использование указателя this

Допустим, имеется класс Point для представления точки на плоскости. Необходимо реализовать функцию сравнения двух точек. Перед тем, как сравнивать координаты, необходимо проверить, не сравнивается ли объект сам с собой.

Функцию сравнения можно объявить функцией-элементом класса Point:

class Point

{

private:

double x, y;

public:

Point(double newX, double newY) { x = newX; y = newY; }

bool isEqual(Point& p);

};

bool Point::isEqual(Point& p)

{

return (this == &p) || (p.x == x) && (p.y == y);

}

В функции main() можно протестировать работу функции isEqual():

int main(int argc, char* argv[])

{

Point p1(1, 1), p2(2, 2), p3(1, 1);

cout << p1.isEqual(p1) << ' '

<< p1.isEqual(p2) << ' '

<< p1.isEqual(p3);

return 0;

}

5.3 Массив вещественных чисел

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

Элементами данных разрабатываемого класса будут указатель на вещественные данные (для размещения массива в динамической памяти) и целое значение (текущая размерность массива). Для обеспечения сокрытия данных все его элементы должны быть закрытыми. Для доступа к элементам массива можно предусмотреть функции установки и получения элемента массива. Размер массива должен быть доступен только для чтения. Кроме того, необходим конструктор, в котором будет осуществлено выделение памяти под массив, и деструктор, в котором эта память будет освобождаться:

class Array

{

double *pa;

int size;

public:

Array(int n);

~Array();

void setElem(int index, double elem);

double getElem(int index) const;

int getSize() const;

};

Конструктор может иметь следующий вид:

Array::Array(int n)

{

pa = new double [size = n];

for (int i = 0; i < size; i++)

pa[i] = 0;

}

В функции установки значения элемента необходимо проверять, не вышел ли индекс за границы массива:

void Array::setElem(int index, double elem)

{

if (index >= 0 && index < size)

pa[index] = elem;

else

cout << "Error!\n";

}

Функция получения элемента по индексу также должна проверять, не вышел ли индекс за границы массива. Кроме того, она должна вернуть заведомо неприемлемое значение, например максимальное значение типа double. Такое значение можно получить с помощью специализации шаблона класса numeric_limits (заголовочный файл limits) и получения искомого значения с помощью функции-элемента max():

double Array::getElem(int index) const

{

if (index >= 0 && index < size)

return pa[index];

else

{

cout << "Error!\n";

return numeric_limits<double>::max();

}

}

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

void Array::addElem(double elem)

{

double *temp = new double [size + 1];

if (pa)

{

for (int i = 0; i < size; i++)

temp[i] = pa[i];

delete [] pa;

}

pa = temp;

pa[size] = elem;

size++;

}

Теперь понадобится конструктор без параметров и функция, возвращающая размер массива. Эти функции можно определить внутри класса:

#include <iostream>

#include <limits>

using namespace std;

class Array

{

double *pa;

int size;

public:

Array() { pa = 0; size = 0; }

Array(int n);

~Array() { if (pa) delete [] pa; }

void addElem(double elem);

void setElem(int index, double elem);

double getElem(int index) const;

int getSize() const { return size; }

};

Теперь работу класса можно протестировать в функции main()

int main(int argc, char* argv[])

{

Array a;

a.addElem(11);

a.addElem(12.5);

for (int i = 0; i < a.getSize(); i++)

cout << a.getElem(i) << ' ';

cout << endl;

Array b(10);

b.setElem(9, 35);

for (int i = 0; i < b.getSize(); i++)

cout << b.getElem(i) << ' ';

cout << endl;

b.setElem(10, 35);

cout << b.getElem(10);

return 0;

}

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

Array::Array(const Array& arr)

{

size = arr.size;

pa = new double [size];

for (int i = 0; i < size; i++)

pa[i] = arr.pa[i];

}

Естественно, что соответствующий конструктор должен быть объявлен в соответствующем разделе определения класса:

class Array

{

. . .

public:

. . .

Array(const Array& arr);

. . .

};

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]