Помощь - Поиск - Пользователи - Календарь
Полная версия: вещественная матрица
Форум «Всё о Паскале» > Pascal, Object Pascal > 32 битные компиляторы
Svetlana
Помогите, пожалуйста, доработать код.Думаю ошибок там много(((

program lab_a;
{Описать класс, реализующий тип данных "вещественная матрица" и работу
с ними.Методы класса должны обеспечивать:
сложение, вычитание, умножение матриц (умножение, как на другую
матрицу, так и на число);
вычисление транспонированной матриц;
проверку типа матрицы (квадратная, диагональная, нулевая, единичная);
Написать программу, демонстрирующую работу с этим классом.}

{$APPTYPE CONSOLE}

uses
SysUtils;

type
veshmatr=class
X:array of array of Double;
n,m:integer;

Procedure vvod (var B:veshmatr);
Procedure vivod ( var B:veshmatr);
Procedure slosh(const A,B:veshmatr; var C:veshmatr);
Procedure vichet(const A,B:veshmatr; var C:veshmatr);
Procedure umnosh_na_chislo(const A:veshmatr; var B:veshmatr);
Procedure umnosh_na_matr(const A,B:veshmatr; var C:veshmatr);
Procedure transpan(const A:veshmatr;var B:veshmatr);
Function TypematriX:string;{определяет тип матрицы:квадратная,
диоганальная,нулевая или единичная}
end;


var
W,R,T:veshmatr;
i,j,k:integer;


procedure veshmatr.vvod( var B:veshmatr);
begin for i:=1 to n do
for j:=1 to m do begin
write('vvedite_element[',i,',',j,']=','');
readln(B.X[i,j]) end
end;

Procedure veshmatr.vivod ( var B:veshmatr);
begin
for i:=1 to n do begin
for j:=1 to m do writeln(' ',B.X[i,j]:12:3); writeln end;

end;

Procedure veshmatr.slosh(const A,B:veshmatr; var C:veshmatr);
begin
for I := 1 to n do
for j := 1 to m do
begin C.X[i,j]:=A.X[i,j]+B.X[i,j] end;
end;

Procedure veshmatr.vichet(const A,B:veshmatr; var C:veshmatr);
begin
for I := 1 to n do
for j := 1 to m do
begin C.X[i,j] :=A.X[i,j]-B.X[i,j] end;
end;

Procedure veshmatr.umnosh_na_chislo(const A:veshmatr; var B:veshmatr);
var chislo:double;
begin
writeln('vvedite_chislo');
readln(chislo);
for i:=1 to n do
for j:=1 to m do
begin B.X[i,j]:= A.X[i,j] * chislo end
end;

Procedure veshmatr.umnosh_na_matr(const A,B:veshmatr; var C:veshmatr);
var
i,j,k:word;
begin for i:=1 to n do
for j:=1 to m do
begin
C.X[i,j]:=0;
for k:=1 to n do
C.X[i,j]:=C.X[i,j]+A.X[i,k]*B.X[k,j]; end;
end;

Procedure veshmatr.transpan( const A:veshmatr;var B:veshmatr);
var
i,j:integer;
begin
for i:=1 to n do
for j:=i to m do
B.X[i,j]:=A.X[j,i];
end;

Function veshmatr.TypematriX:string;
begin
if n=m then writeln('matrica_kvadratnaya');

for i:=1 to n do
for j:=1 to m do begin
if (i<>j) and (X[i,j]=0) then writeln('matrica_diagonalnaya');
if X[i,j]=0 then writeln('matrica_nulevaya'); end;

for i:=1 to n do
for j:=1 to m do
if (i=j) and (X[i,j]=1) then writeln('matrica_edinichnaya')

end;

{начало программы}
begin
W:= veshmatr.Create; {создаём первую матрицу}
W.vvod(W); {ввод первой матрицы}
R:= veshmatr.Create; {создаём 2-ую матрицу}
R.vvod®; {ввод 2-ой матрицы}
T.slosh(W,R,T);
T.vivod(T);
T.vichet(W,R,T);
T.vivod (T);
R.umnosh_na_chislo(W,R);
R.vivod ®;
T.umnosh_na_matr(W,R,T);
T.vivod (T);
R.transpan(R,T);
R.vivod ®;


W.Free; {удаляем объект}
R.Free;
T.Free;

readln
end.


sheka
...
Извините. smile.gif
Svetlana
извиняю...)
volvo
Цитата
Думаю ошибок там много(((
Первая из них - неправильный выбор раздела. Тебе это надо сделать на Паскале, или Дельфи? А может быть, Object Pascal? Определись с этим, потом будем смотреть дальше.
Svetlana
Object Pascal
volvo
В таком случае вот тебе информация к размышлению:

type
veshmatr=class
X:array of array of Double;
n,m:integer;
Procedure vvod;
Procedure vivod;

Constructor Create;

Procedure Add(const A: veshmatr); // self := self + A
Procedure Sub(const A: veshmatr); // self := self - A
Procedure Mult(f: double); // self := self * f
Procedure Mult(const A: veshmatr); // self := self * A
Procedure Transpose; // self := T(self)
Function TypematriX: string;
end;

Этого интерфейса в принципе достаточно, чтобы организовать тот класс, который тебе нужен. В Object Pascal-е есть перегрузка (overloading) функций, так что одно имя можно использовать для нескольких методов, при условии, что в них будут передаваться разные параметры (что я и сделал на примере Mult). Второе: обрати внимание, у тебя все время должен изменяться тот экземпляр, для которого вызван метод. Поэтому нет нужды передавать в качестве параметров исходную матрицу, и результат тоже. Только второй параметр - то, что находится справа от знака операции.

Еще одно: никогда не делай так, как пыталась сделать в методе umnosh_na_chislo (я про то, что ты внутри метода пытаешься заставить пользователя ввести само число, на которое надо умножить матрицу.) Этого делать нельзя ни в коем случае: метод занимается ТОЛЬКО перемножением матрицы на число. Всё, больше ничем. Он получает на вход ТОЛЬКО число, на которое надо умножить матрицу. Как и когда ты получаешь от пользователя это число - это твоя проблема, метод об этом знать ничего не должен, это не его дело. Его дело - получить матрицу и число, и перемножить их. Точка. Не пытайся возхложить на методы чужую работу. Каждый должен заниматься своим делом. Кто-то складывает, кто-то перемножает, кто-то вводит данные, кто-то выводит их. А не "все вперемешку".

Тему переношу в 32-битные компиляторы, там гораздо ближе к Object-Pascal-ю.

Дальше сама справишься?
Svetlana
Спасибо,стало яснее. Только у меня ещё одна проблема:в первой же процедуре ввода. Она меня выбрасывает из командной строки после ввода первого элемента массива. Почему?
volvo
Я не вижу у тебя нигде инициализации массива Х в классе... У тебя просто попытка записи в неинициализированную переменную. Напиши свой конструктор, в котором сделай SetLength этому массиву, тогда все будет работать. Только вот M, N надо бы знать ДО инициализации.
Svetlana
Спасибо smile.gif
Svetlana
Решила написать работающий код(может кому-нибудь пригодится):


program lab_a;
{Описать класс, реализующий тип данных "вещественная матрица" и
работу с ними.Методы класса должны обеспечивать:
-сложение, вычитание, умножение матриц (умножение, как на другую
матрицу, так и на число);
-вычисление транспонированной матриц;
-проверку типа матрицы (квадратная, диагональная, нулевая, единичная);
Написать программу, демонстрирующую работу с этим классом.}

{$APPTYPE CONSOLE}

uses
SysUtils;


type
veshmatr=class
private{члены класса доступны только в этом модуле и внутри методов этого класса}

X:array of array of real;
n,m:integer;



public {члены класса доступны из лююбой точке программы,где действует описание класса}
Constructor Create;
Procedure vvod (const A:veshmatr) ;
Procedure vivod ( const A:veshmatr);
Procedure Add (const A,B:veshmatr; var C:veshmatr);
Procedure Sub(const A,B:veshmatr; var C:veshmatr);
Procedure Mult(s: Double;const A:veshmatr;var B:veshmatr); overload;
{один и тот же алгоритм для разных типов данных}
Procedure Mult ( const A,B:veshmatr;var C:veshmatr); overload;
Procedure Transpose( const A:veshmatr; var T:veshmatr);
Function TypematriX:string;{определяет тип матрицы:квадратная,
диоганальная,нулевая или единичная}
end;


var
M1,M2,M3,T:veshmatr; {это и есть объекты}
s: Double;
U:string;
Ch:char;

Constructor veshmatr.Create;

begin
inherited Create;{выполнение программы прерывается и вызывается одноименный метод родительского класса}


setlength(X,20,20);
end;





procedure veshmatr.vvod( const A:veshmatr);
var f,z,n,m:integer;
begin write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);
for f:=0 to n-1 do
for z:=0 to m-1 do
begin write('vvedite_[',f,',',z,']','___');
readln(A.X[f,z])
end;
for f:=0 to n-1 do begin {красивый ввод,похоже на матрицу}
for z:=0 to m-1 do write(' ',A.X[f,z]:12:3); writeln end; writeln
end;

Procedure veshmatr.vivod ( const A:veshmatr);
var f,z:integer;
begin writeln('Result:');
for f:=0 to n-1 do begin
for z:=0 to m-1 do write(' ',A.X[f,z]:12:3); writeln end; writeln
end;

Procedure veshmatr.Add(const A,B:veshmatr; var C:veshmatr);
var f,z:integer;
begin
write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);
for f := 0 to n-1 do
for z := 0 to m-1 do
begin C.X[f,z]:=A.X[f,z]+B.X[f,z] end; {складываем две матрицы поэлементно}
end;

Procedure veshmatr.Sub(const A,B:veshmatr; var C:veshmatr);
var f,z:integer;
begin
write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);
for f := 0 to n-1 do
for z:= 0 to m-1 do
begin C.X[f,z] :=A.X[f,z]-B.X[f,z] end; {вычитаем две матрицы поэлементно}
end;

Procedure veshmatr.Mult(s: Double;const A:veshmatr;var B:veshmatr);
var f,z:integer;
begin write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);

for f:=0 to n-1 do
for z:=0 to m-1 do
begin B.X[f,z]:= A.X[f,z] * s end {каждый эл.матр.умножаем на число s}
end;

Procedure veshmatr.Mult(const A,B:veshmatr; var C:veshmatr);
var f,z,k:integer;

begin for f:=0 to n-1 do
for z:=0 to m-1 do
begin
C.X[f,z]:=0;
for k:=0 to n-1 do
C.X[f,z]:=C.X[f,z]+A.X[f,k]*B.X[k,z]; end;
end;

Procedure veshmatr.Transpose (const A:veshmatr; var T:veshmatr);
var f,z:integer;
begin write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);

