c - 多维列移位中的数组索引错误(使用指针)

标签 c arrays algorithm pointers multidimensional-array

我对如何处理多维数组列有了一些了解。

下面是一些可编译的代码,大部分情况下都可以正常运行和执行。

我想使用我现在正在使用的逻辑,这对我来说似乎很合理(至少作为新手),但是我得到了非常令人讨厌的输出。

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

Here I initialize an empty array which you will see later in main:

void initializeGrid(int row, int col, int grid[][col])
{
    int count = 1;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            grid[i][j] = count;
            count++;
        }
    }
}

Here I print the initial case of the grid that will later be manipulated. This should be reused:

void printGrid(int row, int col, int grid[][col])
{
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                printf("%3d", grid[i][j]);
            }
            printf("\n");
        }
}

Here I get the location of a specific value by its row and its column and I store it to the pointers r, and c:

bool findUnit(int unit, int row, int col, int grid[][col], int *r, int *c)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (grid[i][j] == unit)
            {
                *r = i;
                *c = j;
                return true;
            }
        }
    }
    return false;
}

Here I shift up using very elementary array mechanics and I felt so confident about it until seeing my output:

bool shiftUp(int unit, int row, int col, int grid[][col])
{
    int r = 0;
    int c = 0;
    if (findUnit(unit, row, col, grid, &r, &c))
    {
        int i;
        int temp = grid[0][c];
        for (i = 1; i <= row; i++)
        {
            grid[i - 1][c] = grid[i][c];
        }
        grid[r][c] = temp;
        return true;
    }
    return false;
}

Here I run the shift up command or I quit. Assume that run can make array move in other directions as well. It does not work for any direction yet, but I assume if I can fix one, I can fix all:

bool run(char cmd[10], int row, int col, int grid[][col])
{
    int unit = 0;
    printf("$: ");
    scanf(" %s %d", cmd, &unit);

    if (strcmp(cmd, "up") == 0)
    {
        shiftUp(unit, row, col, grid);
        return true;
    }
    if (strcmp(cmd, "quit") == 0)
    {
        return false;
    }
    return false;
}

Here I execute the code:

int main()
{
    int row = 4;
    int col = 4;
    int grid[row][col];
    char cmd[32];

    initializeGrid(row, col, grid);
    printGrid(row, col, grid);

    while (run(cmd, row, col, grid))
    {
        printGrid(row, col, grid);
    }
    return 0;
}

这都是一个文件。这也是我得到的令人不安的输出和预期的输出。

  1  2  3  4
  5  6  7  8
  9 10 11 12
 13 14 15 16
$: up 9
  5  2  3  4
  9  6  7  8
  1 10 11 12
1347447432 14 15 16
$: quit

^C

请注意,即使我输入 quit,它也不会退出。

预期输出应该类似于(在较小的网格中,即 3x3):

1 2 3             1 5 3
4 5 6 --(up 5)--> 4 8 6
7 8 9             7 2 9

最佳答案

在这部分

for (i = 1; i <= row; i++)
{
    grid[i - 1][c] = grid[i][c];
}

i == row时,grid[i][c]出现越界错误。

在 C 语言中,数组索引从 0 开始,
当有这样的数组时

Type array[n];

可用的最大索引为n-1

<小时/>

举个例子,
您可以使用一维数组而不是二维数组来简化该过程。

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

//When there is no strlwr
#ifndef STRLWR
#include <ctype.h>
char *strlwr(char *s){
    for(char *p = s; *p; ++p)
        *p = tolower((unsigned char)*p);
    return s;
}
#endif

static inline void clear_input_buff(void){
    while(getchar() != '\n');
}

typedef enum {
    QUIT, UP, DOWN, LEFT, RIGHT
} Command;

Command getCommand(const char *prompt){
    while(true){
        char cmd[8] = "";
        fputs(prompt, stdout);fflush(stdout);
        scanf("%7s", cmd);
        strlwr(cmd);
        if(!strcmp(cmd, "quit"))
            return QUIT;
        else if(!strcmp(cmd, "up"))
            return UP;
        else if(!strcmp(cmd, "down"))
            return DOWN;
        else if(!strcmp(cmd, "left"))
            return LEFT;
        else if(!strcmp(cmd, "right"))
            return RIGHT;
        printf(
            "invalid input for command\n"
            "input again\n"
        );
        clear_input_buff();
    }
}

