You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多维数组赋值行错误:奇数阶幻方生成程序故障排查

奇数阶幻方C程序赋值错误排查与修复

我正在编写一个生成奇数阶幻方的C程序,规则如下:

  • 将1放在第0行的中间位置
  • 后续数字放在上一行的右一列(越界则循环)
  • 若目标位置已有数字,则放在当前数字的正下方

但执行else分支时,值被赋到了错误的行:修改else分支打印row值显示为1,却持续赋值到第2行,甚至出现覆盖之前数值的情况。

原代码

// Print an nxn magic square

#include <stdio.h>

int main(void)
{
    int n;
    printf("This program creates a magic square of a specified size.\n");
    printf("The size must be an odd number between 1 and 99.\n");
    printf("Enter size of the square: ");
    scanf("%d", &n);

    int square[n] [n];

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            square[i] [j] = 0;
        }
    }
    
    square[0] [n / 2] = 1;

    int row = 0, column = n/2;
    for (int i = 2; i < n * n + 1; i++) {
        if (square[row == 0 ? n - 1 : row - 1] [(column + 1) % n] == 0) {
            square[row == 0 ? row = n - 1 : --row] [(++column) % n] = i;
        } else {
            square[++row] [column] = i;
        }
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                printf("%2d ", square[j] [k]);
            }
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}

修改后的else分支代码(用于调试)

} else {
            square[printf("row: %d ", row), row] [column] = i;
        }

输出示例(n=5时)

0  0  1  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  2  0

 0  0  1  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  3
 0  0  0  2  0

 0  0  1  0  0
 0  0  0  0  0
 4  0  0  0  0
 0  0  0  0  3
 0  0  0  2  0

 0  0  1  0  0
 0  5  0  0  0
 4  0  0  0  0
 0  0  0  0  3
 0  0  0  2  0

row: 1
 0  0  1  0  0
 0  5  0  0  0
 4  6  0  0  0
 0  0  0  0  3
 0  0  0  2  0

row: 1
 0  0  1  0  0
 0  5  0  0  0
 4  7  0  0  0
 0  0  0  0  3
 0  0  0  2  0
.
.
.

问题分析

  1. 下标内赋值导致逻辑混淆:原代码将row的修改(row = n-1或--row)直接写在数组下标中,虽然能修改row,但逻辑不直观,容易引发后续错误。
  2. else分支未正确更新row:调试用的else分支仅打印row并赋值,但未更新row的值,导致下一次循环时row仍为旧值,重复进入else分支并覆盖同一位置的数值。
  3. 原else分支的前缀自增误解:原else分支使用++row,会先将row自增再赋值,这符合“正下方”的规则(当前数字在row,正下方是row+1),但调试时打印的是自增前的row值,导致误以为赋值位置错误。

修复方案

将候选位置的计算与row、column的更新逻辑分离,避免在数组下标内进行赋值操作,让代码逻辑更清晰:

// Print an nxn magic square

#include <stdio.h>

int main(void)
{
    int n;
    printf("This program creates a magic square of a specified size.\n");
    printf("The size must be an odd number between 1 and 99.\n");
    printf("Enter size of the square: ");
    scanf("%d", &n);

    int square[n][n];

    // 初始化数组为0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            square[i][j] = 0;
        }
    }
    
    // 放置初始值1
    int row = 0, column = n / 2;
    square[row][column] = 1;

    // 填充剩余数字
    for (int i = 2; i <= n * n; i++) {
        int next_row, next_col;
        // 计算右上候选位置
        next_row = row - 1;
        if (next_row < 0) {
            next_row = n - 1;
        }
        next_col = column + 1;
        if (next_col >= n) {
            next_col = 0;
        }

        if (square[next_row][next_col] == 0) {
            // 候选位置为空,更新到该位置
            row = next_row;
            column = next_col;
        } else {
            // 候选位置被占,放到当前位置的正下方
            row = row + 1;
            // 处理越界(Siamese方法中实际不会触发,但保留以增强鲁棒性)
            if (row >= n) {
                row = 0;
            }
        }
        // 赋值当前数字
        square[row][column] = i;

        // 打印当前状态(可选,用于调试)
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                printf("%2d ", square[j][k]);
            }
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}

修复说明

  • 单独计算右上候选位置,逻辑清晰易懂,避免了原代码中嵌套三元运算符的混乱。
  • 明确更新row和column的值,确保每一步的位置都正确同步。
  • else分支中更新row为当前位置的正下方,符合幻方规则,同时处理了可能的越界情况。

内容的提问来源于stack exchange,提问作者raidenfox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:10:54