Лабораторная работа № 7.
Разработка программы "Умножение матриц" в C++ Builder

Цель работы

Написать программу перемножения двух матриц размерностью 4х4. 

Пример умножения двух матриц:
Умножить на .

Решение.
 
В ходе вычислений были выполнены следующие действия
Умножаем 1 строку на 1 столбец 1 • (-1) + (-2) • 23 + 3 • 4.4 + 1 • (-4.4) = -38.2
Умножаем 1 строку на 2 столбец 1 • 2 + (-2) • (-23) + 3 • 12 + 1 • 12 = 96
Умножаем 1 строку на 3 столбец 1 • 3 + (-2) • 1 + 3 • 1 + 1 • (-1) = 3
Умножаем 2 строку на 1 столбец 23 • (-1) + (-23) • 23 + 1 • 4.4 + 2 • (-4.4) = -556.4
Умножаем 2 строку на 2 столбец 23 • 2 + (-23) • (-23) + 1 • 12 + 2 • 12 = 611
Умножаем 2 строку на 3 столбец 23 • 3 + (-23) • 1 + 1 • 1 + 2 • (-1) = 45
Умножаем 3 строку на 1 столбец (-44) • (-1) + 12 • 23 + 0 • 4.4 + 1 • (-4.4) = 315.6
Умножаем 3 строку на 2 столбец (-44) • 2 + 12 • (-23) + 0 • 12 + 1 • 12 = -352
Умножаем 3 строку на 3 столбец (-44) • 3 + 12 • 1 + 0 • 1 + 1 • (-1) = -121 

Пример компоновки формы

Спецификация программы:
    1) Для работы с матрицами (ввод и вывод матриц) должен быть использован компонент StringGrid.
    2) Перемножаемые матрицы должны вводиться пользователем. То есть таблица StringGrid1 и StringGrid2 должны быть редактируемые.
    3) Таблица с результатом  StringGrid3должна быть закрыта для редактирования пользователем.

Справка по работе с компонентом StringGrid.
Компонент StringGrid представляет собой таблицу, содержащую строки. Данные таблицы могут быть только для чтения или редактируемыми. Таблица может иметь полосы прокрутки, причем заданное число первых строк и столбцов может быть фиксированным и не прокручиваться. Таким образом, можно задать заголовки столбцов и строк, постоянно присутствующие в окне компонента. Каждой ячейке таблицы может быть поставлен в соответствие некоторый объект. 
Компонент StringGrid  находится на вкладке Additional панели компонентов. 
Таблица StringGrid состоит из выделенных серым FixedCols и FixedRows - зафиксированных ячеек-заголовков, и обычных, белых ячеек. Содержимое Fixed ячеек недоступно для редактирования, и меняется только программно. Для установки количества фиксированных ячеек можно изменить значение свойств FixedCols и FixedRows в окне свойств Object Inspector. Или поменять количество фиксированных строк и столбцов программно, написав в коде программы команды

StringGrid1-> FixedCols=1; // устанавливает 1 фиксированный столбец
StringGrid1-> FixedRows=1; // устанавливает 1 фиксированную строку

Общее количество строк и столбцов  в таблице можно установить вручную в окне Object Inspector, отредактировав свойства RowCount и ColCount, а можно изменить программно в ходе выполнения программного кода, написав следующие команды:

StringGrid1->RowCount=5 //устанавливаем общее кол-во строк равное 5
StringGrid1->ColCount=7 //устанавливаем общее кол-во столбцов равное 7
Эти свойства доступны как для записи (при установке количества строк и столбцов), так и для чтения (при проверке размер таблицы).

За многие свойства компонента StringGrid отвечает свойство Options. В Инспекторе Объектов Options - это раскрывающийся список, представляющий собой элементы данного множества. Если значение элемента равно True, то он присутствует в множестве, если False - то нет.

 Свойство  Значение