bool findUnit(int unit, int row, int col, int grid[], int *r, int *c){
    for(*r = 0; *r < row; ++*r)
        for(*c = 0; *c < col; ++*c)
            if(*grid++ == unit)
                return true;
    return false;
}

void moveHelper(int n, int array[], Command dir, int distance){
    int temp;
    int last = (n-1) * distance;
    if(dir == LEFT){
        temp = array[0];
        for(int i = distance; i <= last; i += distance){
            array[i - distance] = array[i];
        }
        array[last] = temp;
    } else if(dir == RIGHT){
        temp = array[last];
        for(int i = last; i > 0; i -= distance)
            array[i] = array[i - distance];
        array[0] = temp;
    }
}

bool move(int unit, int row, int col, int grid[], Command cmd){
    int r, c;
    if(findUnit(unit, row, col, grid, &r, &c)){
        switch(cmd){
        case UP:
        case DOWN:
            cmd = (cmd == UP) ? LEFT : RIGHT;
            moveHelper(row, &grid[c      ], cmd, col);
            break;
        case LEFT:
        case RIGHT:
            moveHelper(col, &grid[r * col], cmd,   1);//1: 1 element
            break;
        }
        return true;
    }
    printf("Can't found [%d]. So you can't move.\n", unit);
    return false;
}

bool run(int row, int col, int grid[]){
    Command cmd;

    while((cmd = getCommand("$: ")) != QUIT){
        int unit = 0;
        if(scanf("%d", &unit) != 1){//get operand as unit
            printf("invalid input for unit.\n");
            clear_input_buff();
            continue;
        }
        return move(unit, row, col, grid, cmd);
    }
    return false;
}

void initializeGrid(int n, int grid[n]){
    int value = 1;
    while(n--)
        *grid++ = value++;
}

void printGrid(int row, int col, int *grid, int width){
    for (int i = 0; i < row; i++){
        for (int j = 0; j < col; j++)
            printf("[%*d]", width, *grid++);
        putchar('\n');
    }
}

static inline int width(int value){
    return snprintf(NULL, 0, "%d", value);
}

int main(void){
    int row = 4, col = 4;
    int n = row * col;//number of elements
    int grid[n];

    initializeGrid(n, grid);

    int w = width(grid[n-1]);//width of max value
    printGrid(row, col, grid, w);

    while(run(row, col, grid)){
        printGrid(row, col, grid, w);
    }
    return 0;
}
<小时/>

执行示例:

[ 1][ 2][ 3][ 4]
[ 5][ 6][ 7][ 8]
[ 9][10][11][12]
[13][14][15][16]
$: up 9
[ 5][ 2][ 3][ 4]
[ 9][ 6][ 7][ 8]
[13][10][11][12]
[ 1][14][15][16]
$: right 11
[ 5][ 2][ 3][ 4]
[ 9][ 6][ 7][ 8]
[12][13][10][11]
[ 1][14][15][16]
$: down 15
[ 5][ 2][15][ 4]
[ 9][ 6][ 3][ 8]
[12][13][ 7][11]
[ 1][14][10][16]
$: left 15
[ 2][15][ 4][ 5]
[ 9][ 6][ 3][ 8]
[12][13][ 7][11]
[ 1][14][10][16]
$: quit

关于c - 多维列移位中的数组索引错误(使用指针),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46555479/

相关文章:

c - 使用 GDB 确定代码错误

java - 更改 tcp/ip 数据包 c++ 或 java

java - 将对象添加到对象数组

algorithm - 由 'smart lines' 链接的盒子 - 这叫什么?怎么样?

c - Brainfuck 解释器不运行某些代码

c - malloc 中的 "free(): invalid next size (fast)"错误

java - 如何发现此错误代码中的错误的过程?

C++ 如何将 char 数组转换为字节 vector (vector<byte>)

algorithm - 从字符串向量中移除_if

algorithm - 矩阵中求和元素的动态规划