C++, функция. работающая с массивами
error C2664: 'mas' : cannot convert parameter 1 from 'short' to 'short [][3]'.
я понимаю, что ошибка, скорее всего, элементарная, но не могу найти
//Написать функцию, которая для заданных двухмерных массивов А, В
// и С типа double одинаковой размерности вычисляет массив D по
//формуле Di,j = Ai,j+ Bi,j*Ci,j
#include "stdafx.h"
#include <stdlib.h>
#include <iostream.h>
void mas (short A[3][3],short B[3][3],short C[3][3])
{
short D[3][3];
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
D[j]=A[j]+B[j]*C[j];
cout<<D[j]<<"\t";
}
cout<<"\n";
}
}
void main()
{
short M[3][3];
short N[3][3];
short K[3][3];
short L[3][3];
int i,j;
cout<<"massiv M\n";
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
M[j]=rand()%100;
cout<<M[j]<<"\t";
}
cout<<"\n";
}
cout<<"\n";
cout<<"massiv N\n";
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
N[j]=rand()%100;
cout<<N[j]<<"\t";
}
cout<<"\n";
}
cout<<"\n";
cout<<"massiv K\n";
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
K[j]=rand()%100;
cout<<K[j]<<"\t";
}
cout<<"\n";
}
cout<<"\n";
mas(M[3][3],N[3][3],K[3][3]);
}
Компилятор не может преобразовать конкретное значение типа short к массиву типа short
Этим вы передаете в функцию mas не сами массивы, а только значения элементов, имеющих индекс 3, по сколько в ваших массивах всего три элемента(0,1,2, т.е. максимальный индекс равен 2), то скорее всего вы передаете в функцию какое-то значение из не вашей области памяти - мусор.
Правильная передача массивов в функцию будет так:
По заданию указано тип массивов double, а у вас short =)
#include <cstdlib>
#include <ctime>
void mas(double** A, double** B, double** C, double** D,
const int x, const int y)
{
for (int j = 0; j < y; ++j)
{
for (int i = 0; i < x; ++i)
{
D[j] = A[j] + B[j] * C[j];
}
}
}
int main()
{
using std::cout;
// srand() устанавливает начальную точку
// для генерации псевдослучайных чисел
srand((unsigned)(time(0)));
// задаем размеры массивов
const int size_x = 3;
const int size_y = 3;
double** M = new double*[size_y];
double** N = new double*[size_y];
double** K = new double*[size_y];
double** L = new double*[size_y];
int i, j;
for (j = 0; j < size_y; ++j)
{
M[j] = new double[size_x];
N[j] = new double[size_x];
K[j] = new double[size_x];
L[j] = new double[size_x];
}
cout << "massiv M\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
M[j] = (double)(rand() % 100);
cout << M[j] << '\t';
}
cout << '\n';
}
cout << '\n';
cout << "massiv N\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
N[j] = (double)(rand() % 100);
cout << N[j] << '\t';
}
cout << '\n';
}
cout << '\n';
cout << "massiv K\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
K[j] = (double)(rand() % 100);
cout << K[j] << '\t';
}
cout << '\n';
}
cout << '\n';
mas(M, N, K, L, size_x, size_y);
// вывод результирующего массива
cout << "massiv L\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
cout << L[j] << '\t';
}
cout << '\n';
}
cout << '\n';
// освобождаем память
for (j = 0; j < size_y; ++j)
{
delete [] M[j];
delete [] N[j];
delete [] K[j];
delete [] L[j];
}
delete [] M;
delete [] N;
delete [] K;
delete [] L;
return 0;
}
PS Забыл еще сказать по поводу заголовков. Не знаю зачем вам понадобился stdafx.h - возможно вы использовали прекомпиляцию, но это с большей эффективностью будет работать при использовании MFC. А вот iostream.h и stdlib.h в стандарт C++ не входят. Это хедеры из C, которые оставили для совместимости. А в С++ нужно использовать соответствующие стандарту iostream и cstdlib и пространство имен std.
Так вот наверное то, что так хотел рассказать человек в вот этой теме
В задании ни слова не говорится о том, как должна выделяться память для массивов. Но, если угодно, есть и статический вариант.
#include <cstdlib>
#include <ctime>
// задаем размеры массивов
const int size_x = 3;
const int size_y = 3;
void mas(double A[][size_x], double B[][size_x],
double C[][size_x], double D[][size_x])
{
for (int j = 0; j < size_y; ++j)
{
for (int i = 0; i < size_x; ++i)
{
D[j] = A[j] + B[j] * C[j];
}
}
}
int main()
{
using std::cout;
// srand() устанавливает начальную точку
// для генерации псевдослучайных чисел
srand((unsigned)(time(0)));
double M[size_y][size_x];
double N[size_y][size_x];
double K[size_y][size_x];
double L[size_y][size_x];
int i, j;
cout << "massiv M\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
M[j] = (double)(rand() % 100);
cout << M[j] << '\t';
}
cout << '\n';
}
cout << '\n';
cout << "massiv N\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
N[j] = (double)(rand() % 100);
cout << N[j] << '\t';
}
cout << '\n';
}
cout << '\n';
cout << "massiv K\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
K[j] = (double)(rand() % 100);
cout << K[j] << '\t';
}
cout << '\n';
}
cout << '\n';
mas(M, N, K, L);
// вывод результирующего массива
cout << "massiv L\n";
for (j = 0; j < size_y; ++j)
{
for (i = 0; i < size_x; ++i)
{
cout << L[j] << '\t';
}
cout << '\n';
}
cout << '\n';
return 0;
}
Это не так.
Компилятор может неявно преобразовывать массив к указателю на первый элемент этого массива.
Но это не значит, что "компилятор воспринимает имя массива как указатель".
Массив самостоятельный тип данных, который может быть использован, в т.ч. передан в функцию без преобразования к указателю на первый элемент. Т.к. сам тип содержит свою размерность, то в этом случае нет необходимости передавать количество элементов отдельным параметром.
Единственное ограничение, что массив должен передаваться по ссылке, а не по значению, т.к. он не имеет конструктора копирования.
Я уже как-то подробно рассказывал об этом. Воспользуйтесь поиском.
В контексте данного решения, думаю, все же это необходимо. Каким же образом можно организовать расчет элементов массива в цикле, если функция не знает о том, сколько в массиве элементов? В примере с размещением массивов в статической области памяти я не передаю размеры массива, т.к. они объявлены глобально (иначе ведь никак нельзя, кроме использования пространства имен?).
Легко сказать...
Вот. Вроде нашел:
http://forum.codenet.ru/showpost.php?p=205152&postcount=44
Ну и поигрался для тренировки:
using namespace std;
template<class T, int N, int M>
void Test(const T(&)[N][M])
{
cout << "This is an array of " << N << " x " << M << " elements" << endl;
}
template<class T>
void Test(const T&)
{
cout << "This is not array" << endl;
}
template<class T, int N, int M>
void Fill(T(& a)[N][M])
{
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
a[j] = (i + 2) * 10 + j + 1;
}
template<class T, int N, int M>
void Print(const T(& a)[N][M])
{
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
cout << a[j] << " ";
cout << endl;
}
}
int main()
{
int a[3][4];
Test(a);
int *b;
Test(b);
Fill(a);
Print(a);
return 0;
}
Спасибо за находку! Подчерпнул для себя немало. Вот только применить эти знания в данной задаче не смог. С оператором sizeof все понятно: функция получает не массив, а указатель. (sizeof(A)/sizeof(A[0][0]) в списке параметров функции не работает.
Не знаю как передать массив по ссылке :confused:
Как-то так:
#include <cstdlib>
#include <ctime>
using std::cout;
using std::endl;
template<class T, int N, int M>
void mas(T(& A)[N][M], T(& B)[N][M],
T(& C)[N][M], T(& D)[N][M])
{
for (int j = 0; j < N; ++j)
{
for (int i = 0; i < M; ++i)
{
D[j] = A[j] + B[j] * C[j];
}
}
}
template<class T, int N, int M>
void FillMass(T(& a)[N][M])
{
for (int j = 0; j < N; ++j)
for (int i = 0; i < M; ++i)
a[j] = (double)(rand() % 100);
}
template<class T, int N, int M>
void PrintMass(T(& a)[N][M])
{
for (int j = 0; j < N; ++j)
{
for (int i = 0; i < M; ++i)
cout << a[j] << '\t';
cout << endl;
}
cout << endl;
}
int main()
{
// srand() устанавливает начальную точку
// для генерации псевдослучайных чисел
srand((unsigned)(time(0)));
const int size_x = 3;
const int size_y = 3;
double M[size_y][size_x];
double N[size_y][size_x];
double K[size_y][size_x];
double L[size_y][size_x];
FillMass(M);
cout << "massiv M\n";
PrintMass(M);
FillMass(N);
cout << "massiv N\n";
PrintMass(N);
FillMass(K);
cout << "massiv K\n";
PrintMass(K);
mas(M, N, K, L);
// вывод результирующего массива
cout << "massiv L\n";
PrintMass(L);
return 0;
}
Не всё дублирование и мешанину стилей убрал, но не в том суть. sizeof тут не нужен. Тут работает другой финт с компилятором - хитрое использование шаблонов. Шаблон типа T можно убрать в этой задаче, используя простое double.
Полагаю, что в той фразе участника Green имелось в виду:
В случае передачи обычной переменной (не являющейся массивом) есть возможность выбора, передавать по ссылке или по значению:
{ ... }
void func1(int& n) // передача по ссылке
{ ... }
...
int n = 10;
func1(n); // по значению
func2(n); // по ссылке
В случае же передачи в функцию массива такой возможности выбора нет - передавать массив можно только по ссылке. Т.е. когда вы делаете такой вызов функции:
{ ... }
...
int a[10];
// заполнение a
func3(a);
Вы передаете массив именно по ссылке, а не по значению, несмотря на то что знак & в функции не пишете.
Т.е. когда вы делаете такой вызов функции:
{ ... }
...
int a[10];
// заполнение a
func3(a);
Вы передаете массив именно по ссылке, а не по значению, несмотря на то что знак & в функции не пишете.
Нет.
В данном примере ты передаешь по указателю на первый элемент, т.к. запись int mas[] равнозначна записи int* mas.
Передача массива по ссылке выглядит так (используется именно знак &):
{ ... }
...
int a[10];
// заполнение a
func3(a);
Шаблон типа T можно убрать в этой задаче, используя простое double.
В том-то и дело, что нельзя! Ведь размеры массива как раз и передаются в функцию в виде параметров шаблона. Как тогда должно выглядеть объявление функции?
double (&C)[][], double (&D)[][]);
Это, конечно, приводит к ошибке компиляции:
Код:
void func3(int(&mas)[10])
{ ... }
Насколько я понимаю, возможны два варианта (кроме широко известных):
1. передача в шаблонную функцию, которая в качестве параметров типа принимает размеры массива;
2. передача по ссылке с прямым указанием размера массива (ну, или через глобальную переменную).
double (&C)[][], double (&D)[][]);
Это, конечно, приводит к ошибке компиляции
Я не говорил, что шаблон надо убрать совсем. Я говорил про такое:
void mas(double (&A)[N][M], double (&B)[N][M],
double (&C)[N][M], double (&D)[N][M]){/* ... */}
Тут нету шаблона типа T.
1. передача в шаблонную функцию, которая в качестве параметров типа принимает размеры массива;
2. передача по ссылке с прямым указанием размера массива (ну, или через глобальную переменную).
Ну и правильно. В варианте с шаблоном компилятор сам подставит размер массива, если я правильно понимаю механизм этой фишки. То есть, мы напишем только одну функцию для массивов разных размеров, а компилятор сделает из них несколько.