Авторские разработки С++ MFC

О проекте | Новости | Статьи | Исх.тексты | Отзывы | Форум | Главная

 

Создания класса матрицы (практическое задание).

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

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

Cоздадим заголовочный файл matrix.h. В него будет занесено описание класса matrix (обычная практика разделения описания и тела класса, используется для дальнейшего включения заголовочного файла в другие программы проекта) и matrix.cpp, в него будет занесено тело класса.

Необходимо сразу понять, что здесь создается объект "матрица". Этот объект обладает некоторыми свойствами и некоторыми методами, через которые с объектом можно работать.

Сначала напишем файл matrix.h. В нем опишем все, что нужно для работы класса.

#pragma once      // нужна для того, чтобы компилятор
                            // обрабатывал файл только один раз

class CMatrixStr  // назовем нашу матрицу так

Что матрицу  характеризует? Количество столбцов и количество строк. Это внутренние данные, поэтому определим эти данные в область для внутреннего использования.

private:
    int Rows;      // рядов
    int Cols;        // колонок

Для хранения данных нужна память, а т.к. в С++ выделение динамической памяти происходит блоками, то используем для эмуляции доступа массив указателей на блоки памяти, т.е. указатель на указатель. Будем хранить данные типа float   

    float ** FloatData; 

Т.к. для нашей задачи необходимо нахождение минимальных и максимальных значений и дальнейшая работа с этими значениями (получение разности), то и для них оставим по указателю.

    float * DataMin;
    float * DataMax;

На этом внутренние данные закончились, и переходим к работе с методами.
       
public:
    CMatrixStr(int Row=1,int Col=1);   // конструктор
    ~CMatrixStr(void);                          //   деструктор

Для установки и считывания одного элемента:

    float GetAt(int Row,int Col);         //  получить
    void SetAt(int Row,int Col,float Data); // записать

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

    void Fill();

В конце концов, необходимо нахождение минимальных и максимальных значений:

    void MinMax(int Row);

Найти еще полдела, нужно еще показать, что нашли.

    void Display();

Теперь файл matrix.h выглядит следующим образом.

#pragma once
class CMatrixStr
{
private:
    int Rows;
    int Cols;
    float ** FloatData;
    float * DataMin;
    float * DataMax;
       
public:
    CMatrixStr(int Row=1,int Col=1);
    ~CMatrixStr(void);
    float GetAt(int Row,int Col);
    void SetAt(int Row,int Col,float Data);
    void Display();
    void MinMax(int Row);
    void Fill();
};

Перейдем к собственно телу матрицы (matrix.cpp)
Для начала включим в него необходимые файлы

#include "iostream.h"       // для работы   cin
#include "stdlib.h"             // для функций работы с числами
#include "stdio.h"              // для printf
#include "matrix.h"            // заголовочный для класса

Опишем конструктор класса (вызывается при объявлении переменной с типом CMatrixStr). Конструктор запускается с параметрами количества строк и количества столбцов. Если вдруг эти параметры будут пропущены, то, чтобы не ломалась программа, при объявлении конструктора задаются единицы.

CMatrixStr::CMatrixStr(int Row,int Col)
{
    Rows = Row;        // присвоим внутренним переменным переданные параметры
    Cols = Col;

    Выделим динамически память для хранения минимального и максимального значения каждого ряда полученной матрицы.

    DataMin = new float[Rows]; 
    DataMax = new float[Rows];

Для хранения собственно данных матрицы сначала выделим память для массива указателей на каждый ряд матрицы
    FloatData= new float * [Rows];

Теперь для каждого ряда выделяем память для хранения элементов в колонках и попутно забиваем новые значения нулями и присваиваем нулевые значения для минимального и максимального элемента.
    for (int j=0;j<Rows;j++){
        FloatData[j] = new float[Cols];
        DataMin[j]=0.0;
        DataMax[j]=0.0;
        for (int i=0;i<Cols;i++){
            FloatData[j][i]=0.0;
        }
    }
    return;
};

