2016-11-28 8 views
-4

Итак, у меня есть программа в c, структурированная в 3 файлах: main, alloc.h и alloc.c: В основном у меня есть разметка указателя на другой указатель, на который я намереваюсь выделить символ * м массива:динамическое распределение функции 2d-массива

#include <stdio.h> 
#include <stdlib.h> 
#include "alloc.h" 
int main() 
{ 
    int **mat,n,m; 
    alloc_matrix(&mat,int &n,int &m); 
    return 0; 
} 

В alloc.ci есть следующие объявления:

#ifndef ALLOC_H_INCLUDED 
#define ALLOC_H_INCLUDED 
#include <stdio.h> 
#include <stdlib.h> 
void alloc_matrix(int***,int*,int*); 

#endif 

В alloc.ci имеют функцию:

void alloc_matrix(int ***mat,int *n,int *m) 
{ 
    printf("\nn = "); scanf("%d", n); 
    printf("\nm = "); scanf("%d", m); 
    *mat = (int**)calloc(*n,sizeof(int*)); 
    int i; 
    for(i = 0; i < *n; i++) 
    *(mat+i) = (int*)calloc(*m,sizeof(int)); 
} 

Но программа не работает. Она входит в какой-то цикл и не заканчивается. Если я выделил его в main, это сработает, но я не знаю, что я делаю неправильно в функции alloc.

+0

Нет двухмерного массива, а также указатель на один или что-то, что может его представлять! И быть 3-звездочным программистом C не является комплиментом. – Olaf

+0

Если это был ваш код: пожалуйста, не исправьте его ошибки в вопросе. Если это не так, отправьте весь вопрос с помощью * фактического * кода. –

+2

'alloc_matrix (& mat, int & n, int &m);' this is not legal C. Какой компилятор вы используете? –

ответ

2

Вот правильный код. Ваша ошибка заключалась в том, что в определении alloc_matrix вы использовали *(mat+i) в цикле выделения, который должен быть *(*mat+i) as, mat - int***, поэтому базовый адрес для 2D-массива будет находиться в *mat. Затем вам нужно переместить смещение i, а затем удалить ссылку на эту ячейку памяти для массива 1D.

Главная:

#include <stdio.h> 
#include <stdlib.h> 
#include "alloc.h" 
int main() 
{ 
    int **mat,n,m; 
    alloc_matrix(&mat,&n,&m); 
    return 0; 
} 

alloc.h

#ifndef ALLOC_H_INCLUDED 
#define ALLOC_H_INCLUDED 
#include <stdio.h> 
#include <stdlib.h> 
void alloc_matrix(int***,int*,int*); 

#endif 

alloc.c:

void alloc_matrix(int ***mat,int *n,int *m) 
{ 
    printf("\nn = "); scanf("%d", n); 
    printf("\nm = "); scanf("%d", m); 
    *mat = (int**)calloc(*n,sizeof(int*)); 
    int i; 
    for(i = 0; i < *n; i++) 
    *(*mat+i) = (int*)calloc(*m,sizeof(int)); 
} 

Код для функции чтения:

void read_matrix(int ***mat,int n,int m) 
    { 
     int i,j; 
     for(i = 0; i < n; i++) 
     for(j = 0; j < m; j++) 
     { 
      printf("mat[%d][%d] = ", i, j); 
      scanf("%d", (*(*mat+i))+j); 
     } 
    } 

Проблема в том, что он читает только первую строку, и она зависает.

+0

Кажется, что это работает. Но когда я пытаюсь его прочитать, он читает только первую строку. Что может быть проблемой с тем, как я его читаю? void read_matrix (int *** mat, int n, int m) { int i, j; для (i = 0; i NickName

+0

@NickName Я добавил правильную функцию 'read_matrix' – Nishant

+0

@NickName' void read_matrix (int *** 'Проблема состоит в том, что * три звезды *. Вам не нужно столько. Другая проблема:' * (* (мат + I) + J)); '. Это просто вздор. Доступ к матрице осуществляется следующим образом: ** 'mat [i] [j]' **. –

0
void alloc_matrix(int ***mat,int *n,int *m) 

В этой строке есть две проблемы. Ни один из них не смертелен, но оба они заслуживают исправления.

Первая проблема: матрица в этой программе представлена ​​как int**. Почему alloc_matrix принять int***? Все стандартные функции, которые выделяют что-то (malloc и friends), возвращают указатель на что-то. Это идиоматический способ делать вещи на C. Это уменьшает количество ваших звезд (будучи трехзвездным программистом на C, не является достижением, которым можно гордиться) и упрощает код. Функция должна быть изменена на

int** alloc_matrix(// but what's inside the() ? 

второй проблема, почему функция называется alloc_matrix подсказки пользователя и читать значение? Эти вещи не связаны с распределением. Функция должна делать одно и делать это хорошо. malloc предлагает ввести размер? fopen предлагает ввести имя файла? Эти вещи считались бы абсурдом первой степени, и это справедливо. Рекомендуется, чтобы читал размеры в другом месте и передал их alloc_matrix в качестве входных аргументов.Следовательно,

int** alloc_matrix(int n, int m) { // but what's inside the {}? 

Что остается alloc_matrix прост:

int** alloc_matrix(int n, int m) { 
    int** mat; // that's what we will return 
    int i; 
    mat = (int**)calloc(n, sizeof(int*)); 
    for(i = 0; i < n; i++) 
    // here comes the important part. 

Поскольку мы упростили alloc_matrix и уменьшили количество звезд в mat, что мы должны делать со старым телом цикла? Это было:

*(mat+i) = (int*)calloc(...); 

, но если убрать звезду, он становится

(mat+i) = (int*)calloc(...); 

, который является очевидной ерундой. Возможно, старая линия была проблемой. Тот факт, что он вызвал предупреждение о компиляторе, конечно, не говорит о его правильности. Итак, как исправить это? Вариантов не так уж много. Оказывается, что для восстановления здравомыслия, мы должны оставить старую левую сторону (написанную для трехзвездочного mat) нетронутой. Или, еще лучше, использовать эквивалентное, но более идиоматическое обозначение:

mat[i] = (int*)calloc(m, sizeof(int)); 

Так вся функция теперь становится

int** alloc_matrix(int n, int m) { 
    int **mat; 
    int i; 
    mat = (int**)calloc(n, sizeof(int*)); 
    for(i = 0; i < n; i++) 
    mat[i] = (int*)calloc(m, sizeof(int)); 
    return mat; 
} 

и он должен называться как

mat = alloc_matrix(n, m); 

Он часто говорил, что не следует делать результат calloc и друзьями. Но в этом случае бросок активировал предупреждение, которое помогло найти ошибку. Сейчас я оставляю броски на месте.

+0

Не могли бы вы как-то объяснить, как бросок включил это предупреждение и что такое предупреждение? –

+0

@BradenBest Литье произвело предупреждение, потому что тип в левой части задания не соответствовал типу с правой стороны. Оказалось, что левая сторона была неправильной. –

+1

ах, чтобы поймать ошибки новичка. Хотя я вполне уверен, что если кто-то искажает уровень косвенности в типе, они, вероятно, тоже будут бить броска. Помимо этого, я думаю, что наилучшим интересам азериков было бы уменьшить уровень косвенности и использовать лучший дизайн. «Int **» вряд ли полезен для матрицы, IMO. –