goFixedVertLine Наличие вертикальных разделительных линий между "фиксированными" ячейками
goFixedHorzLine Наличие горизонтальных разделительных линий между "фиксированными" ячейками
goVertLine Наличие вертикальных разделительных линий между "обычными" ячейками
goHorzLine Наличие горизонтальных разделительных линий между "обычными" ячейками
goRangeSelect Возможность выделить диапазон ячеек
goDrawFocusSelected Закрашивание ячейки с фокусом ввода
goRowSizing Возможность менять высоту строк мышкой
goColSizing Возможность менять ширину столбцов мышкой
goRowMoving Возможность менять номер строки, то есть перемещать её, мышкой
goColMoving Возможность менять номер столбца, то есть перемещать его, мышкой
goEditingВозможность редактировать содержимое ячейки с клавиатуры
goTabs При значении True фокус смещается на следующую ячейку в таблице, False - на следующий компонент
goRowSelect Выделяется вся строка с "фокусированной" ячейкой
goAlwaysShowEditor При значении True содержимое ячейки при получении фокуса сразу доступно редактированию, False - сначала необходимо щёлкнуть по ней мышкой (прим.: не действует при goRowSelect=True)
goThumbTracking При значении True перемещение "бегунка" прокрутки мышкой вызывает немедленное перемещение ячеек, False - ячейки перемещаются только при отпускании "бегунка"

Как следует из таблицы, за возможность редактировать содержимое ячеек с клавиатуры отвечает элемент goEditing свойства-множества Options. В Инспекторе Объектов установите его значение в True. Чтобы управлять этой возможностью программно, нужно включить или исключить из множества данный элемент:

StringGrid1->Options<<goEditing;  //Включаем редактирование, другие 
  //элементы не трогаем

StringGrid1->Options>>goEditing;  //Выключаем редактирование, другие 
  //элементы не трогаем

Компонент StringGrid имеет возможность адресации каждой отдельной ячейки по номеру столбца и строки. 

Содержимое ячейки (i, j), где где i - номер столбца, j - номер строки, имеет вид:

StringGrid1->Cells[i][j]

и доступно как для чтения, так и для записи. Например: 

StringGrid1->Cells[i][j]=”Hello”; - записывает слово в ячейку с координатами I и j.
A=StringGrid1->Cells[i][j]; - считывает содержимое ячейки с координатами I и j в переменную A.

Номера столбцов (i) и строк (j) отсчитываются от 0.

Выделенная ячейка таблицы имеет: 
номер столбца:  StringGrid1->Col
номер строки:   StringGrid1->Row

поэтому содержимое выделенной ячейки будет адресоваться так:

S=StringGrid1->Cells[StringGrid1->Col][StringGrid1->Row];

Ячеек в таблице, как правило, много, и в рамках компонента видна только часть из них. Если ячейки не помещаются в таблице, появляются полосы прокрутки. При прокручивании:
StringGrid1->LeftCol                 Номер столбца, видимого самым левым
StringGrid1->TopRow                 Номер строки, видимой самой верхней
StringGrid1->VisibleColCount Количество столбцов, видимых в рамках таблицы
StringGrid1->VisibleRowCount Количество строк, видимых в рамках таблицы

У таблицы StringGrid также есть свойство и для управления размером ячеек.Для всех ячеек
DefaultRowHeight - высота строк по умолчанию
DefaultColWidth - ширина столбцов по умолчанию

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

RowHeights[i] - массив, содержащий высоты строк с номером i
ColWidths[i] - массив, содержащий ширины столбцов с номером i

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

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

int i, j;
{
    for (i=1;i<StringGrid1->RowCount;i++)  //Заголовки строк не трогаем
    for (j=1;j<StringGrid1->ColCount;j++)  //Заголовки столбцов не трогаем
      StringGrid1->Cells[j][i]='';
  
 Хотя, есть метод для очищения содержимого целого столбца или строки:
  StringGrid1->Cols[i]->Clear(); //Очищается столбец с номером i
  StringGrid1->Rows[i]->Clear(); //Очищается строка с номером i 
 
Очевидно, очищение этими методом происходит гораздо быстрее. Однако будут очищены и ячейки фиксированной зоны, содержащие, например, названия строк и столбцов, которые удалять не нужно. Их после очистки нужно просто "написать" заново, на глаз эта манипуляция совершенно незаметна. Для очистки всей таблицы достаточно последовательно очистить только строки или только столбцы:

int i, j;
{
    for (i=1;i<StringGrid1->RowCount;i++) //Заголовки столбцов не трогаем                     
//цикл от 1
      {
        StringGrid1->Rows[i]->Clear();
        StringGrid1->Cells[0][i]="Заголовок строки i";
      }
}
Comments