CMatrixStr::~CMatrixStr()
{
В деструкторе обязательно освобождаем выделенную память для каждого ряда ...

    for (int j=0;j<Rows;j++){
        delete FloatData[j];
    }

и для массива указателей на ряды и на массивы минимальных и максимальных значений
delete [] FloatData;
delete [] DataMin;
delete [] DataMax;
};

Методы "получить значение элемента" и "установить значение элемента" необходимы для защищенного доступа к элементам матрицы извне. Т.к. при запросе на запись и получение данных проверяются переданные параметры, то в программе гарантировано не будет выхода за границы массива. Причем при передаче неправильных границ массива можно активизировать диагностические сообщения, которых здесь нет по причине учебного задания.

float CMatrixStr::GetAt(int Row,int Col)
{
    if (Row < 0 || Row > Rows)
        Row=0;
    if (Col < 0 || Col > Cols)
        Col=0;
    return FloatData[Row][Col];
};

void CMatrixStr::SetAt(int Row, int Col,float Data)
{
    if (Row < 0 || Row > Rows)
        Row=0;
    if (Col < 0 || Col > Cols)
        Col=0;
    FloatData[Row][Col]=Data;
}

Одной функцией получаем минимальные и максимальные значения для ряда матрицы. Соответственно параметр -  ряд

void CMatrixStr::MinMax(int Row)
{
Для начала присваиваем минимуму и максимуму значения нулевой колонки. Это значение будет у нас эталоном.

    DataMin[Row]=FloatData[Row][0];
    DataMax[Row]=FloatData[Row][0];

Теперь сравниваем каждое значение в колонке

    for (int i=1;i<Cols;i++){
     и если оно меньше того значения, которое записано в DataMin, то присваиваем новое значение

        if (DataMin[Row] > FloatData[Row][i])
            DataMin[Row]= FloatData[Row][i];
    и если оно больше того значения, которое записано в DataMax, то присваиваем новое значение       

    if  (DataMax[Row]< FloatData[Row][i])
            DataMax[Row]=FloatData[Row][i];
    }
}

Заполнение матрицы рядами цифр по одной - тяжелое занятие. Пусть за нас компьютер заполнит матрицу случайными значениями

void CMatrixStr::Fill()
{
    for (int j=0;j<Rows;j++){
        for (int i=0;i<Cols;i++){
            FloatData[j][i]=(float)rand();
        }
        MinMax(j);     // и не забудем при этом пересчитать минимальное и максимальное значение для каждого ряда
    }
    return;
}

Осталось только вывести матрицу на печать

void CMatrixStr::Display()
{
    printf("\n Matrix \n");
    for (int j=0;j<Rows;j++){
        printf("Row:%i>", j);        // нумеруем каждый ряд
        for (int i=0;i<Cols;i++){
            printf("%5.0f ",FloatData[j][i]); // печатаем колонки
        }
        printf(" Max: %5.0f Min: %5.0f Min-Max = %5.0f    // выводим разность \n",DataMax[j],DataMin[j],DataMax[j]-DataMin[j]);
    }
    return;
}

А программа будет совсем простая файл main.cpp:

#include "iostream.h"
#include "matrix.h"

void main()
{
    // спросим сколько колонок и строк
    int Row,Col;
    cout << "\nRow ?:" ;
    cin >> Row ;
    cout << "\nCol ?:" ;
    cin >> Col ;


    CMatrixStr Matrix(Row,Col);    // создадим нашу матрицу
    Matrix.Fill();                               // заполним значениями
    Matrix.Display();                        // и покажем результаты
}

При запуске должно получиться примерно следующее

Row ?:3
Col ?:4

Matrix
Row:0> 41 18467 6334 26500 Max: 26500 Min: 41 Min-Max = 26459
Row:1>19169 15724 11478 29358 Max: 29358 Min: 11478 Min-Max = 17880
Row:2>26962 24464 5705 28145 Max: 28145 Min: 5705 Min-Max = 22440

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

Скачать полный текст zd_prog.arj (52kb)
   

© Авторские разработки http://progcpp.narod.ru при цитировании ссылка обязательна.

Сайт создан в системе uCoz