提问人:vatsal 提问时间:5/24/2023 最后编辑:mchvatsal 更新时间:5/24/2023 访问量:85
为什么我的“for”循环在矩阵程序中的运行方式与预期不同?[关闭]
Why is my 'for' loop running differently than expected in my matrix program? [closed]
问:
#include <stdio.h>
int main()
{
int matrix;
printf("ENTER NUMBER OF MATRICES\n");
scanf("%d", &matrix);
getchar();
int row[matrix], column[matrix];
for (int m = 0; m < matrix; m++) {
printf("ENTER NUMBER OF ROWS IN %d MATRICE\n", m + 1);
scanf("%d", &row[m]);
getchar();
printf("ENTER NUMBER OF column IN %d MATICE\n", m + 1);
scanf("%d", &column[m]);
getchar();
int x[m][row[m]][column[m]];
int g = 1;
printf("ENTER ALL ELEMENT LEFT TO RIGHT\n");
for (int j = 0; j < row[m]; j++) {
for (int u = 0; u < column[m]; u++) {
printf("%d\n", g);
scanf("%d", &x[m][j][u]);
g = g + 1;
}
}
for (int k = 0; k < row[m]; k++) {
printf("|");
for (int l = 0; l < column[m]; l++) {
printf("%d", x[m][k][l]);
if (l < column[m] - 1) {
printf(" ");
}
}
printf("|");
printf("\n");
}
}
return 0;
}
输出:
ENTER NUMBER OF MATRICES
1
ENTER NUMBER OF ROWS IN 1 MATRICE
1
ENTER NUMBER OF column IN 1 MATICE
2
ENTER ALL ELEMENT LEFT TO RIGHT
1 // COUNTING JUST FOR USER
3 // INPUT 1
2 // COUNTING
4 // INPUT 2
3 //WHY IS IT ASKING ME THIRD ELEMENT WHEN I HAVE SET SIZE OF
MATRIX TO BE 1-2
2 // INPUT 3
|3 4 2|
EXPECTATIONS:
ENTER NUMBER OF MATRICES
1
ENTER NUMBER OF ROWS IN 1 MATRICE
1
ENTER NUMBER OF column IN 1 MATICE
2
ENTER ALL ELEMENT LEFT TO RIGHT
1
3
2
4
|3 4|
在这里,如您所见,我给出的行数和列数为 1-2,但矩阵大小仍然是 1 行和 3 列,出于某种原因,给我的矩阵的第一个输入被设置为 FOR 循环应该运行的次数数和矩阵中的列数
我已经用矩阵制作了一个程序,但是“for”循环的运行与我的预期不同,我无法理解“for”循环的值是什么,作为运行的输入,我已经设法弄清楚,由于某种原因,“for”循环的扫描中的第一个值是设置no。矩阵的列,并确定循环将要运行的匝数。由于我无法找到解决问题的方法,因此请您帮助我解决此错误。
答:
循环中的问题就在这里:
int x[m][row[m]][column[m]];
// ...
scanf("%d", &x[m][<whatever>][<whatever>]);
此代码首先生成一个包含矩阵的三维数组,每个矩阵都有行和列,然后通过以下方式越界访问此数组 – 有效索引在 的范围内,特别注意:不包括在内!实际上,您甚至根本不会生成任何矩阵(可以在结构中使用零大小的数组来生成灵活的数组成员......m
row[m]
column[m]
x[m]
[0; m-1]
m
m == 0
越界访问数组是未定义的行为,因此任何事情都可能发生,包括程序按预期运行(在某些幸运输入上)、程序崩溃或(最坏)显示您所经历的意外行为。
在引擎盖下发生的事情是,显然在具有自上而下的堆栈的体系结构上运行时,数组被放置在某个高内存地址,放置在(一些较低的内存地址)的前面,最后放在 的前面。然后,当越界访问时,您可以访问一些高于 的内存地址,并猜测有数组和列。因此,通过写入越界,您不小心更改了其中的值和/或至少一个,从而更改了循环限制,从而导致您看到的行为(您可以尝试其他矩阵值并观察行为如何变化......row
column
row
x
column
x
x
row
x
row
column
旁注:的具体值是无关紧要的,假设放在紧挨着前面,那么 的地址就是 的地址,减去,然后再次添加到这个地址,因此总是访问 ...m
x
columns
x
b
m*sizeof(*x)
x[m]
m*sizeof(*x)
x[m][0][0]
column[0]
如何解决:只要在循环中进行整个矩阵处理,就可以将矩阵创建为简单的二维数组:
for(int m = 0; m < c; ++m)
{
// in this case actually sufficient here as well,
// as ordinary integers:
int row; int column;
// scan row and column
int matrix[row][column];
// now scan into matrix[r][c] with r and c iterating accordingly
}
如果你想维护一个矩阵数组,那么你需要在进入循环之前定义这个数组!随之而来的问题是:所有数组条目都必须大小相等!对于单个 3D 数组,您需要首先确定所有矩阵的大小,并记住用于所有矩阵的最大尺寸。
另一种方法是动态分配矩阵,但是您需要一种方法来正确处理它们。
我建议使用专用结构,并将矩阵的 2D 数组映射到单个单维数组,手动进行索引计算,例如:
#include<stddef.h> // for size_t
struct Matrix
{
size_t rows, columns;
int* values;
// or alternatively with flexible array member:
int values[0];
};
int get(struct Matrix* matrix, size_t row, size_t column)
{
return matrix->values[row * matrix->columns + column];
}
void set(struct Matrix* matrix, size_t row, size_t column, int value)
{
matrix->values[row * matrix->columns + column] = value;
}
最后,您可以动态分配;要么作为
struct Matrix matrices[m] = { {0, 0, NULL} };
或使用灵活的数组成员作为
struct Matrix* matrices[m] = { NULL };
请注意,无论如何,您都需要动态内存分配,无论是对于指针矩阵引用的数组,还是对于灵活的数组成员的整个矩阵结构(我个人认为后一种方法更简洁一些......
然后,循环中矩阵的分配发生如下:
size_t count;
scanf("%zu", &count);
for(size_t m = 0; m < count; ++m)
{
size_t rows, columns;
scanf("%zu", &rows);
scanf("%zu", &columns);
///////////////////////////////////////////////////
// pointer variant:
matrices[m].values = malloc(rows * columns * sizeof(*matrices[m].values));
if(!matrices[m].values)
{
// allocation failed!
// TODO: appropriate error handling!
// return or exit(-1) or ???
}
matrices[m].rows = rows;
matrices[m].columns = columns;
///////////////////////////////////////////////////
// flexible array member variant:
matrices[m] = malloc
(
// base size
sizeof(*matrices[m])
// plus size of array
+ rows * columns * sizeof(*matrices[m]->values)
);
if(!matrices[m])
{ /* again: error handling! */ }
matrices[m]->rows = rows;
matrices[m]->columns = columns;
///////////////////////////////////////////////////
// now scan the matrix entries
int* values = matrices[m].values; // pointer variant
int* values = matrices[m]->values; // flexible array member; note that the
// array decays to pointer automatically
// looping over rows and columns
scanf("%d", values++);
}
最后:有动态分配的内存,不要再忘记它:free
for(size_t m = 0; m < count; ++m)
{
free(matrices[m].values); // array as pointer
free(matrices[m]); // flexible array member
}
最后说明:所有代码都完全未经测试,如果您发现错误,请自行修复......
评论
printf("%6d", matrix[r][c])
printf("%*d", digits, matrix[r][c])
int x[m][a][b]
x[m][...][...]
x[m]
a
b