Мой код перестал работать после того, как я изменил обозначение - PullRequest
0 голосов
/ 24 апреля 2020

Я очень новичок в указателях и массивах. Буду признателен за любую помощь.

Я пытаюсь написать код умножения матриц. Сначала мой код выглядел так:

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

void populate (int inp_row,int inp_col,int *arr);
void multiplication(int *arr1,int *arr2,int *arr3,int inp_row,int inp_col);
void display(int *arr,int inp_row,int inp_col);

int main(){
    srand(time(NULL));

    int row,col;

    printf("Enter number of rows: ");
    scanf("%d",&row);

    printf("Enter number of columns: ");
    scanf("%d",&col);

    int*arrA=(int *)malloc(row*col*sizeof(int));
    int*arrB=(int *)malloc(row*col*sizeof(int));
    int*arrC=(int *)malloc(row*col*sizeof(int));

    populate(row,col,arrA);
    populate(row,col,arrB);

    multiplication(arrA,arrB,arrC,row,col);

    printf("Your Matrices are as follows:\n=============================");
    printf("\nMatrix A is as follows:\n");
    display(arrA,row,col);
    printf("\nMatrix B is as follows:\n");
    display(arrB,row,col);
    printf("\nResults:\n=============================");
    printf("\nA * B is as follows:\n");
    display(arrC,row,col);
}

void populate (int inp_row,int inp_col,int *arr){
    int i,j;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            *(arr + inp_row*i + j)=rand()%11;
}

void multiplication(int *arr1,int *arr2,int *arr3,int inp_row,int inp_col){
    int i,j,k;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            *(arr3 + inp_row*i + j)=0;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            for(k=0;k<inp_col;k++)
                *(arr3 + inp_row*i + j)=(*(arr1 + inp_row*i +k)*(*(arr2 + inp_row*k + j))+*(arr3 + inp_row*i + j));
}

void display(int *arr,int inp_row,int inp_col){
    int i,k;

    for(i=0;i<inp_row;i++){
        printf("\n|");printf("%d",*(arr + inp_row*i + 0));
        for(k=0;k<(inp_col-1);k++)
            printf("  %d",*(arr + inp_row*i + k));
        printf("|");
    }
}

Печать казалась нормальной, она не перестала работать. Единственная проблема выглядела так, как будто это была математика. Умножение давало неправильные ответы. Я посмотрел на некоторые онлайн-ресурсы, и я подумал, что мой алгоритм выглядел хорошо. Затем я в основном начал разбираться с кодом ..

Я просмотрел свои лекционные заметки, изменил обозначения массивов и добавил сообщения об ошибках выделения памяти.

Теперь код перестает работать после запроса запроса входы и я не могу понять.

Я также новичок в этом обозначении динамических c массивов. Обычно я писал их как мой предыдущий код. Это может быть проблемой.

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

void populate (int inp_row,int inp_col,int **arr);
void multiplication(int **arr1,int **arr2,int **arr3,int inp_row,int inp_col);
void display(int **arr,int inp_row,int inp_col);

int main(){
    srand(time(NULL));

    int row,col;

    printf("Enter number of rows: ");
    scanf("%d",&row);

    printf("Enter number of columns: ");
    scanf("%d",&col);

    int**arrA=(int **)malloc(row*sizeof(int));
    int**arrB=(int **)malloc(row*sizeof(int));
    int**arrC=(int **)malloc(row*sizeof(int));

    if(arrA == NULL || arrB == NULL|| arrC == NULL){
        printf("\nCouldn't allocate the memmory!");
        return -1;}

    int i;
    for(i=0;i<col;i++){
        arrA[i]=(int*)malloc(sizeof(int)*col);
        arrB[i]=(int*)malloc(sizeof(int)*col);
        arrC[i]=(int*)malloc(sizeof(int)*col);
        if(arrA[i] == NULL || arrB[i] == NULL|| arrC[i] == NULL){
            printf("\nCouldn't allocate the memmory!");
            return -2;}}

    populate(row,col,arrA);
    populate(row,col,arrB);

    multiplication(arrA,arrB,arrC,row,col);

    printf("Your Matrices are as follows:\n=============================");
    printf("\nMatrix A is as follows:\n");
    display(arrA,row,col);
    printf("\nMatrix B is as follows:\n");
    display(arrB,row,col);
    printf("\nResults:\n=============================");
    printf("\nA * B is as follows:\n");
    display(arrC,row,col);
}