for f:=0 to n-1 do
for z:=0 to m-1 do
T.X[f,z]:=A.X[z,f];
end;

Function veshmatr.TypematriX:string;
var f,z:integer;flag,flag1:boolean;
begin
write('vvedite_kol-vo_strok_N >>>_'); readln(n);

write('vvedite_kol-vo_stolbofff_M >>>_'); readln(m);
if n=m then writeln('matrica_kvadratnaya');

{_________проверка на диагональность___________}
flag:=true;flag1:=false; {инициализация флагов}
f:=0;
while (f<=n-1) and (flag)do
begin
If X[f,f]=0 then flag :=false;
If X[f,f]<>0 then flag1:=true;
inc(f);
end;
if (not flag) then writeln('ne_diag');
f:=0;
while (f<=n-1) and (flag1) do
begin
z:=0;
while (z<=m-1) do
begin
if (f<>z) and (X[f,z]=0) then flag1:=true;
if (f<>z) and (X[f,z]<>0)then flag1:=false;

inc(z);

end;
inc(f);
end;
if flag1 then writeln('matr_diag');

{__________проверка на нулевую______________}
flag:=true;
f:=0;
while (f<=n-1) and (flag) do
begin
z:=0;
while z<=m-1 do
begin
if X[f,z]<>0 then flag:=false
else flag:=true;
inc(z);
end;
inc(f);
end;

