【问题标题】:Garbage output of my int** in a struct being printed正在打印的结构中我的 int** 的垃圾输出
【发布时间】:2023-09-24 08:53:01
【问题描述】:

我从文件中读取整数值,通过空格字符对其进行解析,然后将它们插入到我的结构中名为 game 的 int** 中。使用打印语句,我已经确认正确的值被放置在 int** 的正确位置,但是一旦我离开 while 循环或返回结构,打印的值是错误的。

我的结构:

typedef struct Map_s{

        char * defender;
        char * attacker;
        int missles;
        int ** layout;
        size_t capacity;
        size_t size;
}map;

结构体的初始化:

map * newGame(){

        map * game = malloc(sizeof(map));
        game->layout = (int**)malloc(_DEFAULT_MAP_SIZE * sizeof(int*));
        game->defender = NULL;
        game->attacker = NULL;
        game->missles = 0;
        game->capacity = _DEFAULT_MAP_SIZE;
        game->size = 0;

        return game;
}

文件解析:

map * game = newGame();

    char * token;
    char * dup;
    char * ptr;
    int ret;
    const char delim[2] = " ";
    char * buf = NULL;
    char * temp = NULL;
    size_t size = _MAX_SIZE;
    int lineNum = 1;

    while( getline(&temp, &size, fp) > 1 ){
            buf = strtok(temp, "\n");
            dup = strdup(buf);
            if( buf[0] != '#' ){
                    if( lineNum == 1){
                            if( game->defender == NULL ){
                                    game->defender = dup;
                            }
                    }
                    else if( lineNum == 2 ){
                            if( game->attacker == NULL )
                                    game->attacker = dup;
                    }
                    else if( lineNum == 3 ){
                            game->missles = atoi(dup);
                    }
                    else if( lineNum > 3 ){
                            token = strtok(dup, delim);
                            while( token != NULL ){
                                    if( game->size >= game->capacity ){
                                            game->layout = (int**)realloc(game->layout, \
                                                            game->capacity*2 * sizeof(int*));
                                            game->capacity = game->capacity * 2;
                                    }
                                    ret = (int)strtol(token, &ptr, 10);
                                    game->layout[game->size] = &ret;
                                    game->size = game->size + 1;
                                    token = strtok(NULL, delim);
                                    //printf("%s ", token);
                            }
                    }**

                    lineNum++;
            }
    }



    return game;

我几乎可以肯定我的代码在第二个 while 循环中的某个地方出现了问题。我正在尝试将字符串转换为整数,然后将其保存到 int** 中的正确位置。

我如何从 main 打印:

for( size_t i = 0; i < thisgame->size; i++ ){
            printf("%d ", *thisgame->layout[i]);
            if( i == 0)
                    continue;
            else if( (i+1) % 10 == 0 )
                    printf("\n");
    }

返回结构后主函数的输出:

0 0 0 0 0 0 0 0 0 0 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10 
10 10 10 10 10 10 10 10 10 10

输出应该是什么样子(文件中的内容):

2 2 2 2 2 2 2 2 2 2
2 2 6 6 7 7 7 5 5 2
2 2 7 7 7 2 2 17 17 17 2
2 2 2 2 2 2 2 2 2 2
8 8 8 6 6 6 9 9 9 2
2 2 2 2 2 2 2 2 2 2
10 10 10 4 4 9 9 9 2
2 2 2 2 2 2 2 2 2 2
3 3 3 6 6 6 9 9 9 2
3 3 3 6 6 6 9 9 9 2
2 2 2 2 2 2 2 2 2 2

【问题讨论】:

  • game-&gt;layout[game-&gt;size] = &amp;ret; 您似乎在存储ret 的地址而不是值。这就是你想要的吗?
  • @D.Go 如果没有 &ret,我会收到警告:从不强制转换的整数中生成指针
  • **token = strtok(dup, delim); 行...这是实际的代码行,还是您使用初始的** 来标记行?因为这看起来是试图双重取消引用尚未(在首次使用时)初始化的指针)。这可能也破坏了该循环的第一次迭代。
  • @PhilM 对不起,一开始就不应该在那里。不知道它是怎么进来的。
  • @Boballendo 好的,那应该是您的这部分代码不正确的线索。我不认为您正在尝试存储指针数组,这就是您进行此设置的方式。你想要一个整数数组。

标签: c structure c99


【解决方案1】:

问题是您使用的是 int* 数组,而您真正想要的是 int 数组。每次存储 ret 时,都存储了相同的地址。当您检查循环中的值时,它将是正确的,因为ret 包含您想要的值......直到下一次迭代。

【讨论】:

  • 谢谢!我的一个非常愚蠢的错误让我花费了数小时的屏幕时间。永远不要忘记基础知识。
  • @Boballendo 请接受其中一个答案,以便我们知道您的问题已结束。此外,将它们标记为有用(向上箭头)将不胜感激。
  • 我确实支持了你的答案,但是因为我是新人,所以我的答案会被记录下来,不会公开显示分数
  • @Boballendo 啊,好的。它会让你接受答案吗?
  • 我该怎么做?我在页面上看不到任何内容
【解决方案2】:

我发现了几个问题。

第一行是**token = strtok(dup, delim);。在此行的第一次运行时,token 没有有效值,因此取消引用它不是一次,而是两次,也会导致问题。我相信这应该只是token = strtok(dup, delim);

这将导致 if 块中的 while 循环的第一次迭代返回错误值(至少所有这些 0 似乎都符合这个猜测)。

其次是 D Go 指出的,因为你给出了ret 的地址(地址不会改变),所以game-&gt;layout 的每个元素都有相同的地址,因此查看相同的 int (适合所有​​这 10 岁)。

我认为解决这个问题的方法就是将layout 设为int * 的数组(调整分配代码以适应),并将ret 直接分配给每个元素。

【讨论】: