Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.03.2012, 13:05   #1
nartov55
Пользователь
 
Регистрация: 25.04.2010
Сообщений: 21
Смех Запутался с программой. Умножение матриц c++

Код:
//Проблема в функции multiplication.

#include "stdafx.h"
#include <clocale>
#include <conio.h>
#include <windows.h>

const int MAX_N=100, MAX_M=100;

void multiplication(int*,int*,int*,int,int,int);//Перемножает матрицы.
void prnt_arr(int*,int,int);//Выводит элементы матрицы на экран.
void read_arr(int*,int,int);//Считывает элементы матрицы с экрана.
char *format(int*,int,int);//Возвращает управляющую последовательность для функции printf.

void main()
{
	int A[MAX_N*MAX_M],B[MAX_N*MAX_M],C[MAX_N*MAX_M],n,m,k,t;
	bool b,c,d;
        setlocale(0,"Rus");
	do
	{
		system("cls");
		printf("Введите через пробел число строк и столбцов первой матрицы:");
		scanf("%d %d",&n,&m);
		printf("Введите через пробел число строк и столбцов второй матрицы:");
		scanf("%d %d",&t,&k);
		if(b=((n<=0)||(m<=0)||(k<=0)||(t<=0)))
			printf("Ошибка ввода! Число строк и столбцов матрицы должно быть больше нуля");
		if(c=(t!=m))
			printf("Ошибка ввода! Число столбцов первой матрицы должно быть равным числу строк второй. ");
		if(d=((n>MAX_N)||(m>MAX_M)||(t>MAX_N)||(k>MAX_M)))
			printf("Ошибка ввода! Число строк матрицы не должно превышать %d, а столбцов %d",MAX_N,MAX_M);
		if(b||c||d)
			getch();
	}while(b||c||d);
	printf("Введите коэффициенты первой матрицы:\n");
	read_arr(A,n,m);
	printf("Введите коэффициенты второй матрицы:\n");
	read_arr(B,m,k);
	multiplication(A,B,C,n,m,k);
	printf("Матрица произведения:\n");
	prnt_arr(C,n,k);
}

void read_arr(int *A,int n,int m)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			scanf("%d",&A[i*n+j]);
	}
}

void prnt_arr(int *A,int n,int m)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			printf(format(A,n,m),A[i*n+j]);
		printf("\n");
	}
}

char *format(int *A,int n,int m)
{
	char c[]="%0d ";
	int max=A[0], i;
	for(int i=1;i<n*m;i++)
		if(A[i]>max)
			max=A[i];
	for(i=0;max>0;i++)
		max/=10;
	c[1]=48+i;
	return c;
}

void multiplication(int *A, int *B, int *C, int n, int m, int p)
{
	for(int i=0;i<n;i++)
		for(int j=0;j<p;j++)
		{
			C[i*n+j]=0;
			for(int k=0;k<m;k++)
				C[i*n+j]+=A[i*n+k]*B[k*p+j];
		}
}

Последний раз редактировалось ACE Valery; 30.03.2012 в 13:39.
nartov55 вне форума Ответить с цитированием
Старый 30.03.2012, 14:43   #2
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

Проблема - в ф-ии format(). На "возвращаемую" ею после вызова строку посмотрите...
Vago вне форума Ответить с цитированием
Старый 30.03.2012, 15:18   #3
nartov55
Пользователь
 
Регистрация: 25.04.2010
Сообщений: 21
По умолчанию

С функцией format() всё ОК. Проблему решил, просто перепутал размерности при обращении к массивам в функциях prnt_arr(), read_arr() и естественно в функции multiplication() Вот, кому надо, нормальный код:
Код:
#include "stdafx.h"
#include <clocale>
#include <conio.h>
#include <windows.h>

const int MAX_N=100, MAX_M=100;

void prnt_arr(int*,int,int);//Выводит элементы матрицы на экран.
void read_arr(int*,int,int);//Считывает элементы матрицы с экрана.
char *format(int*,int,int);//Возвращает управляющую последовательность для функции printf.
void multiplication(int*,int*,int,int,int);//Перемножает матрицы.