if flag then writeln('nulevaya');

{_______________проверка на единичную___________}
flag:=true;flag1:=false; {инициализация флагов}
f:=0;
while (f<=n-1) and (flag)do
begin
If X[f,f]<>1 then flag :=false;
If X[f,f]=1 then flag1:=true;
inc(f);
end;
if (not flag) then writeln('ne_edinichnaya');
f:=0;
while (f<=n-1) and (flag1) do
begin
z:=0;
while (z<=m-1) do
begin
if (f<>z) and (X[f,z]=0) then flag1:=true;
if (f<>z) and (X[f,z]<>0)then flag1:=false;

inc(z);

end;
inc(f);
end;
if flag1 then writeln('matr_edinichnaya');










end;
{начало программы}
begin





M1:= veshmatr.Create; {создаём первую матрицу}
Writeln;
Writeln(' M1 ');
M1.vvod(M1); {ввод первой матрицы}
M2:= veshmatr.Create; {создаём 2-ую матрицу}
Writeln;
Writeln(' M2 ');
M2.vvod(M2); {ввод 2-ой матрицы}

M3:= veshmatr.Create;
T:= veshmatr.Create;

writeln('Add M1+M2? y/n >>>_');readln(ch);
if ch='y' then begin
M3.Add(M1,M2,M3); {вызов процедуры сложения}
Writeln('__________Add_M1+M2________');
M3.vivod(M3) end;

