Передать переменной значение функции(матрица) c++
У меня есть функция, заполняющая матрицу числами
template <class Type>
Type mass(Type a, Type b){
Type **arr;
arr=new Type*[a];
for (int i=0;i<a;i++) arr[i]=new int[b];
for (int i = 0; i < a; i++){
for (int j = 0; j < b; j++)
cin >> arr[i][j];
}
return **arr;
}
А потом я хочу использовать значение этой функции в другой. Для этого я прописываю
Type arr = mass(a,b);
В таком случае появляется ошибка error: subscripted value is neither array nor pointer
if(arr[i][j] != 0)
Что это такое и как с этим бороться ?
Код целиком:
#include <iostream>
#include <iomanip>
using namespace std;
template <class Type>
Type mass(Type a, Type b){
Type **arr;
arr=new Type*[a];
for (int i=0;i<a;i++) arr[i]=new int[b];
for (int i = 0; i < a; i++){
for (int j = 0; j < b; j++)
cin >> arr[i][j];
}
return **arr;
}
template <class Type>
void index(Type a, Type b){
Type arr = mass(a,b);
int ind=0;
bool ok = false;
for (int i = 0; i < a; i++){
ind++;
for (int j = 0; j < b; j++){
if (arr[i][j]!=0){
ok = true;
break;
}
}
if(ok){
cout<<ind;
break;
}
}
}
template <class Type>
void new_matr(Type a, Type b){
Type arr = mass(a,b);
Type** matr;
matr = new Type*[a];
for (int i=0;i<a;i++) matr[i]=new Type[b];
for (int i = 0; i < a; ++i){
bool ok = false;
for (int j = 0; j < b; ++j){
if(arr[i][j] != 0){
ok = true;
}
}
if(ok){
for (int j = 0; j < b; ++j){
matr[i][j]=arr[i][j];
cout << matr[i][j] << " ";
}
cout << endl;
}
}
cout << endl;
}
int main(){
int n,m;
cin>>n>>m;
new_matr(n, m);
index(n, m);
}
Задача: принять матрицу размера m*n, удалить из неё все столбцы и строки заполненные нулями. Использовать шаблоны чтобы программа работала для типов int, float, double
Ответы (2 шт):
#include <iostream>
#include <iomanip>
using namespace std;
template <class Type>
void mass(Type** arr, int a, int b) {
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++)
cin >> arr[i][j];
}
}
template <class Type>
void deleteZeroRowsAndColumns(Type** arr, int a, int b) {
mass(arr, a, b);
Type** matr;
matr = new Type * [a];
for (int i = 0; i < a; i++) matr[i] = new Type[b];
//в массив matr занесем только строки без нулей из исходной матрицы
int row = 0;
for (int i = 0; i < a; ++i) {
bool hasNotZero = false;
for (int j = 0; j < b; ++j) {
hasNotZero |= (bool)arr[i][j]; //row будет равно false, если все элементы строки нулевые, в противном случае - true
}
if (hasNotZero) {
for (int j = 0; j < b; ++j) {
matr[row][j] = arr[i][j];
}
row++;
}
}
//повторяем то же самое, но только со столбцами, но только берем уже новую матрицу без нулевых строк
int column = 0;
for (int i = 0; i < b; ++i) {
bool hasNotZero = false;
for (int j = 0; j < row; ++j) {
hasNotZero |= (bool)matr[j][i];
}
if (hasNotZero) {
for (int j = 0; j < row; ++j) {
arr[j][column] = matr[j][i];
}
column++;
}
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
int main() {
int n, m;
cin >> n >> m;
int** arr;
arr = new int*[n];
for (int i = 0; i < n; i++) arr[i] = new int[m];
deleteZeroRowsAndColumns<int>(arr, n, m);
return 0;
}
Когда вы делаете шаблонную функцию по созданию матрицы, вам нужно задать тип данных, который будет храниться в матрице и размерность матрицы. Т.е. аргументами функции будут 2 int - размерность, независимо от того, какой тип данных вы храните в матрице. А вернуть вы хотите созданную матрицу. А как выглядит у вас матрица? Матрица выделяется динамически и представляет собой указатель на массив указателей, т.е. возвращаете вы указатель на указатель.
template <class Type>
Type** mass(int a, int b) // возвращаемое значение - указатель на указатель
// аргументы - размерность - 2 int
{
Type **arr = new Type*[a]; // выделяем память под массив типа Type*
for (int i=0; i<a; ++i)
arr[i] = new Type[b]; // выделяем память под массив типа Type
for (int i = 0; i < a; ++i)
for (int j = 0; j < b; ++j)
cin >> arr[i][j];
return arr; // матрица - это указатель на указатель
}
template <class Type>
void index(int a, int b) // аргументы - индексы типа int
{
Type** arr = mass(a,b); // матрица - это указатель на указатель
Кстати, непонятно зачем нужна функция index() - она у вас подсчитывает количество строк (которое и так известно) и выводит на экран. Т.е. её результатами воспользоваться невозможно.
Ну и ещё замечание - матрицу скорее всего вы должны создать 1 раз, а потом вызывать для неё какие-то функции. Т.е. в функции вы должны передавать матрицу и размерность. Причем если вы меняете матрицу в смысле перевыделяете память, то вам нужно передавать либо ссылку/указатель на двойной указатель, либо возвращать двойной указатель. Потому что сейчас вы дважды создаете матрицу - один раз в index(), второй раз в new_matr(). Т.е. сигнатуры должны выглядеть так
template <class Type>
void new_matr(Type ***arr, int a, int b);
// либо так
template <class Type>
void new_matr(Type& **arr, int a, int b);
// либо так
template <class Type>
Type** new_matr(Type **arr, int a, int b);
Чтобы не писать такие длинные списки инициализации, создайте структуру и поместите эти данные в неё. И код становится читабельнее - вы передали в функцию матрицу и вернули из функции матрицу. Ну и чтобы не дублировать код добавьте вспомогательную функцию - Print(), которая просто выводит матрицу на экран.
template <class Type>
struct MyMatrix
{
Type **arr;
int a, b;
}
template <class Type>
MyMatrix new_matr(MyMatrix &m);
template <class Type>
void Print(const MyMatrix &m);
Кроме того, для удаления нулевых столбцов и строк не обязательно перевыделять память - можно просто копировать данные и уменьшать размерность в исходной матрице. В результате память останется выделена под большую матрицу, а храниться в ней будет меньше данных.
