我知道有很多问题属于"多维数组"。由于我找不到能解决问题的具体问题,我终于要问了。
目标:存储其值从用户输入的2D数组。
Method-01 :为数组使用任意大的初始大小。
代码:
int method_arbit()
{
int n, m;
int i, j;
float myarray[100][100];
printf("Enter the number of rows: ");
scanf("%d", &m);
printf("Enter the number of columns: ");
scanf("%d", &n);
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
scanf("%f", &myarray[i][j]);
}
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf("[%d][%d] = %f", i, j, myarray[i][j]);
}
}
评论:此功能按预期工作!
方法-02 :使用动态内存分配。
代码:
int method_dynamic()
{
int n, m;
int i, j;
float **myarray; // m x n matrix
printf("Enter the number of rows: ");
scanf("%d", &m);
printf("Enter the number of columns: ");
scanf("%d", &n);
myarray = malloc(m*sizeof(float*));
for(i=0; i<m; i++)
myarray[m] = malloc(n*sizeof(float));
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
scanf("%f", &myarray[i][j]);
}
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf("[%d][%d] = %f", i, j, myarray[i][j]);
}
}
评论:此方法在接受输入时会产生分段错误。
Q1:我很难调试这个。而且,我发现更难理解这种行为背后的原因。 我对指针和动态内存分配有基本的了解。 我希望详细解释我所犯的错误以及我可能忽略的概念。
Q2:如果我们在编译时不知道数组的大小,我们应该总是动态分配数组吗?
OR
什么时候建议使用动态分配的数组?
我知道的一个用例是在处理函数和从它们返回数组时。
答案 0 :(得分:0)
OP的问题是使用错误的索引@forcebru
myarray = malloc(m*sizeof(float*));
assert(myarray); // Do some allocation check;
for(i=0; i<m; i++) {
// v----- here
// myarray[m] = malloc(n*sizeof(float));
myarray[i] = malloc(n*sizeof(float));
assert(myarray[i]);
}
答案 1 :(得分:0)
您可以将多维数组声明为大数组。
int n, m;
int i, j;
float* myarray; // m x n matrix
std::cout<<"Enter the number of rows: \n";
scanf("%d", &m);
std::cout << "Enter the number of columns: \n";
scanf("%d", &n);
myarray = (float*)malloc( m * n * sizeof(float) );
for(i=0; i<m; i++)
{
for (j = 0; j<n; j++) {
scanf("%f", &(myarray[i * n + j]));
}
}
for(i=0; i<m; i++)
{
for(j=0; j<n; j++) {
printf("[%d][%d] = %f", i, j, (myarray[i * n + j]));
}
}
答案 2 :(得分:0)
Q1 :你需要一块内存来容纳一个2维的浮点数,你的初始代码为
float **myarray;
myarray = malloc( m * sizeof(float*) );
m = 3; // for this example
n = 5; // for this example
是一个问题,因为您的两个维度是 m 和 n 。您没有在那里使用 n 。你也在做sizeof(float*)
并且你不希望指针的大小浮动。发生的事情是,如果sizeof( pointer to float)
= {64位系统上的8个字节,32位系统上的4个字节},那么您的malloc分别保留24或12个字节。但是当你真正需要 m x n 单位时,只有 m 单位的内存{15个单位的15个唯一值,类型为float}
所以你想要一个 float 占用内存的大小。因此你应该做
float *myarray; // not a double pointer
myarray = (float *) malloc( m * n * sizeof( float ) );
例如,如果sizeof(float)= 4个字节,那么如果m = 3且n = 5,则得到4x15 = 60个字节的内存。 malloc返回一个指向那块内存的指针,然后将它的类型转换为你声明的指针。
此时,您需要索引60个字节的总块,其中*myarray
指向它的开头,就是这样。除了指向它的开头的指针myarray
之外,编译器不知道如何排列或使用该块内存,它是浮点数据类型。 malloc或编译器无法知道您在使用myarray[][]
约定时尝试使用的行或列大小 m 和 n 。
在你的系统上,如果sizeof(float)是4,那么60字节块中的每4个字节可以是一个浮点值,给你15个值。
如果你想使用约定myarray[i][j]
你不能,因为你使用了malloc,它不知道如何划分60字节的内存块。
您必须手动将[row] [col]索引编入myarray,例如
m = 3; // max rows
n = 5; // max columns
row = 2; // value entered by user, must be < m
col = 3 // value entered by user, must be < n
*(myarray + (row*n) + col) = 1.2345;
Q2:是的我认为最好不要知道你需要的内存大小,编写好的代码来获取所有用户输入,然后计算你的内存大小我需要。然后使用 malloc 或 calloc 来分配该内存,如果不成功{系统没有足够},则处理该条件并相应地编写代码。唯一的缺点是,如果你编写重复调用malloc或calloc的代码,那么释放它并多次重复这个过程,这会产生很多开销。
答案 3 :(得分:0)
你永远不会“真实地”这样做。让用户通过标准输入输入二维矩阵是一个教学玩具问题,给人们学习C.这个练习的一个缺点是没有一个好的答案,有一些方法你可以做到像创建超大缓冲区,或重新分配内存以增长,或在输入变量之前查询用户的宽度和高度。但没有什么是完全令人满意的。
实际上,数据很可能采用CSV等文件格式。解析CSV文件相当困难,但并不难以让任何有能力的程序员无法实现它。通常的方法是将结构读入内存结构,然后“解析解析器的输出”以将其转换为平面2D数组(或一维结构数组,对于CSV文件非常常见)。