writeln('Sub M1-M2? y/n >>>_');readln(ch);
if ch='y' then begin
M3.Sub(M1,M2,M3); {вызов процедуры вычитания}
Writeln('__________Sub_M1-M2________');
M3.vivod(M3) end;


writeln('Mult s*M2? y/n >>>_');readln(ch);
if ch='y' then begin
writeln('vvedite_s');
readln(s);
M3.Mult(s,M1,M3);
Writeln('__________Mult_s*M1________');
M3.vivod(M3) end;



writeln('Mult M1*M2? y/n >>>_');readln(ch);
if ch='y' then begin
M3.Mult(M1,M2,M3);
Writeln('__________Mult_M1*M2_______');
M3.vivod(M3) end;



writeln('Traspon M1? y/n >>>_');readln(ch);
if ch='y' then begin
T.Transpose(M1,T);
Writeln('______Transponirovanaya____');
T.vivod(T) end;


writeln('Found type M1? y/n >>>_');readln(ch);
if ch='y' then begin
U:=M1.TypematriX;
Writeln(U) end;

writeln('Found type M2? y/n >>>_');readln(ch);
if ch='y' then begin
U:=M2.TypematriX;
Writeln(U) end;




M1.Free; {удаляем объект и переменная больше не ссылается на к.-л. обл.памяти}
M1:=nil;
M2.Free;
M2:=nil;
M3.Free;
M3:=nil;
T.Free;
T:=nil;
readln
end.



volvo
blink.gif Что это было? Вот это тебе зачем, например:
Цитата
Procedure Add (const A,B:veshmatr; var C:veshmatr);
? Add - сам по себе метод класса veshmatr, так ты мало того, что не используешь возможность вернуть результат (почему процедура, а не функция?), так еще и не используешь self.X, а передаешь оба операнда как параметры... Зачем тогда делать "сложение" методом класса?

