为什么我的“for”循环在矩阵程序中的运行方式与预期不同?[关闭]

Why is my 'for' loop running differently than expected in my matrix program? [closed]

提问人:vatsal 提问时间:5/24/2023 最后编辑:mchvatsal 更新时间:5/24/2023 访问量:85

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将帮助其他人回答这个问题。

6个月前关闭。

#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。矩阵的列,并确定循环将要运行的匝数。由于我无法找到解决问题的方法,因此请您帮助我解决此错误。

c for 循环 语法错误

评论

2赞 Retired Ninja 5/24/2023
明确您的期望。您提供什么输入?您期望输出什么?
2赞 Aconcagua 5/24/2023
旁注:适当的缩进会极大地提高可读性,所以也许您可能需要调整一下?提示:使用 IDE 提供的自动格式化工具(您正在使用一个,是吗?
1赞 Aconcagua 5/24/2023
您可能想尝试使用调试器来了解您的代码实际在做什么......
1赞 Aconcagua 5/24/2023
只是一个建议:会注意矩阵条目的正确对齐,最多 5 位数字和一个减号(或 6 位正数)——否则,如果数字包含多个数字,您的输出会变得非常分散。根据您期望的输入,您可能可以使用更少的数字,甚至需要更多数字,或者您甚至可以动态计算 - 然后拥有!printf("%6d", matrix[r][c])printf("%*d", digits, matrix[r][c])
1赞 Aconcagua 5/24/2023
噢,我的......花了我一段时间,但是:您正在使用 生成一个 3D 数组,然后您使用 – 但超出了范围!你产生了未定义的行为,很可能你不小心覆盖了你的数组和/或至少一个数组。int x[m][a][b]x[m][...][...]x[m]ab

答:

0赞 Aconcagua 5/24/2023 #1

循环中的问题就在这里:

int x[m][row[m]][column[m]];
// ...
scanf("%d", &x[m][<whatever>][<whatever>]);

此代码首先生成一个包含矩阵的三维数组,每个矩阵都有行和列,然后通过以下方式越访问此数组 – 有效索引在 的范围内,特别注意:不包括在内!实际上,您甚至根本不会生成任何矩阵(可以在结构中使用零大小的数组来生成灵活的数组成员......mrow[m]column[m]x[m][0; m-1]mm == 0

越界访问数组是未定义的行为,因此任何事情都可能发生,包括程序按预期运行(在某些幸运输入上)、程序崩溃或(最坏)显示您所经历的意外行为。

在引擎盖下发生的事情是,显然在具有自上而下的堆栈的体系结构上运行时,数组被放置在某个高内存地址,放置在(一些较低的内存地址)的前面,最后放在 的前面。然后,当越界访问时,您可以访问一些高于 的内存地址,并猜测有数组和列。因此,通过写入越界,您不小心更改了其中的值和/或至少一个,从而更改了循环限制,从而导致您看到的行为(您可以尝试其他矩阵值并观察行为如何变化......rowcolumnrowxcolumnxxrowxrowcolumn

旁注:的具体值是无关紧要的,假设放在紧挨着前面,那么 的地址就是 的地址,减去,然后再次添加到这个地址,因此总是访问 ...mxcolumnsxbm*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
}

最后说明:所有代码都完全未经测试,如果您发现错误,请自行修复......

评论

0赞 vatsal 5/24/2023
谢谢谢谢谢谢阿空加瓜,我一直在为这个问题苦苦挣扎很长时间,我终于明白了.再次感谢您的时间和精力,并详细写下我问题的解决方案。