所以我有一个c结构的程序,有3个文件:main,alloc.h和alloc.c: 在主要我有一个指向另一个指针的指针的deccalaration我打算分配一个n * m数组:
#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.c中,我有以下声明:
#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));
}
但该程序不起作用。它进入某种循环并且不会结束。
如果我在main
中分配它,它会起作用,但我不知道我在alloc
函数中做错了什么。
答案 0 :(得分:2)
这是正确的代码。您的错误是在alloc_matrix
的定义中,您在分配循环中使用了*(mat+i)
,它应该是*(*mat+i)
,因为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);
}
}
问题在于它只读取第一行并冻结。
答案 1 :(得分: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
和朋友的结果。但在这种情况下,演员已启用警告,这有助于找到错误。我现在要离开演员了。