void main()
{
	int A[MAX_N*MAX_M],B[MAX_N*MAX_M],n,m,k,t;
	bool b,c,d;
        setlocale(0,"Rus");
	do
	{
		system("cls");
		printf("Введите через пробел число строк и столбцов первой матрицы:");
		scanf("%d %d",&n,&m);
		printf("Введите через пробел число строк и столбцов второй матрицы:");
		scanf("%d %d",&t,&k);
		if(b=(n<=0)||(m<=0)||(k<=0)||(t<=0))
			printf("Ошибка ввода! Число строк и столбцов матрицы должно быть больше нуля");
		if(c=t!=m)
			printf("Ошибка ввода! Число столбцов первой матрицы должно быть равным числу строк второй. ");
		if(d=(n>MAX_N)||(m>MAX_M)||(t>MAX_N)||(k>MAX_M))
			printf("Ошибка ввода! Число строк матрицы не должно превышать %d, а столбцов %d",MAX_N,MAX_M);
		if(b||c||d)
			getch();
	}while(b||c||d);
	printf("Введите коэффициенты первой матрицы:\n");
	read_arr(A,n,m);
	printf("Введите коэффициенты второй матрицы:\n");
	read_arr(B,m,k);
	multiplication(A,B,n,m,k);
	printf("Матрица произведения:\n");
	prnt_arr(A,n,k);
}

void read_arr(int *A,int n,int m)
{
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			scanf("%d",&A[i*m+j]);
}

void prnt_arr(int *A,int n,int m)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			printf(format(A,n,m),A[i*m+j]);
		printf("\n");
	}
}

char *format(int *A,int n,int m)
{
	char c[]="%0d ";
	int max=A[0], i;
	for(int i=1;i<n*m;i++)
		if(A[i]>max)
			max=A[i];
	for(i=0;max>0;i++)
		max/=10;
	c[1]=48+i;
	return c;
}

void multiplication(int *A, int *B, int n, int m, int p)
{
	int C[MAX_N*MAX_M];
	for(int i=0;i<n;i++)
		for(int j=0;j<p;j++)
		{
			C[i*p+j]=0;
			for(int k=0;k<m;k++)
				C[i*p+j]+=A[i*m+k]*B[k*p+j];
		}
	memcpy(A,C,sizeof(C));
}

Последний раз редактировалось nartov55; 30.03.2012 в 15:29.
nartov55 вне форума Ответить с цитированием
Старый 30.03.2012, 16:46   #4
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

Цитата:
Сообщение от nartov55 Посмотреть сообщение
С функцией format() всё ОК.
Блажен, кто верует!.. Что с этими пятью байтами, выделяемыми в теле ф-ии под локальный массив c[], после выхода из ф-ии происходит, не подскажете?.. Трансляторы "Студий", кстати, на return c; кричат:
Код:
warning C4172: returning address of local variable or temporary
ADDED 18:38 CET
Цитата:
Сообщение от nartov55 Посмотреть сообщение
Вот, кому надо, нормальный код:
Э-э... Простите...
Код:
void multiplication(int *A, int *B, int n, int m, int p)
{
	int C[MAX_N*MAX_M];
	for(int i=0;i<n;i++)
		for(int j=0;j<p;j++)
		{
			C[i*p+j]=0;
			for(int k=0;k<m;k++)
				C[i*p+j]+=A[i*m+k]*B[k*p+j];
		}
	memcpy(A,C,sizeof(C));
}
ЭТО - НОРМАЛЬНЫЙ КОД?!..

Последний раз редактировалось Vago; 30.03.2012 в 19:38.
Vago вне форума Ответить с цитированием
Старый 31.03.2012, 18:33   #5
nartov55
Пользователь
 
Регистрация: 25.04.2010
Сообщений: 21
По умолчанию

Да, согласен. Были косяки, особенно с тем, что я возвращал в функции format() адрес не закрепленной за массивом области памяти. А memcpy() всё-же лучше заменить на memcpy_s(), хотя количество выделенной памяти под B[] и C[] было равно.

