Как сделать красивую матрицу в c
Добавил пользователь Владимир З. Обновлено: 04.10.2024
- количество строк
- количество столбцов
- указатель на массив элементов
- конструкторы (по умолчанию, полный, копирования) и деструктор
- генерация единичной матрицы
- получение элемента под номером (i,j)
- получение и изменение размерности матрицы
- сложение, вычитание и умножение матрицы на число
- сложение и вычитание двух матриц
- транспонирование матрицы
- проверка равенства размерности двух матриц
- проверка возможности умножения двух матриц
- умножение двух матриц
- ввод матрицы с клавиатуры и вывод матрицы на экран
Решение:
Матрицу можно организовать как вектор из векторов ( std::vector > ), в академических целях иногда просят реализовать вектор самостоятельно, тогда можно взять там. Однако, ниже (с той же целью) приведена другая реализация — двумерная матрица тут задается массивом (линейным), где строки записаны последовательно друг за другом. Поэтому для получения j-того элемента i-той строки надо выполнить такое обрещение:
такой подход иногда применяется, ведь при нем выполняется меньше динамических аллокаций — что хорошо при большом количестве небольших матриц. Однако, он требует цельного куска в памяти для хранения всех элементов матрицы — поэтому не очень хорошо работает если нужны очень большие матрицы.
Алгоритм умножения матриц описан тут, а про транспонирование — там.
Для генерации единичной матрицы была добавлена функция generate_1 , которая заполняет матрицу нулями, но на главной диагонали ставит единицы. Функция отработает корректно только для квадратных матриц, ведь единичная матрица — всегда квадратная.
Для получения размерности добавлены функции:
Они помечены const чтобы их можно было вызывать для константных матриц. Ведь в коде выше мастрица часто передается по константной ссылке чтобы устранить лишние копирования матрицы при вызове функции.
При сложении с числом — число добавляется к каждому элементу, при вычитании — вычитается (при этом по факту выполняется сложение с -value ). При умножении — каждый элемент умножается на число.
Исходный код целиком (при копировании стоит разделить его на объявление в .h файле и реализацию в .cpp файле):
Рассмотрим основные операции , выполняемые над матрицами (статическими и динамическими) при решении задач.
Матрицы, как и массивы, нужно вводить (выводить) поэлементно. Блок- схема ввода элементов матрицы x[n][m] изображена на рис. 6.3.
При выводе матрицы элементы располагаются построчно, например:
Алгоритм построчного вывода элементов матрицы приведён на рис. 6.4.
Ниже приведён текст программы на C++ ввода-вывода статической матрицы.
Цикл для построчного вывода матрицы можно записать и так.
При вводе матрицы элементы каждой строки можно разделять пробелами, символами табуляции или Enter . Ниже представлены результаты работы программы.
Далее на примерах решения практических задач будут рассмотрены основные алгоритмы обработки матриц и их реализация в C++ . Перед этим давайте вспомним некоторые свойства матриц (рис. 6.5):
- если номер строки элемента совпадает с номером столбца (), это означает, что элемент лежит на главной диагонали матрицы;
- если номер строки превышает номер столбца (), то элемент находится ниже главной диагонали;
- если номер столбца больше номера строки (i >
Как известно процессор i80186 является 16 битным, соответственно регистры данного процессора имеют размер 16 бит (например регистр аккумулятор AX) и делятся на две части по 8 бит (AH — старшая часть и AL — младшая). Так же нам понадобятся прерывания BIOS: 10h и 16h, которые будут управлять видеорежимом и клавиатурой соответственно. И прерывание Dos под номером 21h, необходимое нам в данном случае для вывода строки на дисплей и корректного завершения программы.
Далее следует память в которой мы объявляем переменные и константы для нашего кода, и сразу перепрыгиваем эту часть памяти чтобы не выполнять её:
Итак, мы добрались до момента когда нужно указать видео режим дисплея нашей ЭВМ в котором мы будем выводить символы матрицы. Но сначала сохраним текущий режим в стек чтобы в конце к нему вернуться.
Выставляем видеорежим: текст CGA,EGA 80x25:
И, наконец, нам необходимо получить сигнал о том что мы больше не хотим смотреть на матрицу и уже можем проследовать за белым кроликом. Для этого мы используем проверку нажатия клавиши клавиатуры и если символ нажат не был, то продолжаем вывод символов матрицы:
Символ нажат и мы закрываем программу, но сначала восстановим предыдущий видеорежим:
Следуем за белым кроликом:
Заканчиваем программу корректно:
Если слепить все эти кусочки кода вместе, то скомпилировать и слинковать можно с помощью команд:
Пока этот класс явлеятся просто оберткой для двумерного массива.
Начинаем добавлять вспомогательные методы. Сначала добавим метод, позволяющий выполнить какое-либо действие над всеми элементами матрицы.
Функции высших порядков — это функции, которые как переменные передаются в аргументы других функций. В методе выше аргумент func имеет тип Action . Это значит, что аргументом должна быть функция, принимающая 2 аргумента типа int и возвращающая void. Добавим в конструктор такой вызов:
Этот вызов присвоит 0 во все элементы матрицы. Стрелочная функция (i, j) => this.data[i, j] = 0 — это и есть наша функция высшего порядка.
Использовать стрелочные функции не обязательно, можно было передавать и метод:
Индексаторы — это свойства, позволяющие обращаться к объекту как к массиву. Добавим такое свойство, позволяющее обращаться к элементам матрицы по индексу
Теперь к экземпляру класса Matrix можно обращаться как к двумерному массиву.
Сначала реализуем умножение матрицы на число. В результате должна получиться матрица того же размера, элементами будут элементы исходной матрицы умноженные на это число.
Теперь умножить матрицу на число можно с помощью оператора умножения
Матрицу можно так же умножить на другую матрицу. Результатом будет новая матрица, элементами которой будут скалярные произведения столбцов и строк исходных матриц. Формулу можно посмотреть на википедии
Читайте также: