【问题标题】:Parse in and return 2D array解析并返回二维数组
【发布时间】:2019-12-03 10:19:12
【问题描述】:

尝试制作井字游戏并遇到网格问题,我是 C 的新手,到处寻找,但似乎没有任何效果。

int main(void) {
    char grid[GRID_HEIGHT][GRID_WIDTH];
    grid = make_grid((char **)grid);
    print_grid((char **)grid);
}

char ** make_grid(char **grid) {
    char grid[GRID_HEIGHT][GRID_WIDTH] = {
        { '\n', ' ', '1', ' ', '|', ' ', '2', ' ', '|', ' ', '3', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '4', ' ', '|', ' ', '5', ' ', '|', ' ', '6', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '7', ' ', '|', ' ', '8', ' ', '|', ' ', '9', ' ' }
    };
    return grid;
}

void print_grid(char **grid) {
    for (int row = 0; row < GRID_HEIGHT; row++) {
        for (int column = 0; column < GRID_WIDTH; column++) {
            printf("%c", grid[row][column]);
        }
    }
    printf("\n");
}

如何将网格解析为函数并在程序不崩溃的情况下返回它?

【问题讨论】:

  • GRID_HEIGHTGRID_WIDTH 是如何定义的?
  • 还有,一旦你从make_grid回来,grid就消失了,你不能引用它。
  • 请注意,您不能将二维数组传递给void print_grid(char **grid),它应该是void print_grid(char grid[][GRID_WIDTH])
  • GRID_HEIGHT 和 GRID_WIDTH 是定义的常量整数
  • 将 void print_grid(char **grid) 更改为 print_grid(char grid[][GRID_WIDTH]) 似乎有效,谢谢

标签: c function multidimensional-array declaration


【解决方案1】:

您已经在 main 中声明了数组网格。

char grid[GRID_HEIGHT][GRID_WIDTH];

比如这个函数定义

char ** make_grid(char **grid) {
    char grid[GRID_HEIGHT][GRID_WIDTH] = {
        { '\n', ' ', '1', ' ', '|', ' ', '2', ' ', '|', ' ', '3', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '4', ' ', '|', ' ', '5', ' ', '|', ' ', '6', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '7', ' ', '|', ' ', '8', ' ', '|', ' ', '9', ' ' }
    };
    return grid;
}

至少没有意义,因为参数是在函数的外部块范围内重新声明的。

函数可能如下所示

void make_grid( char ( *grid )[GRID_WIDTH] )
{
    static const char *rows[] = 
    {
        { "\n 1 | 2 | 3 " } ,
        { "\n-----------" } ,
        { "\n 4 | 5 | 6 " } ,
        { "\n-----------" } ,
        { "\n 7 | 8 | 9 " }
    };
    const size_t N = sizeof( rows ) / sizeof( *rows );

    for ( size_t i = 0; i < N; i++ )
    {
        strncpy( grid[i], rows[i], GRID_WIDTH );
    }
}

并像这样称呼

make_grid( grid );

函数print_grid可以这样定义

void print_grid( char ( *grid )[GRID_WIDTH], size_t height ) 
{
    for ( size_t row = 0; row < height; row++) {
        for ( size_t column = 0; column < GRID_WIDTH; column++) {
            printf("%c", grid[row][column]);
        }
        putchar( '\n' );
    }
    putchar( '\n' );
}

并像这样称呼

print_grid( grid, GRID_HEIGHT );

【讨论】:

  • 不要使用strncpy,这是一个危险的函数,会导致strncpy( grid[i], rows[i], GRID_WIDTH );等bug。结果数组不是空终止的,因为GRID_WIDTH 在编写代码时不包含空终止符的空间。请改用memcpy
  • @Lundin 这不是错误。当字符数组不包含终止零时,这是一种设计解决方案。为什么决定 grid 的元素为零=终止?!
  • 因为strncpy 只是memcpy 的懒惰版本。你知道大小,你知道字符串不是空终止的,所以没有必要调用一个函数慢慢搜索不存在的空终止。
  • @Lundin 我认为在这种情况下,最好使用 strncpy 而不是 memcpy,因为对于初始化程序没有什么可说的。
【解决方案2】:

基本问题:

  • 您需要#include相关标头。
  • 您需要在调用函数之前声明它们。
  • 您不能从 C 中的函数返回数组。您可以返回指针,但这可能是错误的解决方案。如果你想复制一个数组,你必须使用memcpy
  • 在同一个作用域内不能有两个同名的变量grid
  • Pointer-to-pointers 不能指向数组并且它们与数组不兼容。所以你不能在这里使用指针到指针。

固定代码:

#define GRID_HEIGHT 5
#define GRID_WIDTH 12

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

void make_grid (char grid[GRID_HEIGHT][GRID_WIDTH]);
void print_grid (char grid[GRID_HEIGHT][GRID_WIDTH]);

int main(void) {
    char grid[GRID_HEIGHT][GRID_WIDTH];
    make_grid(grid);
    print_grid(grid);
}

void make_grid (char grid[GRID_HEIGHT][GRID_WIDTH]) {
    const char GRID [GRID_HEIGHT][GRID_WIDTH] = {
        { '\n', ' ', '1', ' ', '|', ' ', '2', ' ', '|', ' ', '3', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '4', ' ', '|', ' ', '5', ' ', '|', ' ', '6', ' ' } ,
        { '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' } ,
        { '\n', ' ', '7', ' ', '|', ' ', '8', ' ', '|', ' ', '9', ' ' }
    };
    memcpy( grid, GRID, sizeof(char[GRID_HEIGHT][GRID_WIDTH]) );
}

void print_grid (char grid[GRID_HEIGHT][GRID_WIDTH]) {
    for (int row = 0; row < GRID_HEIGHT; row++) {
        for (int column = 0; column < GRID_WIDTH; column++) {
            printf("%c", grid[row][column]);
        }
    }
    printf("\n");
}

在本例中,每个函数中的参数grid 是一个数组,它“衰减”为指向第一个元素的指针。二维数组的第一个元素是一维数组,因此您最终会得到一个数组指针。如果您不希望编译器“衰减”数组,您可以手动编写数组指针语法:char (*grid)[GRID_WIDTH],但它更难阅读,因此我不推荐它。

【讨论】:

    猜你喜欢
    • 2013-09-02
    • 1970-01-01
    • 2011-07-27
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多