Код:
#include "stdafx.h"
#include <clocale>
#include <conio.h>
#include <windows.h>

const int MAX_N=100, MAX_M=100;

void multiplication(int*,int*,int,int,int);//Перемножает матрицы.
void prnt_arr(int*,int,int);//Выводит элементы матрицы на экран.
void read_arr(int*,int,int);//Считывает элементы матрицы с экрана.
void format(int*,char*,int,int);//Записывает управляющую последовательность для функции printf() в массив символов.

void main()
{
	int A[MAX_N*MAX_M],B[MAX_N*MAX_M],n,m,k,t;
	bool b,c,d;
        setlocale(0,"Rus");
	do
	{
		system("cls");
		printf("Введите через пробел число строк и столбцов первой матрицы:");
		scanf("%d %d",&n,&m);
		printf("Введите через пробел число строк и столбцов второй матрицы:");
		scanf("%d %d",&t,&k);
		if(b=(n<=0)||(m<=0)||(k<=0)||(t<=0))
			printf("Ошибка ввода! Число строк и столбцов матрицы должно быть больше нуля.\n");
		if(c=(t!=m))
			printf("Ошибка ввода! Число столбцов первой матрицы должно быть равным числу строк второй.\n");
		if(d=(n>MAX_N)||(m>MAX_M)||(t>MAX_N)||(k>MAX_M))
			printf("Ошибка ввода! Число строк матрицы не должно превышать %d, а столбцов %d.",MAX_N,MAX_M);
		if(b=(b||c||d))
			getch();
	}while(b);
	printf("Введите коэффициенты первой матрицы:\n");
	read_arr(A,n,m);
	printf("Введите коэффициенты второй матрицы:\n");
	read_arr(B,m,k);
	multiplication(A,B,n,m,k);
	printf("Матрица произведения:\n");
	prnt_arr(B,n,k);
}

void read_arr(int *A,int n,int m)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			scanf("%d",&A[i*m+j]);
	}
}

void prnt_arr(int *A,int n,int m)
{
	char C[]="%0d ";
	format(A,C,n,m);
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			printf(C,A[i*m+j]);
		printf("\n");
	}
}

void format(int *A,char *C,int n,int m)
{
	int max=A[0],i;
	for(i=1;i<n*m;i++)
		if(A[i]>max)
			max=A[i];
	for(i=0;max>0;i++)
		max/=10;
	C[1]=48+i;
}

void multiplication(int *A, int *B, int n, int m, int p)
{
	int *C=new int[n*p];
	for(int i=0;i<n;i++)
		for(int j=0;j<p;j++)
		{
			C[i*p+j]=0;
			for (int k=0;k<m;k++) 
				C[i*p+j]+=A[i*m+k]*B[k*p+j];
		}
	n*=sizeof(int)*p;
	memcpy_s(B,n,C,n);
	delete[]C;
}

Последний раз редактировалось nartov55; 31.03.2012 в 18:43.
nartov55 вне форума Ответить с цитированием
Старый 31.03.2012, 22:28   #6
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

- не боимся работать с двумерным массивом, как с одномерным - это требует определённого "закапывания" в архитектуру, что есть редкость среди нынешних студентов, привыкших не к книгам а к "Гугль в помощь!". Уже хорошо!

- индексы сами исправили. ЗдОрово!...

- про судьбу локальных переменных после завершения работы функции больше не забываем...

- громадный массив на стек уже не пихаем.

