Как правильно использовать функции с массивами

#c #matrix

#c #матрица

Вопрос:

Это небольшая программа, которую я написал, чтобы добавить 2 квадратные матрицы.

Когда я ввожу вторую матрицу, значения первой изменяются, и результат впоследствии становится ложным. Это довольно хорошо работает для матриц 2×2, но не для матриц большего размера. Алгоритм хорошо работает без использования функций. Пожалуйста, помогите мне решить эту проблему.

Вот код:

 #include <stdio.h>
#include <stdlib.h>

int n;
void PrintMatrix(int P[n][n])
{
    int i,j;
    for(i=0;i<n;i  )
    {
        printf("n");
        for(j=0;j<n;j  )
        {
            printf("%dt", P[i][j]);
        }
    }printf("n");
}
void ReadMatrix(int P[n][n])
{
    int i,j;
    for(i=0;i<n;i  )
    {
    printf("input row %dn", i 1);
        for(j=0;j<n;j  )
        {
        scanf("%d", amp;P[i][j]);
        }
    }
}
void AddMatrix(int P[n][n], int Q[n][n], int Result[n][n])
{
   int i,j;
    for(i=0;i<n;i  )
    {
    for(j=0;j<n;j  )
      {
        Result[i][j]=P[i][j] Q[i][j];
      }
    }
}

int main()
{
    int i,j;
    int A[n][n];
    int B[n][n];
    int Sum[n][n];

    printf("input matrix size:");
    scanf("%d", amp;n);

    printf("input first matrixn");
    ReadMatrix(A);
    PrintMatrix(A);

    printf("input second matrixn");
    ReadMatrix(B);
    PrintMatrix(B);

    AddMatrix(A,B,Sum);
    PrintMatrix(Sum);
    return 0;
}
  

Комментарии:

1. C должен знать ширину матрицы во время компиляции, это не может быть переменной.

2. @Barmar За исключением того, что ему не нужно знать ширину во время компиляции, это может быть переменная. VLA, добро пожаловать в 1999 год 🙂 Но, конечно, есть много случаев, когда VLAS не подходят.

3. @Lundin Хорошо, но ему нужно объявить переменные матрицы после чтения n , не так ли?

4. @Barmar Да, действительно, объявление массива должно быть справа от переменных измерения, смотрите Мой ответ ниже.

5. Я знал о VLA, но думал, что это применимо только к первому измерению.

Ответ №1:

Вы можете определить свой собственный тип матрицы с помощью структуры, такой как, например:

 typedef struct
{
  int*    data;
  size_t  width;
  size_t  height
} matrix_t;
  

Или, если у вас есть современный компилятор C, вы можете написать такие функции, как

 void func (size_t width, size_t height, int matrix[width][height])
  

Но, вероятно, предпочтительнее версия struct.


Редактировать

Что касается того, почему ваша программа глючит, вы должны инициализировать n значением. Если вы объявите массивы как массивы переменной длины размером [n][n] после момента, когда вы читаете n от пользователя, все должно работать нормально.

Комментарии:

1. int matrix[width][height] width и height должно быть постоянным или нет? современный стандарт C позволяет использовать массив переменной длины в качестве функционального параметра?

2. @ikh Им не обязательно быть постоянными, в современном C есть концепция массивов переменной длины.

3. C99 принимает массив переменной длины в качестве параметра функции, при условии, что параметры длины предшествуют самому массиву. В GNU C специально есть расширение синтаксиса, которое допускает пересылку параметров, например: void func (size_t width; size_t height; int matrix[width][height], size_t width, size_t height) {...} ; в данном случае width и height являются формальными параметрами, которые должны передаваться ПОСЛЕ matrix и просто объявляются заранее.

4. Это все еще не работает. проблема по-прежнему остается той же. Когда я считываю значения второй матрицы, значения первой изменяются. и я понятия не имею, почему это так.

5. @Gladson Ах, оказывается, это была просто тривиальная ошибка. Смотрите мой обновленный ответ.

Ответ №2:

если вы запустите это под gdb, вот что вы найдете (gdb) p A $ 14 = 0x7fffffffdfb0 (gdb) p B $ 15 = 0x7fffffffdfa0

независимо от того, какое «n» вы выберете, базовый адрес массива всегда отличается на 16, то есть работает целочисленная матрица 2 x 2

но если я введу длину как 3, программа вылетит. Происходит повреждение памяти. перед выполнением ввода (gdb) x / 12 A 0x7fffffffdfb0: 0 0 -255260739 52 0x7fffffffdfc0: -1 -1 -1 0x7fffffffdfd0: -8272 32767 -1 -1

после ввода: x / 12 0x7fffffffdfb0 0x7fffffffdfb0: 1 2 3 4 0x7fffffffdfc0: 5 6 7 8 0x7fffffffdfd0: 9 32767 -1 -1 нормально, поскольку я дал значения 1 2 3 4 5 6 7 8 9

но p A $ 16 = 0x7fff00000009 является ли этот доступ к нему причиной ошибки сегментации в PrintMatrix.

теперь, если вы измените свою программу на это

 int main()
{
    int i,j;

    printf("input matrix size:");
    scanf("%d", amp;n);
    int A[n][n];
    int B[n][n];
    int Sum[n][n];
  

ваши проблемы решены, и вы можете идти

Комментарии:

1. Спасибо за помощь. По крайней мере, это хорошее объяснение ошибки. должен признать, я многого из этого не понял. Я все еще новичок. 🙂