Зачем понадобилось в Transpose, например, заставлять пользователя вводить количество строк/столбцов? Что, класс не знает, сколько столбцов, а сколько строк в той матрице, которую он хранит? Знает (иначе зачем тебе M и N?). Почему для печати матрицы надо делать вот этот ужас:
Цитата
M3.vivod(M3)
, а не просто M3.vivod ?

В общем, эту программу можно значительно упростить и сделать работу с классом гораздо более ясной и понятной... Чуть позже покажу, как...
Svetlana
Хорошо,буду ждать
volvo
Ну вот. Сравни с твоей реализацией, и скажи, с чем удобнее работать? Можно и дальше улучшать, кстати, это еще не самый окончательный вариант. Если честно, я думал, ты сама уже все сделала - столько времени прошло.
program lab_a;
{$APPTYPE CONSOLE}
uses
SysUtils;


type
veshmatr = class
private
X: array of array of real;
rows, cols: integer;

public
constructor Create(ARows, ACols: integer);
destructor Destroy;

procedure Vvod();
procedure Vivod();

function Add(const B: veshmatr): veshmatr;
function Sub(const B: veshmatr): veshmatr;
function Scale(f: double): veshmatr;
function Mult(const B: veshmatr): veshmatr;
function T: veshmatr;
function TypematriX(): string;
end;



constructor veshmatr.Create(ARows, ACols: integer);
begin
inherited Create;
Rows := ARows; Cols := ACols;
setlength(X, Rows, Cols);
end;
destructor veshmatr.Destroy;
begin
SetLength(X, 0, 0);
inherited;
end;

procedure veshmatr.Vvod();
var
iCols, iRows: integer;
begin
for iRows := 0 to Rows - 1 do
for iCols := 0 to Cols - 1 do
begin
write('element [', iRows,',',iCols,'] = ');
readln(X[iRows, iCols])
end;
Vivod();
end;

procedure veshmatr.vivod();
var
iCols, iRows: integer;
begin
if (Rows = 0) and (Cols = 0) then
writeln('<empty>');

for iRows := 0 to Rows - 1 do
begin
for iCols := 0 to Cols - 1 do
write(X[iRows, iCols]:12:3);
writeln;
end;
end;

function veshmatr.Add(const B: veshmatr): veshmatr;
var iCols, iRows: integer;
begin
if (Rows <> B.Rows) or (Cols <> B.Cols) then
result := VeshMatr.Create(0, 0)
else
begin
result := VeshMatr.Create(Rows, Cols);
for iRows := 0 to Rows - 1 do
for iCols := 0 to Cols - 1 do
result.X[iRows, iCols] := X[iRows, iCols] + B.X[iRows, iCols];
end
end;

function veshmatr.Sub(const B: veshmatr): veshmatr;
var iCols, iRows: integer;
begin
if (Rows <> B.Rows) or (Cols <> B.Cols) then
result := VeshMatr.Create(0, 0)
else
begin
result := VeshMatr.Create(Rows, Cols);
for iRows := 0 to Rows - 1 do
for iCols := 0 to Cols - 1 do
result.X[iRows, iCols] := X[iRows, iCols] - B.X[iRows, iCols];
end
end;

function veshmatr.Scale(f: double): veshmatr;
var iCols, iRows: integer;
begin
result := veshmatr.Create(Rows, Cols);
for iRows := 0 to Rows - 1 do
for iCols := 0 to Cols - 1 do
result.X[iRows, iCols] := f * X[iRows, iCols];

end;

