【问题标题】:How can i malloc a char **我怎样才能malloc一个字符**
【发布时间】:2021-12-30 22:14:26
【问题描述】:

我必须为学校编写一个战舰游戏,所以我试图生成玩家将要放置他们的船的地图,我有一个段错误,但我不明白为什么。

这是我的代码:

主要:

int main(int ac, char **av)
{
    map_data map_data;
    print_map(map_gen(map_data));
    return(0);
}

结构:

typedef struct map_data {
    int lines;
    int letters;
    int width;
    int height;
}map_data;

地图生成:

char **map_gen(map_data map_data)
{
    map_data.lines = 0;
    map_data.width = 18;
    map_data.height = 10;
    map_data.letters = 65;
    char **map = malloc(sizeof((char)18 * 10));

    for (int s = 0; s <= map_data.height ; s++) {
        for (int c = 0; c <= map_data.width; c++) {
            map_fill(map, map_data, s, c);
        }
    }
    return (map);
}

char **map 的填充:

void char_fill(char **map, char ch, int s, int c)
{
        map[s][c] = ch;
}

void map_fill(char **map, map_data map_data, int s, int c)
{
    if (c == 1)
        char_fill(map, '|', s, c);
    if (s == 1)
        char_fill(map, '-', s, c);
    if (c == map_data.width)
        char_fill(map, '\n', s, c);
    map_fill2(map, map_data, s, c);
}

int map_fill2(char **map, map_data map_data, int s, int c)
{
    if (s == 0 && c == 0)
        char_fill(map, ' ', s, c);
    if (s == 1 && c == 1)
        char_fill(map, '+', s, c);
    if (c > 1 && c % 2 == 0)
        char_fill(map, '.', s, c);
    if (s > 1 && c % 2 == 1)
        char_fill(map, ' ', s, c);
    if (s == 10 && c == 18)
        char_fill(map, '\0', s, c);
    if (s > 1 && c == 0) {
        char_fill(map, my_int_to_char(map_data.lines), 0, 0);
        map_data.lines = map_data.lines + 1;
    }
    if (!map[s][c]) {
        my_putstr("error filling the map, please try again.");
        return (EXIT_FAILURE);
    }
}

打印:

void print_map(char **map)
{
    int h = 0;
    int w = 0;

    while (map[h][w] != '\0') {
        while (map[h][w] != '\n') {
            my_putchar(map[h][w]);
            w = w + 1;
        }
        h = h + 1;
    }
}

我做错了吗? 关于如何改进我的代码的任何提示?

谢谢

【问题讨论】:

    标签: c malloc


    【解决方案1】:
    1. 您不需要一个指向仅指向二维数组的指针。
    2. 使用正确的类型。
    3. 将数据包装到您的结构中。不要在不需要的情况下使用单独的数据结构
    4. C atart 中的索引从 0 开始。
    typedef struct map_data {
        size_t lines;
        size_t letters;
        size_t width;
        size_t height;
        char map[];
    }map_data;
    
    int map_fill2(map_data *map, size_t s, size_t c);
    
    
    void char_fill(map_data *map, char ch, size_t s, size_t c)
    {
        char (*cmap)[map -> width] = (char (*)[map -> width])map -> map;
        cmap[s][c] = ch;
    }
    
    void map_fill(map_data *map, size_t s, size_t c)
    {
        if (c == 0)
            char_fill(map, '|', s, c);
        if (s == 0)
            char_fill(map, '-', s, c);
        if (c == map -> width - 1)
            char_fill(map, '\n', s, c);
        map_fill2(map, s, c);
    }
    
    int map_fill2(map_data *map, size_t s, size_t c)
    {
        char (*cmap)[map -> width] = (char (*)[map -> width])map -> map;
        if (s == 0 && c == 0)
            char_fill(map, ' ', s, c);
        if (s == 1 && c == 1)
            char_fill(map, '+', s, c);
        if (c > 1 && c % 2 == 0)
            char_fill(map, '.', s, c);
        if (s > 1 && c % 2 == 1)
            char_fill(map, ' ', s, c);
        if (s == 10 && c == 18)
            char_fill(map, '\0', s, c);
        if (s > 1 && c == 0) {
            char_fill(map, my_int_to_char(map -> lines), 0, 0);
            map -> lines += 1;
        }
        if (!cmap[s][c]) {
            puts("error filling the map, please try again.");
            return (EXIT_FAILURE);
        }
        return 0;
    }
    
    map_data *map_gen(size_t lines, size_t letters, size_t width, size_t height)
    {
        map_data *map = malloc(sizeof(*map) + width * height * sizeof(map -> map[0]));
    
        if(map)
        {
            map -> width = width;
            map -> lines = lines;
            map -> letters = letters;
            map -> height = height;
            for (size_t s = 0; s < height ; s++) 
            {
                for (size_t c = 0; c < width; c++) 
                {
                    map_fill(map, s, c);
                }
            }
        }
        return (map);
    }
    

    【讨论】:

    • 可能想在这个答案的良好应用中添加对Flexible array member 的引用。可能对 OP 来说是新事物。
    • 感谢您的宝贵时间,您所写的内容确实有助于帮助我理解。
    【解决方案2】:

    至少这个问题:

    sizeof((char)18 * 10)int 的大小,可能是 4。

    分配给被引用对象的大小乘以所需数量。

    // char **map = malloc(sizeof((char)18 * 10));
    char **map = malloc(sizeof *map * map_data.height);
    

    然后为每一行分配

    // Note <, not <=
    for (int row = 0; row < map_data.height; row++) {
        map[row] = malloc(sizeof *(map[row]) * map_data.width);
        for (int col = 0; col < map_data.width; col++) {
            map_fill(map, map_data, row, col);
        }
    }
    

    健壮的代码也会检查分配失败。

    【讨论】:

    • 有点狂热地尝试在sizeof 中避免()。它使阅读变得困难。 sizeof(*map) * map_data.height 好多了
    • @0___________ 既不狂热也不难读,而是风格问题。就像这些倾向于圣战的问题一样,编码到你的团队的风格指南中。也许sizeof map[0] * map_data.height
    • @0___________ this 进入() 位。 C 规范使用全部 3 个:sizeof *ptr, sizeof ptr[0], sizeof (*ptr).
    • 该链接证明了什么? IMO sizeof *map * map_data.height 是不可读的,即使它在 C 中是正确的。() 提供对象和乘法之间的逻辑分离,使其在未来更容易阅读和维护
    • @0___________ 链接是对其他观点的引用,不是证明,也不是暗示。
    猜你喜欢
    • 2011-01-10
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 2019-09-01
    • 1970-01-01
    相关资源
    最近更新 更多