C 数组检查行和列。指针问题(取消引用 NULL 指针警告)
C Array check row and column. Issue with pointer(dereferencing NULL-Pointer warning)
我对编程还是个新手,这个网站请对我这个不知情的傻瓜好一点。我目前正在做一项任务。我们需要在 C 中制作一个 Binoxxo 拼图,并在输入值时根据规则检查它是否正确。规则是:
- 'x'或'o'.
后面不能超过两个
- 每一行和每一列都需要等量的 'x' 和 'o'.
- 所有行和列都是唯一的。
Binoxxo 字段是一个 array[10][10]
,填充有 'x'、'o' 和 ' '。对于第二条规则,我有一个可行的解决方案。但是,我真的无法弄清楚其他两个。我现在越来越习惯数组,但我想我还是不太明白。
这是我对规则 1 的处理方式:
//There can't be more than two following 'x' or 'o'
for (i = j = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if ((puzzle[i][j + 1] == val) && (puzzle[i][j - 1] == val)) x++;
if ((puzzle[i][j + 1] == val) && (puzzle[i][j + 2] == val)) x++;
if ((puzzle[i][j - 1] == val) && (puzzle[i][j - 2] == val)) x++;
if ((puzzle[i + 1][j] == val) && (puzzle[i - 1][j] == val)) x++;
if ((puzzle[i + 1][j] == val) && (puzzle[i + 2][j] == val)) x++;
if ((puzzle[i - 1][j] == val) && (puzzle[i - 2][j] == val)) x++;
if (x > 0)
return false;
}
}
为了更好地理解,这是数组的图片。
我试图覆盖一个点周围的区域,以确保连续出现的 x 或 o 不会超过两个。 val通过控制台输入到另一个函数中,可以是x或o。
当我尝试 运行 时,它首先正确启动,然后我尝试输入一些内容,但出现错误 0xC0000005 Access Violation
.
我了解到当指针出现问题时可能会发生此错误。我注意到我有一个警告 C6011
dereferencing NULL-Pointer,这让我想到了这个:
char** board()
{
int i, j;
char** puzzle;
char arrpuzzle[10][10] = {' ', ' ', 'o', 'x', ' ', ' ', ' ', ' ', ' ', 'o',
'x', ' ', ' ', 'x', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', 'o', ' ', ' ', 'x', ' ', ' ', ' ', 'o',
' ', ' ', ' ', ' ', 'o', ' ', ' ', ' ', 'o', ' ',
'o', ' ', ' ', 'x', ' ', ' ', ' ', 'x', ' ', ' ',
'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'o', ' ',
' ', ' ', ' ', 'x', ' ', 'x', ' ', ' ', ' ', ' ',
' ', 'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', 'o', ' ', 'o', ' ', 'x', 'x', ' ', ' ', ' ',
' ', ' ', 'x', ' ', ' ', ' ', 'o', ' ', 'x', 'o' };
puzzle = (char**)malloc(sizeof(char*) * 10);
for (i = 0; i < 10; i++) {
puzzle[i] = (char*)malloc(sizeof(char) * 10); // Warning here...
for (j = 0; j < 10; j++) {
puzzle[i][j] = arrpuzzle[i][j]; // And here
}
}
return puzzle;
}
我做错了什么?问题是由于malloc吗?我该怎么做才能解决这个问题?有人可以给我一些提示吗?
在您的规则 1 测试代码中,无条件检查相邻单元格,即使被测试的单元格位于边缘(或角落)。
在记忆中,puzzle
指向的内容看起来像这样:
...
puzzle
------[X]------------------------------------------------------
--------\------------------------------------------------------
---------[A][B][C][D][E][F][G][H][I][J]------------------------
----------/--/--| ... \------------------------
---------/--/---[][][][][][][][][][]---\-----------------------
--------/--[][][][][][][][][][]---------[][][][][][][][][][]---
-------[][][][][][][][][][]------------------------------------
---------------------------------------------------------------
...
访问puzzle[i][j+1]
时,如果i==2
和j==3
,则访问地址C
后的第5个字符(C+4*sizeof(char)
)。但是如果 j==9
,那么将访问一个未定义的值(“第 11 个”- 分配的最后一个之后的 char 单元格)。这可能不会导致访问冲突,因为它可能在进程的内存范围内,但可能会导致细微且难以发现的错误。
然而,当puzzle[i+1][j]
被访问时,和i==9
,有一个不同的问题:地址J
之后的地址单元将被视为一个地址(a char *
),并取消引用。
那里存储的值可能是:
- 某些值恰好是进程内存范围内的地址,导致细微错误。
- 0x0,导致 NULL 取消引用。
- 某些值超出进程的内存范围,导致访问冲突。
其他边([i-1]
和 [j-1]
)的问题类似。
我对编程还是个新手,这个网站请对我这个不知情的傻瓜好一点。我目前正在做一项任务。我们需要在 C 中制作一个 Binoxxo 拼图,并在输入值时根据规则检查它是否正确。规则是:
- 'x'或'o'. 后面不能超过两个
- 每一行和每一列都需要等量的 'x' 和 'o'.
- 所有行和列都是唯一的。
Binoxxo 字段是一个 array[10][10]
,填充有 'x'、'o' 和 ' '。对于第二条规则,我有一个可行的解决方案。但是,我真的无法弄清楚其他两个。我现在越来越习惯数组,但我想我还是不太明白。
这是我对规则 1 的处理方式:
//There can't be more than two following 'x' or 'o'
for (i = j = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if ((puzzle[i][j + 1] == val) && (puzzle[i][j - 1] == val)) x++;
if ((puzzle[i][j + 1] == val) && (puzzle[i][j + 2] == val)) x++;
if ((puzzle[i][j - 1] == val) && (puzzle[i][j - 2] == val)) x++;
if ((puzzle[i + 1][j] == val) && (puzzle[i - 1][j] == val)) x++;
if ((puzzle[i + 1][j] == val) && (puzzle[i + 2][j] == val)) x++;
if ((puzzle[i - 1][j] == val) && (puzzle[i - 2][j] == val)) x++;
if (x > 0)
return false;
}
}
为了更好地理解,这是数组的图片。
我试图覆盖一个点周围的区域,以确保连续出现的 x 或 o 不会超过两个。 val通过控制台输入到另一个函数中,可以是x或o。
当我尝试 运行 时,它首先正确启动,然后我尝试输入一些内容,但出现错误 0xC0000005 Access Violation
.
我了解到当指针出现问题时可能会发生此错误。我注意到我有一个警告 C6011
dereferencing NULL-Pointer,这让我想到了这个:
char** board()
{
int i, j;
char** puzzle;
char arrpuzzle[10][10] = {' ', ' ', 'o', 'x', ' ', ' ', ' ', ' ', ' ', 'o',
'x', ' ', ' ', 'x', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', 'o', ' ', ' ', 'x', ' ', ' ', ' ', 'o',
' ', ' ', ' ', ' ', 'o', ' ', ' ', ' ', 'o', ' ',
'o', ' ', ' ', 'x', ' ', ' ', ' ', 'x', ' ', ' ',
'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'o', ' ',
' ', ' ', ' ', 'x', ' ', 'x', ' ', ' ', ' ', ' ',
' ', 'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', 'o', ' ', 'o', ' ', 'x', 'x', ' ', ' ', ' ',
' ', ' ', 'x', ' ', ' ', ' ', 'o', ' ', 'x', 'o' };
puzzle = (char**)malloc(sizeof(char*) * 10);
for (i = 0; i < 10; i++) {
puzzle[i] = (char*)malloc(sizeof(char) * 10); // Warning here...
for (j = 0; j < 10; j++) {
puzzle[i][j] = arrpuzzle[i][j]; // And here
}
}
return puzzle;
}
我做错了什么?问题是由于malloc吗?我该怎么做才能解决这个问题?有人可以给我一些提示吗?
在您的规则 1 测试代码中,无条件检查相邻单元格,即使被测试的单元格位于边缘(或角落)。
在记忆中,puzzle
指向的内容看起来像这样:
...
puzzle
------[X]------------------------------------------------------
--------\------------------------------------------------------
---------[A][B][C][D][E][F][G][H][I][J]------------------------
----------/--/--| ... \------------------------
---------/--/---[][][][][][][][][][]---\-----------------------
--------/--[][][][][][][][][][]---------[][][][][][][][][][]---
-------[][][][][][][][][][]------------------------------------
---------------------------------------------------------------
...
访问puzzle[i][j+1]
时,如果i==2
和j==3
,则访问地址C
后的第5个字符(C+4*sizeof(char)
)。但是如果 j==9
,那么将访问一个未定义的值(“第 11 个”- 分配的最后一个之后的 char 单元格)。这可能不会导致访问冲突,因为它可能在进程的内存范围内,但可能会导致细微且难以发现的错误。
然而,当puzzle[i+1][j]
被访问时,和i==9
,有一个不同的问题:地址J
之后的地址单元将被视为一个地址(a char *
),并取消引用。
那里存储的值可能是:
- 某些值恰好是进程内存范围内的地址,导致细微错误。
- 0x0,导致 NULL 取消引用。
- 某些值超出进程的内存范围,导致访问冲突。
其他边([i-1]
和 [j-1]
)的问题类似。