И на фоне всего этого безусловного, без иронии, прогресса - memcpy() !
Код:
...
#define ONE_LOOP_LESS
...
void read_arr( int* A,int nRows,int nCols ) {
 
   int   i ; 
#ifndef ONE_LOOP_LESS
   int   j ;

   for ( i = 0; i < nRows; i++ ) {
      for ( j = 0; j < nCols; j++ )
         scanf( "%d",&A[i*nCols+j] ) ;
   }
#else
   for ( i=0; i<nRows*nCols; i++ ) 
      scanf( "%d", &A[i] ) ;
#endif

}

 
void prnt_arr( int* A,int nRows, int nCols ) {
 
   int   i, j = 0 ;

#ifndef ONE_LOOP_LESS
   for ( i = 0; i < nRows; i++) {
      for ( j = 0; j < nCols; j++)
//1         printf(format(A,n,m),A[i*n+j]);
         printf( "%4d", A[i*nCols+j] ) ;
      printf("\n");
   }
#else
   for ( i = 0; i < nRows*nCols; i++ ) {
      printf( "%4d", A[i] ) ;
      if ( ++j == nCols ) {
         printf( "\n" ) ;
         j = 0 ;
      }
   }
#endif
}

void multiplication( int* A, int* B, int* C, int nRowsA, int nColsA, int nColsB ) {
   
   int   i, j, k ;

#ifndef ONE_LOOP_LESS
   for ( i = 0; i < nRowsA; i++ ) {
      for ( j = 0; j < nColsB;j++ ) {
         C[i*nColsB+j] = 0 ;
         for ( k = 0; k < nColsA; k++ )
            C[i*nColsB+j] += A[i*nColsA+k]*B[k*nColsB+j] ;
      }
   }
#else
   int   i0A = 0,
         i0B = 0 ;

   i = 0 ;
   for ( k = 0; k < nRowsA*nColsB; k++ ) {
      C[k] = 0 ;
      j = i0B ;
      for ( i = i0A; i < i0A+nColsA; i++ ) {
         C[k] += A[i]*B[j] ;
         j += nColsB ;
      }
      if ( ++i0B == nColsB ) {
         i0B = 0 ;
         i0A += nColsA ;
      }
   }
#endif
}
Закомментируйте #define - получится практически Ваша программа, только без этого time-consuming копирования.
Vago вне форума Ответить с цитированием
Старый 01.04.2012, 07:16   #7
nartov55
Пользователь
 
Регистрация: 25.04.2010
Сообщений: 21
По умолчанию

То есть лучше memcpy() не использовать ? Просто я подумал, зачем выделять память под ещё один массив, когда можно просто скопировать временный массив в уже имеющийся.

Последний раз редактировалось nartov55; 01.04.2012 в 07:19.
nartov55 вне форума Ответить с цитированием
Старый 01.04.2012, 11:52   #8
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

В этой задаче - безусловно НЕТ! Во первых, это чревато. Пока Вы - на уровне учебного задания, и у Вас выделены статические "квадратные" массивы одинаковой размерности и под A[], и под B[], Вы этого не заметите. Но представьте теперь, что Вы решили приблизить задачу к реальной жизни и выделяете под массивы ровно столько, сколько нужно, динамически:
Код:
   int *A, *B ;
   ...
   ввод n, m, k

   A = malloc(n*m*sizeof(int)) ;
   B = malloc(m*k*sizeof(int)) ;
   ...

   вычисления
   копирование C в A
(я показываю с malloc(), но с new будет то же самое).

А теперь вводим n = 1, m = 2, k = 3. Какого размера получится матрица C[]?.. А сколько у нас выделено под A[]?..

Ну а второе - это быстродействие. В реальной жизни к алгоритмам подобного типа предъявляется одно требование: они должны считать быстро! А заведение буфера и последующее копирование из этого буфера этому самому "быстро" как-то не способствуют...
Vago вне форума Ответить с цитированием
Старый 04.04.2012, 12:25   #9
nartov55
Пользователь
 
Регистрация: 25.04.2010
Сообщений: 21
По умолчанию

Да уж) Спасибо за объяснения
nartov55 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Умножение матриц BDA Общие вопросы C/C++ 2 20.11.2011 01:06
умножение матриц Rusya_00 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 06.01.2011 23:51
умножение матриц Mila Volkova Помощь студентам 3 25.12.2010 14:17
Умножение матриц) Guzal Общие вопросы C/C++ 1 26.10.2010 21:56
Умножение матриц Alyonka_v Помощь студентам 2 18.08.2009 21:51