C语言状态机问题,为什么会暂停?

问题描述 投票:0回答:1

这个简单的代码尝试从索引 [0][0] 以螺旋方式移动 2 x 2 矩阵,直到原始矩阵中没有元素为止。 例如,如果有一个如下所示的矩阵,

[[1 2 3]  
[4 5 6]  
[7 8 9]]

输出将是,

[1 2 3 6 9 8 7 4 5]

这段代码运行正常,但在最后短暂暂停,然后最终打印输出数组。 造成这种行为的原因是什么?

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

typedef enum {
    move_right,
    move_down,
    move_left,
    move_up
}States;

void print_array(int* arr, int n)
{
    for(int i = 0; i<n; i++){
        printf(" %d", arr[i]);
    }
}

void spiral_matrix(int* input, int row_size, int col_size, int* output)
{
    int size = row_size * col_size;
    int max_col = col_size-1;
    int max_row = row_size-1;
    int min_col = 0;
    int min_row = 0;
    int i = 0;
    int j = 0;
    States current_state = move_right;
    int idx = 0;
    while(idx < size) {
        switch (current_state)
        {
        case move_right:
            if(j < max_col) {
                output[idx] = *(input+i*col_size + j);
                j++;
                idx++;
            } else {
                current_state = move_down;
                min_row += 1;
            }
            break;
        case move_down:
            if(i < max_row) {
                output[idx] = *(input+i*col_size + j);
                i++;
                idx++;
            } else {
                current_state = move_left;
                max_col--;
            }
            break;
        case move_left:
            if(j > min_col) {
                output[idx] = *(input+i*col_size + j);
                j--;
                idx++;
            } else {
                current_state = move_up;
                max_row--;
            }
            break;
        case move_up:
            if(i > min_row) {
                output[idx] = *(input+i*col_size + j);
                i--;
                idx++;
            } else {
                current_state = move_right;
                min_col += 1;
            }
            break;
        default:
            break;
        }   
    }
}
#define N 4
#define M 4

void main(void)
{
    int A[N][M] = {{1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,16}};
    int* spiral_out = (int*)malloc(N*M*sizeof(int));
    spiral_matrix(A[0], N, M, spiral_out);
    print_array(spiral_out, N*M);
    free(spiral_out);
}

c state-machine
1个回答
0
投票

这段代码运行正常,但在最后短暂暂停,然后最终打印输出数组。造成这种行为的原因是什么?

这只是你的假设,缺少事实。

你的逻辑有问题-

打印第一行

1,2,3,4
时,仅将元素
3
写入输出数组,并将
current_state
设置为
move_down
,在
move_down
情况下,将
4
写入
output
数组。但从逻辑上讲,它应该写入到元素
4
,然后将
current_state
设置为
move_down
。当以螺旋方式遍历时,所有角元素的行为相同。

当到达最后一个元素时,变量

max_col
max_row
min_col
min_row
i
j
idx
的值设置为
while
都不会循环条件导致
false
if
循环体中的任何
while
条件导致
true
以及变量
max_col
max_row
min_col
min_row
的值根据以下条件递增或递减
else
块语句。在某一阶段,它们要么上溢/下溢(取决于其是否递增/递减)并最终导致“未定义的行为”。 (未定义的行为包括它可能会错误地执行(崩溃或默默地生成不正确的结果),或者它可能会偶然地完全按照程序员的意图进行操作。

max_col

数组中写入元素

max_row
(螺旋遍历中倒数第二个元素)后,变量
min_col
min_row
i
j
idx
11
output
的值(仅记录了几次迭代):
max_col : 1, max_row : 2, min_col : 1, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 1, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 2, min_row : 2, i : 2, j : 1, idx : 15
max_col : 1, max_row : 1, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 1, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 2, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 3, min_row : 3, i : 2, j : 1, idx : 15
max_col : 0, max_row : 0, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : 0, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 3, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 4, min_row : 4, i : 2, j : 1, idx : 15
max_col : -1, max_row : -1, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -1, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 4, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 5, min_row : 5, i : 2, j : 1, idx : 15
max_col : -2, max_row : -2, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -2, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -3, min_col : 5, min_row : 6, i : 2, j : 1, idx : 15
max_col : -3, max_row : -3, min_col : 6, min_row : 6, i : 2, j : 1, idx : 15
......
......
...... // keep on incrementing/decrementing in same pattern and loop iterates

while

循环不断迭代,给你一种

暂停
的印象。 要解决此问题,在更改

current_state

时,根据状态正确设置

i
j
    while(idx < size) {
        switch (current_state)
        {
        case move_right:
            if(j <= max_col) {     // write to array till max column
                output[idx] = *(input+i*col_size + j);
                j++;
                idx++;
            } else {
                current_state = move_down;
                j = max_col; i++;  // if moving down, increment row and set column to max
                min_row += 1;
            }
            break;
        case move_down:
            if(i <= max_row) {         // write to array till max row
                output[idx] = *(input+i*col_size + j);
                i++;
                idx++;
            } else {
                current_state = move_left;
                i = max_row; j--;  // if moving left, set row to max and  decrement column
                max_col--;
            }
            break;
        case move_left:
            if(j >= min_col) {         // write to array till min column
                output[idx] = *(input+i*col_size + j);
                j--;
                idx++;
            } else {
                current_state = move_up;
                j = min_col; i--;  // if moving up, set column to min and decrement row
                max_row--;
            }
            break;
        case move_up:
            if(i >= min_row) {       // write to array till min row
                output[idx] = *(input+i*col_size + j);
                i--;
                idx++;
            } else {
                current_state = move_right;
                i = min_row; j++;  // if moving right, set row to min and increment column
                min_col += 1;
            }
            break;
        default:
            break;
        }   

矩阵的螺旋遍历可以用更好、更简单的方式实现,但是您在问题中提到了术语 
state machine

,所以我假设,您有意在代码中包含

current_state
,而这根本不是必需的.
    

© www.soinside.com 2019 - 2024. All rights reserved.