Как изменять элементы двумерного массива?

Рейтинг: 0Ответов: 1Опубликовано: 27.04.2023

В функции над элементами двумерного массива не проводятся арифметические операции. Грешу на путаницу с использованием указателей.

    void gauss(float*** arr, int m, int n, int st, int sc)
{
    float del = 0;
    del = (*arr)[sc][st];
    for (int i = 0; i<(m+2); i++)
        {
            (*arr)[sc][i]/=del;
        }
    for (int i =0; i<(n+1); i++)
    {
        if (i!=sc)
            {
                del = (*arr)[i][st];
                for (int j =0; j<(m+2); j++)
                {
                    (*arr)[i][j] -= del*(*arr)[sc][i];
                }
                
            }
        

    }
}

(Кратко про функцию: передаю указатель на двумерный массив, количество его строчек и столбцов, ведущий столбец и ведущую строчку. Сама функция должна осуществлять работу метода Гаусса над нашей матрицей. То есть все элементы ведущей строчки мы делим на элемент, стоящий на пересечении ведущего столбца и строчки. После этого из всех остальных строчек мы вычитаем элемент ведущей строки умноженный на элемент, расположенный на пересечении текущей строчки и ведущего столбца)

Создание и заполнение массива

float** arr;
arr = (float**)malloc(sizeof(float*)*(n+1));
 for (int i =0; i<(n+1); i++)
 {
    arr[i] = (float*)malloc(sizeof(float)*(m+2));
 }
 for (int i =0; i<(n+1); i++)
 {
    for (int j =0; j<(m+2); j++)
    {
        scanf("%f", &arr[i][j]);
    }
 }

Вызов функции

gauss(&arr, m, n, st, sc);

Ответы

▲ 1Принят

Каст массива к указателю

float[R][C] можно скастить только к float(*)[C]. В сигнатуре функции это также иногда пишется как float[][C]. Это допустимо, поскольку массивы по значению не передаются. Они автоматически кастятся к указателю на первый элемент (array to pointer decay).

Между многомерным массивом и указателем на указатель есть большая разница

  • Массивы просто хранят элементы последовательно, а многомерные массивы хранят последовательно подмассивы, поэтому многомерный массив удобно скастить к указтелю на первый элемент первого подмассива.
  • Указатель на указатель - это, в данном контексте, указатель, указывающий на последовательность из указателей, которые в свою очередь указывают на последовательность из чисел. Уже этот факт сам по себе говорит о том, что будут накладные расходы на указатели (обычно 8 байт на штуку), плюс фрагментация памяти и временные расходы на выделение памяти (выделение памяти в куче - это обращение к ядру ОС).

Вот так лучше всего обобщённо передавать массивы:

template<typename T>
void gauss(T* array, const int rows, const int cols) {
    for (int row = 0; row < rows; ++row)
        for (int col = 0; col < cols; ++col) 
            array[row*cols+col] = 0; // any expression
}

template<typename T, int Rows, int Cols>
void gauss(T (&array)[Rows][Cols]) { gauss(*array,Rows,Cols); }

Если нужно создать массив динамически, просто выделите весь кусок сразу:

auto array = new int[rows*cols];