Сложение матриц / возврат массива - PullRequest
0 голосов
/ 02 ноября 2018

Я новичок в C, и у меня есть некоторые проблемы с программированием функции, которая будет брать две матрицы, складывать их и возвращать результат в качестве третьей матрицы. Основная проблема заключается в том, чтобы заставить функцию возвращать массив .

В Интернете я нашел несколько решений о том, как вернуть массив, возвращая указатель на первый элемент массива, но не смог применить его к моей ситуации с двумерным массивом. Я знаю, как добавить матрицы в основную функцию, но мне нужно разбить программу на несколько функций.

Вот мой код

float matrix_add(float matrixA[MAX_SIZE][MAX_SIZE], float matrixB[MAX_SIZE][MAX_SIZE], int column, int line)
{
   float matrixRes[MAX_SIZE][MAX_SIZE];
    for (int i=0; i<column; i++)
    {
        for (int j=0; j<line; j++)
        {
            matrixRes[i][j]=matrixA[i][j]+matrixB[i][j];
        }
    }
    return matrixRes;
}

Я попробовал одно из решений, которое нашел в Интернете:

float *matrix_add(float matrixA[MAX_SIZE][MAX_SIZE], float matrixB[MAX_SIZE][MAX_SIZE], int column, int line)
{
   static float *matrixRes[MAX_SIZE][MAX_SIZE];
    for (int i=0; i<column; i++)
    {
        for (int j=0; j<line; j++)
        {
            *matrixRes[i][j]=matrixA[i][j]+matrixB[i][j];
        }
    }
    return matrixRes;

Но есть несколько проблем с этим - я не понимаю этого, и функция все еще не работает - она ​​возвращает ложные результаты, и в компиляторе есть предупреждение «возврат из несовместимого типа указателя». Кроме того, я не уверен, как это назвать (возможно, это проблема с решением, которое я нашел?). Я хотел получить какое-то конкретное значение из массива и вызвал такую ​​функцию

matrix_add(matrixA, matrixB, column, line)[value][value]);

Где matrixA и B - некоторые двумерные массивы, столбец и строка - целочисленные переменные. Это возвращает ошибку (подписанное значение не является ни массивом, ни указателем, ни вектором)

Можете ли вы указать мне правильное направление и сказать, как заставить эту функцию работать (и объяснить решение)? MAX_SIZE - это предопределенное значение (10), так как в этом назначении я должен использовать статическое выделение памяти (но если вы можете помочь мне с помощью динамического выделения, это нормально) Основная функция выглядит следующим образом

int main()
{
    int column_num[2], line_num[2];
    float matrixA[MAX_SIZE][MAX_SIZE], matrixB[MAX_SIZE][MAX_SIZE];
        scanf("%d", &column_num[0]);
        scanf("%d", &line_num[0]);
        matrix_load_val(matrixA, column_num[0], line_num[0]);
        scanf("%d", &column_num[1]);
        scanf("%d", &line_num[1]);
        matrix_load_val(matrixB, column_num[1], line_num[1]);


    }
    for (int i=0; i<column_num[0]; i++)
    {
        for(int j=0; j<line_num[0]; j++)
        {
            printf("%0.5g\n", matrix_add(matrixA, matrixB, i, j));
        }
    }

matrix_load_val - это процедура, которая запрашивает у пользователя значения и помещает их в результирующую матрицу (она работает точно, проверено)

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Я рекомендую передать в матрицу другую матрицу, которую можно использовать для заполнения результата:

void matrix_add(float matrixA[MAX_SIZE][MAX_SIZE], float matrixB[MAX_SIZE][MAX_SIZE], float matrixRes[MAX_SIZE][MAX_SIZE], int column, int line)
{
    for (int i=0; i<column; i++)
    {
        for (int j=0; j<line; j++)
        {
            matrixRes[i][j]=matrixA[i][j]+matrixB[i][j];
        }
    }
}

После того, как вы позвоните matrix_add, matrixRes будет иметь результаты. Это работает, потому что вы передаете адрес matrixRes в matrix_add, то есть matrixRes не является локальным для matrix_add, как в случае column и line.

0 голосов
/ 02 ноября 2018

Ваша попытка не слишком далеко. У вас есть реальная идея объявить массив static и «вернуть его», но сначала нам нужно понять, что это значит.

В Си типы массивов - странные звери. Вы не можете напрямую вернуть массив значений, как в других языках. Вместо этого вы возвращаете указатель. Мы говорим, что тип массива распадается на указатель. Для одномерных массивов это не так уж страшно:

float *get_array(void) {
    static float my_array[2] = { 1, 2 };
    return my_array;
}

float *result = get_array();

Для многомерных массивов затухание гораздо сложнее и страшнее :

Обратите внимание, что когда применяется затухание массива в указатель, многомерный массив преобразуется в указатель на его первый элемент (например, указатель на его первую строку или на его первую плоскость): затухание массива в указатель равно применяется только один раз.

Чтобы вернуть указатель на двумерный массив, синтаксис: :

float (*get_array(void))[2] {
    static float my_array[2][2] = { { 1, 2 }, { 3, 4 } };
    return my_array;
}

float (*result)[2] = get_array();

Применяя это, мы можем настроить ваш код, чтобы он работал (некоторые скобки опущены для краткости):

float (*matrix_add(float matrixA[MAX_SIZE][MAX_SIZE], float matrixB[MAX_SIZE][MAX_SIZE], int column, int line))[MAX_SIZE]
{
    static float matrixRes[MAX_SIZE][MAX_SIZE];
    for (int i = 0; i < column; ++i)
        for (int j = 0; j < line; ++j)
            matrixRes[i][j] = matrixA[i][j] + matrixB[i][j];
    return matrixRes;
}

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

void matrix_add(
    const float matrixA[MAX_SIZE][MAX_SIZE], /* "input parameter" */
    const float matrixB[MAX_SIZE][MAX_SIZE], /* "input parameter" */
    float matrixRes[MAX_SIZE][MAX_SIZE], /* "output parameter" */
    int column,
    int line)
{
    for (int i = 0; i < column; ++i)
        for (int j = 0; j < line; ++j)
            matrixRes[i][j] = matrixA[i][j] + matrixB[i][j];
}

Обратите внимание, что мы также сделали входные параметры const, чтобы отразить тот факт, что функция не изменяет эти массивы. Это проясняет из прототипа функции, которые являются входными и выходными параметрами.

* Я также позволил себе немного переформатировать и изменить i++ на ++i, потому что это хорошая привычка , хотя в данном конкретном случае это не имеет значения.

...