Динамический массив в struct calloc или указатели не работают, C - PullRequest
0 голосов
/ 25 января 2012

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

Я столкнулся со странной проблемой выделения памяти, которую, похоже, никто раньше не видел. Мой код:

yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;

yale* yale = (struct y*)calloc(1, sizeof(yale));

int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));    
int* JA = (int*)calloc(matrix_elements, sizeof(int));

printf("%d elements\n",matrix_elements);

yale->A = A;      // Value
yale->IA = IA;          // Row (X)
yale->JA = JA;     // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

list* tmp_list = input->first;

for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
    printf("Input Value: %d \n",tmp_list->point.value);
    A[i] = tmp_list->point.value;
    // Initialise the first row
    if(i == 0) IA[0] = tmp_list->point.x;
    else{
        // Add a new row index
        if(tmp_y != tmp_list->point.x){
            j++;
            IA[j] = i;
            tmp_y = tmp_list->point.x;
        }
    }
    JA[i] = tmp_list->point.y;
    tmp_list = tmp_list->next;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->JA[i]);

return yale;
}

А вот структура для Йельского университета:

typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;

Но программа выдает ошибку при первом соответствующем printf на первой итерации цикла.

      printf("%d,",yale->A[i]);

Я уверен: matrix_elements - целое число (9 в моем тестовом примере) matrix_rows является целым числом Все A / IA / JA заполнены правильными значениями (если вы поменяете yale-> A на A в printf, все будет работать нормально). Непосредственная привязка массива к указателям на структуру не влияет на результат. Неразборчивость, выговор, не типизирование, все безрезультатно.

Благодаря Xcode и gdb я также могу увидеть это в точке segfault. Указатели структуры делают НЕ , кажется, указывают на массивы

Ответы [ 2 ]

0 голосов
/ 29 января 2012

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

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

0 голосов
/ 25 января 2012

Чтобы его скомпилировать, мне нужно добавить его к фрагменту:

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

typedef struct y{
        int n;
        int m;
        int elements;
        int *IA;
        int *JA;
        int *A;
        } yale;

typedef struct list {
        struct list *next;
        struct point { int x,y,value; } point;
        } list;

typedef struct matrix_list {
        int elements;
        int m;
        int n;
        struct list *first;
        int *point;
        } matrix_list;

ОБНОВЛЕНИЕ: Я преобразовал программу в нечто более читаемое (ИМХО).Я не имею ни малейшего представления, что должны делать IA и JA, но приведенный ниже фрагмент должен быть эквивалентен OP.

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

struct y {
        unsigned int n;
        unsigned int m;
        unsigned int elements;
        unsigned int *IA;
        unsigned int *JA;
        int *A;
        } ;

struct list {
        struct list *next;
        struct point { unsigned int x,y; int value; } point;
        } ;

struct matrix_list {
        unsigned int elements;
        unsigned int m;
        unsigned int n;
        struct list *first;
        } ;

struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;

struct y *yale ;
struct list *tmp_list ;

yale = calloc(1, sizeof *yale);
assert (yale != NULL);

printf("%u elements\n",matrix_elements);

yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);

yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

    // Initialise the first row, set start condition
        // FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
    printf("Input Value: %d \n",tmp_list->point.value);
    yale->A[ii] = tmp_list->point.value;
        // Add a new row index
    if(tmp_y != tmp_list->point.x){
        jj++;
        yale->IA[jj] = ii;
        tmp_y = tmp_list->point.x;
    }
    yale->JA[ii] = tmp_list->point.y;
    if (++ii >= matrix_elements ) break;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%u,",yale->JA[i]);

return yale;
}

Примечание: я переместил (ii == 0) {} вывести условие из цикла и заменить однобуквенные индексы на двухбуквенные эквиваленты.Также: все индексы без знака (как и должно быть)

...