为什么我更改数组大小后结果会发生变化?

Why the result changes after i change the size of array?

我已经完成了一个程序,该程序将数字 n 作为输入,然后 return 一个方阵 n*n,其中 属性 所有行、列和对角线的总和相同。

该项目没有问题,我尝试尽可能地优化它,从算法到为此使用特定的数据类型(在我的情况下 unsigned short,因为我不需要更大的存储空间)。

毕竟我想看看性能,我想尝试更大的数字,比如 100,200,等等; 但是当我试图改变矩阵的存储时,程序无法正常工作,return用 0 编辑了一个矩阵,总和很奇怪。

我不明白这个错误是从哪里来的。

#include <stdio.h>
#include <stdlib.h>

unsigned short a[100][100], i = 0, j = 0, n, suma[100];

void next_b(unsigned short *i, unsigned short *j);   // find the properly i and j
void completare(unsigned short i, unsigned short j); // completes the matrix after i find the i and j
void tipar();                                        // print the matrix

int suma_linie(unsigned short x);   //sum of a row
int suma_coloana(unsigned short y); //sum of a column
int suma_diagonala_principala();    //first diagonal
int suma_diagonala_secundara();     //second one

int main()
{

    scanf("%hu", &n);
    system("cls");
    j = n / 2 - 1;
    a[0][j] = 4;
    a[0][j + 1] = 1;
    a[1][j] = 2;
    a[1][j + 1] = 3;

    suma[0] = 5;
    suma[1] = 5;
    suma[n + j] = 6;
    suma[n + j + 1] = 4;

    for (int x = 2; x <= (n / 2) * (n / 2); x++)
    {
        next_b(&i, &j);
        a[i][j] = x;
        completare(i, j);
    }
    tipar();
    //for(int x=0;x<n;x++){
    //
    //    printf("suma de pe linia %d este: %d\n",x,suma_linie(x));
    //    printf("suma de pe coloana %d este: %d\n\n",x,suma_coloana(x));
    //}
    //printf("suma de pe daig principala  este: %d\n\n",suma_diagonala_principala());
    //  printf("suma de pe daig secundara este: %d\n\n",suma_diagonala_secundara());

    for (int x = 0; x < 2 * n + 2; x++)
    {
        if (x < n)
        {
            printf("suma de pe linia %d este %hu\n", x, suma[x]);
        }
        else if (x < 2 * n)
        {
            printf("suma de pe coloana %d este %hu\n", x % n, suma[x]);
        }
        else if (x == 2 * n)
        {
            printf("suma de pe diag principala este %hu\n", suma[x]);
        }
        else
        {
            printf("suma de pe diag secundara este %hu\n", suma[x]);
        }
    }
    return 0;
}

void tipar()
{

    for (int k = 0; k < n; k++)
    {
        for (int l = 0; l < n; l++)
        {

            if (a[k][l] < 10)
            {
                printf("   %d |", a[k][l]);
            }
            else if (a[k][l] <= 99)
            {
                printf("  %d |", a[k][l]);
            }
            else if (a[k][l] < 1000)
            {
                printf(" %d |", a[k][l]);
            }
            else if (a[k][l] < 10000)
            {
                printf("%d ", a[k][l]);
            }
        }
        printf("\n");
        for (int z = 0; z <= 6 * n - 1; z++)
        {
            printf("-");
        }
        printf("\n");
    }
    printf("\n");
}

void next_b(unsigned short *i, unsigned short *j)
{
    if (*i - 2 < 0)
    {

        if (a[n - 2][*j + 2] == 0 && *j + 2 <= n - 2)
        {
            // printf("cazul 2\n");
            *i = n - 2;
            *j += 2;
            return;
        }
        else if (a[*i - 2][*j] == 0)
        {
            // printf("cazul 7\n");
            *i += 2;
            return;
        }
    }

    else
    {
        if (*j == n - 2)
        { //printf("cazul 3\n");
            *i -= 2;
            *j = 0;
            return;
        }
        else if (a[*i - 2][*j + 2] != 0)
        {
            //printf("cazul 4\n");
            *i += 2;
        }
        else if (a[*i - 2][*j + 2] == 0)
        {
            //         printf("cazul 5\n");
            *i -= 2;
            *j += 2;
        }
    }
}