function veshmatr.Mult(const B: veshmatr): veshmatr;
var i, j, k: integer;
begin
if (Cols <> B.Rows) then
result := VeshMatr.Create(0, 0)
else
begin
result := veshmatr.Create(Rows, B.Cols);
for i := 0 to Rows - 1 do
for j := 0 to B.Cols - 1 do
begin
result.X[i, j] := 0;
for k := 0 to Cols - 1 do
result.X[i, j] := result.X[i, j] + X[i, k] * B.X[k, j];
end
end;
end;

function veshmatr.T: VeshMatr;
var iCols, iRows: integer;
begin
result := VeshMatr.Create(Cols, Rows);
for iRows := 0 to Rows - 1 do
for iCols := 0 to Cols - 1 do
result.X[iCols, iRows] := X[iRows, iCols];
end;

function veshmatr.TypematriX(): string;
var
iCols, iRows: integer;
flag_diag, flag_O, flag_E: boolean;
begin
result := '';

if (Rows = Cols) then result := result + 'square'#10#13;

flag_diag := true;
flag_O := true; flag_E := true;

for iCols := 0 to Cols - 1 do
for iRows := 0 to Rows - 1 do
begin
flag_diag := flag_diag and
(
((iCols = iRows) and (X[iCols, iRows] <> 0))
or
((iCols <> iRows) and (X[iCols, iRows] = 0))
);
flag_O := (X[iCols, iRows] = 0);
flag_E :=flag_E and
(
((iCols = iRows) and (X[iCols, iRows] = 1))
or
((iCols <> iRows) and (X[iCols, iRows] = 0))
);
end;

if flag_diag then
result := result + 'diagonal'#10#13
else
result := result + 'non-diagonal'#10#13;
if flag_O then
result := result + 'O-matrix'#10#13;
if flag_E then
result := result + 'E-matrix'#10#13;
end;


function GetAnswer(s: string): boolean;
var answer: char;
begin
write(s); readln(answer);
result := answer in ['y', 'Y'];
end;

var
M1, M2: veshmatr;
s: Double;
Cm1, Cm2, Rm1, Rm2: integer;

begin
write('M1: rows = '); readln(Rm1);
write('M1: cols = '); readln(Cm1);
M1 := veshmatr.Create(Rm1, Cm1);
M1.Vvod();

write('M2: rows = '); readln(Rm2);
write('M2: cols = '); readln(Cm2);
M2 := veshmatr.Create(Rm2, Cm2);
M2.Vvod();

if GetAnswer('Add M1 + M2? y/n >>>_') then
begin
Writeln('__________Add_M1+M2________');
with M1.Add(M2) do
begin
Vivod(); Destroy();
end;
end;

if GetAnswer('Sub M1-M2? y/n >>>_') then
begin
Writeln('__________Sub_M1-M2________');
with M1.Sub(M2) do
begin
Vivod(); Destroy();
end;
end;

if GetAnswer('Mult s*M1? y/n >>>_') then
begin
write('vvedite s: '); readln(s);
Writeln('__________Mult_s*M1________');
with M1.Scale(s) do
begin
Vivod(); Destroy();
end;
end;

if GetAnswer('Mult M1*M2? y/n >>>_') then
begin
Writeln('__________Mult_M1*M2_______');
with M1.Mult(M2) do
begin
Vivod(); Destroy();
end;
end;

if GetAnswer('Traspon M1? y/n >>>_') then
begin
Writeln('______Transponirovanaya____');
with M1.T do
begin
Vivod(); Destroy();
end;
end;

if GetAnswer('Found type of M1? y/n >>>_') then
begin
Writeln(M1.TypematriX());
end;
if GetAnswer('Found type of M2? y/n >>>_') then
begin
Writeln(M2.TypematriX());
end;

M2.Destroy;
M1.Destroy;

readln
end.

Svetlana
Ну вот. Сравни с твоей реализацией, и скажи, с чем удобнее работать?

Конечно же этот вариант лучше,причём намного

Если честно, я думал, ты сама уже все сделала - столько времени прошло.

На самом деле я сдала эту работу и совсем о ней не вспоминала...Спасибо
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.