void populate (int inp_row,int inp_col,int **arr){
    int i,j;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            arr[i][j]=rand()%11;
}

void multiplication(int **arr1,int **arr2,int **arr3,int inp_row,int inp_col){
    int i,j,k,sum=0;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            arr3[i][j]=0;

    for(i=0;i<inp_row;i++)
        for(j=0;j<inp_col;j++)
            for(k=0;k<inp_col;k++){
                sum+=arr1[i][k]*arr2[k][j];}
    arr3[i][j]=sum;
}

void display(int **arr,int inp_row,int inp_col){
    int i,k;

    for(i=0;i<inp_row;i++){
        printf("\n|");printf("%d",arr[i][0]);
        for(k=0;k<(inp_col-1);k++)
            printf("  %d",arr[i][k]);
        printf("|");
    }
}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Если вы запускаете под gdb, ваша программа segfaulting in multiplication в первом l oop.

Это потому, что ваша первая партия malloc вызовов в main неверно.

Изменение:

int **arrA = (int **) malloc(row * sizeof(int));
int **arrB = (int **) malloc(row * sizeof(int));
int **arrC = (int **) malloc(row * sizeof(int));

В:

int **arrA = (int **) malloc(row * sizeof(int *));
int **arrB = (int **) malloc(row * sizeof(int *));
int **arrC = (int **) malloc(row * sizeof(int *));

int - это 32 бита, но [очевидно] вы на 64-битной машине, поэтому указатель составляет 64 бита. Таким образом, вы не выделяете достаточно места для указателей.

Это неопределенное поведение, которое может занять некоторое время, чтобы вызвать ошибку. Я предполагаю, что populate вызов уничтожил память, но не убил себя. Но то, что осталось, это недопустимые значения указателя, которые multiplication пытался разыменовать.


Если вы компилируете с -Wall -O2, помечается следующая строка в multiplication:

arr3[i][j] = sum;

С:

warning: ‘j’ may be used uninitialized in this function [-Wmaybe-uninitialized]

Как упоминал MrBens, эта строка, вероятно, должна go внутри l oop


Но математика все равно не выглядит прямо для меня. Я немного устал от умножения матриц, но я посмотрел его в википедии [и я готовлю кофе, так что ...]

Я думаю, вы должны обнулить sum внутри l oop.

Итак, я бы изменил это:

for (i = 0; i < inp_row; i++) {
    for (j = 0; j < inp_col; j++) {
        for (k = 0; k < inp_col; k++) {
            sum += arr1[i][k] * arr2[k][j];
        }
    }
}
arr3[i][j] = sum;

На:

for (i = 0; i < inp_row; i++) {
    for (j = 0; j < inp_col; j++) {
        sum = 0;
        for (k = 0; k < inp_col; k++)
            sum += arr1[i][k] * arr2[k][j];
        arr3[i][j] = sum;
    }
}
0 голосов
/ 24 апреля 2020

Я думаю, что ваша ошибка в этом разделе:

for(i=0;i<inp_row;i++)
    for(j=0;j<inp_col;j++)
        for(k=0;k<inp_col;k++){
            sum+=arr1[i][k]*arr2[k][j];}
        arr3[i][j]=sum;}

Последняя строка не включена в расчет каждой строки! Вы должны изменить это на это:

for(i=0;i<inp_row;i++)
{
    for(j=0;j<inp_col;j++)
    {
        for(k=0;k<inp_col;k++)
        {
            sum+=arr1[i][k]*arr2[k][j];
        }
        arr3[i][j]=sum;
    }
}

Что касается остальной части кода, у вас есть некоторые ошибки, связанные с языком, как упоминалось PiRocks . Самым кричащим является то, что вы не освобождаете ресурсы, которые используете! Это плохая практика и просто неправильно.

Добавьте это в конец своей основной функции, и обязательно поймите значение этого:

for(i = 0; i < col; i++)
{
    free(arrA[i]);
    free(arrB[i]);
    free(arrC[i]);
}

free(arrA);
free(arrB);
free(arrC);

Вы обязательно должны получить привычка использовать valgrind при работе с динамическими c выделениями памяти.

Правка: Крейг прав в том, что вы должны начинать суммирование с 0 на каждой итерации, пропустил это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...