void completare(unsigned short i, unsigned short j)
{

    if (i <= n / 2)
    { //////////// l

        if (i == n / 2 - 1 && j == n / 2 - 1)
        {

            a[i][j + 1] = 4 * a[i][j];
            a[i + 1][j] = 4 * a[i][j] - 2;
            a[i + 1][j + 1] = 4 * a[i][j] - 1;
            a[i][j] = 4 * a[i][j] - 3;
        }
        else
        {
            a[i][j] = 4 * a[i][j];
            a[i][j + 1] = a[i][j] - 3;
            a[i + 1][j] = a[i][j] - 2;
            a[i + 1][j + 1] = a[i][j] - 1;
        }
    }
    else if (i == n / 2 + 1)
    { ///////////// u

        if (j == n / 2 - 1)
        {

            a[i][j] = 4 * a[i][j];
            a[i][j + 1] = a[i][j] - 3;
            a[i + 1][j] = a[i][j] - 2;
            a[i + 1][j + 1] = a[i][j] - 1;
        }
        else
        {

            a[i][j + 1] = 4 * a[i][j];
            a[i + 1][j] = 4 * a[i][j] - 2;
            a[i + 1][j + 1] = 4 * a[i][j] - 1;
            a[i][j] = 4 * a[i][j] - 3;
        }
    }
    else
    { ///////x

        a[i][j + 1] = 4 * a[i][j];
        a[i + 1][j + 1] = 4 * a[i][j] - 2;
        a[i + 1][j] = 4 * a[i][j] - 1;
        a[i][j] = 4 * a[i][j] - 3;
    }

    suma[i] += a[i][j] + a[i][j + 1];
    suma[i + 1] += a[i + 1][j] + a[i + 1][j + 1];
    suma[n + j] += a[i][j] + a[i + 1][j];
    suma[n + j + 1] += a[i][j + 1] + a[i + 1][j + 1];

    if (i == j)
    {
        suma[2 * n] += a[i][j] + a[i + 1][j + 1];
    }
    if (i + j + 1 == n - 1)
    {
        suma[2 * n + 1] += a[i + 1][j] + a[i][j + 1];
    }
}

int suma_linie(unsigned short x)
{
    int s = 0;
    for (int y = 0; y < n; y++)
    {
        s += a[x][y];
    }
    return s;
}
int suma_coloana(unsigned short y)
{
    int s = 0;
    for (int x = 0; x < n; x++)
    {
        s += a[x][y];
    }
    return s;
}
int suma_diagonala_principala()
{
    int s = 0;

    for (int x = 0; x < n; x++)
    {

        s += a[x][x];
    }
    return s;
}
int suma_diagonala_secundara()
{
    int s = 0;

    for (int x = 0; x < n; x++)
    {

        s += a[x][n - x - 1];
    }
    return s;
}

代码是用我在 Wikipedia-Magic Square.

上找到的算法求解的

在上面的 cod 中,如果我尝试将 suma 大小更改为 200 或任何其他值,程序将运行奇怪并且 returns 愚蠢的事情。 即使我将 a 尺寸设置得更高也是有效的。

我用了两种方法来查看总和,一种使用预定义函数,另一种将矩阵元素添加到 suma,使用的函数 int,另一种方法使用 unsigned short 如果重要的话。

我检查了你的代码,发现了一些问题。我试过 n = 90.

for(int x=2; x<=(n/2)*(n/2); x++)
{
   next_b(&i,&j);
   a[i][j]=x;
   completare(i,j);

}

如果你检查这段代码,那么你可以看到 i, j 的值何时相应地变为 0, 2 然后它会转到 next_b(i, j) 方法。还有一些行试图访问 negative 索引。所以它抛出异常。 喜欢 -

else if(a[*i-2][*j]==0)  // here
{
    // printf("cazul 7\n");
    *i+=2;
    return;

}

................................................

if(*j==n-2)
{
    //printf("cazul 3\n");
    *i-=2;
    *j=0;
    return;
}
else if (a[*i-2][*j+2]!=0) // here
{
    //printf("cazul 4\n");
    *i+=2;

}
else if(a[*i-2][*j+2]==0)  // here
{
    //printf("cazul 5\n");
    *i-=2;
    *j+=2;
}

尝试修复这些负索引然后它应该工作(假设你的方法是正确的)。