Передать переменной значение функции(матрица) c++

Рейтинг: -1Ответов: 2Опубликовано: 13.03.2023

У меня есть функция, заполняющая матрицу числами

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

Ответы

▲ 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);

Кроме того, для удаления нулевых столбцов и строк не обязательно перевыделять память - можно просто копировать данные и уменьшать размерность в исходной матрице. В результате память останется выделена под большую матрицу, а храниться в ней будет меньше данных.

▲ 0
#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;
}

Вывод в консоль