当我运行print_puzzle(create_puzzle(input))
时,我在输出的底部得到一堆gobbledegook,只在最后一行。我不知道为什么会这样。输出应该是9行9个数字(输入是一个数独拼图,零代表空格)。
这一堆代码应该接受输入,制作一个二维的字符串数组,然后使用print_puzzle在网格中输出这些字符串。它们是字符串,因为最终我将实现一种方法来显示正方形可能的所有值。但就目前而言,当我打印出来时,事情就搞砸了。我甚至尝试将null值放在所有81个字符串的每一个元素中,但是当它打印字符串时它仍然被搞砸了。我迷路了!
typedef struct square {
char vals[10]; // string of possible values
} square_t;
typedef struct puzzle {
square_t squares[9][9];
} puzzle_t;
static puzzle_t *create_puzzle(unsigned char vals[9][9]) {
puzzle_t puz;
puzzle_t *p = &puz;
int i, j, k, valnum;
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
puz.squares[i][j].vals[0] = '\0';
puz.squares[i][j].vals[1] = '\0';
puz.squares[i][j].vals[2] = '\0';
puz.squares[i][j].vals[3] = '\0';
puz.squares[i][j].vals[4] = '\0';
puz.squares[i][j].vals[5] = '\0';
puz.squares[i][j].vals[6] = '\0';
puz.squares[i][j].vals[7] = '\0';
puz.squares[i][j].vals[8] = '\0';
puz.squares[i][j].vals[9] = '\0';
valnum = vals[i][j] -'0';
for (k = 0; k < 10; k++){
if ((char)(k + '0') == (char)(valnum + '0')){
char tmpStr[2] = {(char)(valnum +'0'),'\0'};
strcat(puz.squares[i][j].vals, tmpStr);
}
}
}
}
return p;
}
void print_puzzle(puzzle_t *p) {
int i, j;
for (i=0; i<9; i++) {
for (j=0; j<9; j++) {
printf(" %2s", p->squares[i][j].vals);
}
printf("\n");
}
}
答案 0 :(得分:1)
在函数create_puzzle()
中,您将返回类型为puzzle_t
的指针。但是,一旦从函数返回,类型puz
的变量puzzle_t
的地址就无效。
在函数内声明的变量是局部变量。它们只能由 inside 该函数的语句使用。这些局部变量对于它们自己以外的函数是不可知的,因此返回局部变量的地址没有意义,因为当函数返回时,它在堆栈上使用的本地存储被程序认为是无效的,尽管它可能是没有立即清理。逻辑上,puz
处的值是不确定的,访问它会导致未定义的行为。
您可以将puz
设为全局变量,并按照您现在的方式使用它。
答案 1 :(得分:1)
简而言之:
在函数create_puzzle()
中,您将返回指向局部变量puz
的指针。只知道局部变量在它们自己内部起作用。因此,create_puzzle返回的指针引用的内容是不确定的。
更多细节:
在C ++中,局部变量通常作为存储在&#34;堆栈上生成。数据结构。输入create_puzzle()
方法时,其局部变量生效。当方法结束时,函数的局部变量将会死亡。不需要实现C ++就可以保持您在堆栈中留下的垃圾不受影响,这样您就可以访问它的原始内容。 C ++不是一种安全的语言,实现让你犯错并逃脱它。其他内存安全语言通过限制功率来解决此问题。例如,在C#中,您可以获取本地的地址,但语言设计巧妙,因此在本地生命周期结束后无法使用它。
这个答案非常棒: Can a local variable's memory be accessed outside its scope?
答案 2 :(得分:0)
您在这里返回一个局部变量:
return p;
在函数外部声明p
和puz
,然后它应该可以正常工作。
答案 3 :(得分:0)
p
指向函数结束后不可用的本地内存。返回会导致问题。而是分配内存。
// puzzle_t puz;
// puzzle_t *p = &puz;
puzzle_t *p = malloc(sizeof *p);
assert(p);
请确保在调用代码完成后使用free()
内存。