2016-11-28 2 views
-4

Donc, j'ai un programme en c structuré en 3 fichiers: main, alloc.h et alloc.c: En main j'ai la décréation d'un pointeur vers un autre pointeur auquel j'ai l'intention d'allouer un tableau * m:allocation dynamique de la fonction de tableau 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; 
} 

Dans alloc.ci avoir les déclarations suivantes:

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

#endif 

Dans alloc.ci avoir la fonction:

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)); 
} 

Mais le programme ne fonctionne pas. Il entre dans une sorte de boucle et ne s'arrête pas. Si je l'alloue en main cela fonctionnerait mais je n'ai aucune idée de ce que je fais mal dans la fonction alloc.

+0

Il n'y a pas de tableau 2D, ni de pointeur sur un ou quelque chose qui peut en représenter un! Et être un programmeur C 3 étoiles n'est pas un compliment. – Olaf

+0

Si c'était votre code: veuillez ne pas corriger ses erreurs dans la question. Si ce n'est pas le cas, veuillez reporter l'ensemble de la question avec le code * réel *. –

+2

'alloc_matrix (& mat, int & n, int &m);' ce n'est pas légal C. Quel compilateur utilisez-vous? –

Répondre

2

Voici le code correct. Votre erreur était que dans la définition de alloc_matrix, vous avez utilisé *(mat+i) dans la boucle d'allocation, qui devrait être *(*mat+i) comme, mat est un int*** donc l'adresse de base pour le tableau 2D serait dans *mat. Ensuite, vous devez déplacer par décalage i, puis de-référence cet emplacement de mémoire pour le tableau 1D.

principal:

#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)); 
} 

Le code de la fonction de lecture:

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); 
     } 
    } 

Le problème avec cela est qu'il ne lit que la première rangée et qu'il se fige.

+0

Il semble fonctionner.Mais quand j'essaie de le lire, il ne lit que la première rangée.Que peut être le problème avec la façon dont je le lis? void read_matrix (int *** mat, int n, int m) { int i, j; pour (i = 0; i NickName

+0

@NickName J'ai ajouté la bonne fonction 'read_matrix' – Nishant

+0

@NickName' void read_matrix (int *** 'Le problème est * les trois étoiles *. Vous n'avez pas besoin de tant de choses. * L'autre problème est' * (* (mat + i) + j)); C'est juste un non-sens. Une matrice est accédée comme ceci: ** 'mat [i] [j]' **. –

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

Il y a deux problèmes dans cette ligne. Aucun n'est fatal mais les deux valent la peine d'être réparés.

Premier problème: Une matrice dans ce programme est représentée par int**. Pourquoi alloc_matrix accepte-t-il un int***? Toutes les fonctions standard qui allouent quelque chose (malloc et amis) renvoient un pointeur sur ce quelque chose. C'est une façon idiomatique de faire les choses en C. Elle réduit votre nombre d'étoiles (être un programmeur C trois étoiles n'est pas une réalisation dont on peut être fier) ​​et simplifie le code. La fonction doit être modifiée pour

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

Le deuxième problème est, pourquoi une fonction appelée alloc_matrix invite l'utilisateur et lire les valeurs? Ces choses ne sont pas liées à l'allocation. Une fonction devrait faire une chose et le faire bien. Est-ce que malloc vous invite à entrer la taille? Est-ce que fopen vous invite à entrer le nom de fichier? Ces choses seraient considérées comme un non-sens du premier degré, et à juste titre. Il est conseillé de lire les tailles ailleurs et de les passer à alloc_matrix comme arguments d'entrée.Par conséquent,

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

Ce qui reste de alloc_matrix est simple:

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. 

Puisque nous avons alloc_matrix simplifié et réduit le nombre d'étoiles à mat, que devons-nous faire avec le vieux corps de la boucle? Il était:

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

mais si on enlève une étoile, il devient

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

qui est un non-sens évident. Peut-être que la vieille ligne était un problème. Le fait qu'il ait provoqué un avertissement de compilateur ne justifie certainement pas son exactitude. Alors, comment le corriger? Il n'y a pas trop d'options. Il s'avère que pour restaurer la santé mentale, nous devons laisser l'ancienne partie gauche (écrite pour le trois étoiles mat) intacte. Ou, mieux encore, utiliser une notation équivalente mais plus idiomatiques:

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

Ainsi, la fonction entière devient maintenant

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; 
} 

et il devrait être appelé comme

mat = alloc_matrix(n, m); 

On dit souvent que l'on ne devrait pas diffuser le résultat de calloc et ses amis. Mais dans ce cas, la distribution a permis un avertissement qui a aidé à trouver un bug. Je laisse les moulages en place pour le moment.

+0

Pourriez-vous expliquer précisément comment la distribution a activé cet avertissement, et quel est l'avertissement? –

+0

@BradenBest La distribution a produit un avertissement car le type du côté gauche de l'assignation ne correspondait pas au type du côté droit. Il s'est avéré que le côté gauche était faux. –

+1

ah, pour attraper les erreurs de débutant. Bien que je sois à peu près sûr que si l'on tâtonne le niveau d'indirection sur le type, ils vont probablement fouiller la distribution aussi bien. En dehors de cela, je pense qu'il serait dans le meilleur intérêt des demandeurs de réduire le niveau d'indirection et d'utiliser un meilleur design. Un 'int **' n'est guère utile pour une matrice, IMO. –