C 程序中的 Char 变量行为
Char variable behavior in C program
我编写了一个数独求解器程序,该程序具有检查在特定位置设置值是否合法的功能:
typedef int cell;
typedef char value;
typedef value sudokuGrid[GRID_SIZE]; // GRID_SIZE is 81
int isLegal (sudokuGrid game, cell location,value candidateDigit);
我还写了一个函数来测试 isLegal 函数,给它一个数独谜题,一旦计算出解决方案,检查所有设置值是否正确:
static void testIsLegal(){
int i, solution;
int mid_result, result;
sudokuGrid testGrid = {
'6','4','.','.','.','.','8','1','7',
'1','7','.','8','6','.','2','.','4',
'.','.','.','.','.','.','.','9','6',
'.','8','.','.','9','6','.','.','.',
'.','6','.','3','.','1','.','2','.',
'.','.','.','2','5','.','.','6','.',
'8','2','.','.','.','.','.','.','.',
'3','.','7','.','1','8','.','4','2',
'4','5','1','.','.','.','.','8','3'
};
printf("Testing isLegal() function ............\n");
result = TRUE;
solution = hasSolution(testGrid);
showGame(testGrid);
int f = isLegal(testGrid,78,'9');
printf("isLegal(testGrid,78,9) = %d\n\n",f);
i = 0;
result = TRUE;
value cellValue;
if (solution){
while ((result == TRUE) && (i < GRID_SIZE)){
cellValue = testGrid[i];
testGrid[i] = EMPTY_VALUE;
printf("isLegal(testGrid,%d,%c) = %d\n",i,cellValue,isLegal(testGrid,i,cellValue));
result = result && isLegal(testGrid,i,cellValue);
testGrid[i] = cellValue;
i++;
}
}
if (result)
printf("\t\t\t\t\t [OK]\n");
else
printf("\t\t\t\t\t[NOK]\n");
}
执行这个函数错误的结果是:
6 4 2 5 3 9 8 1 7
1 7 5 8 6 2 2 3 4
9 3 8 1 4 7 5 9 6
2 8 3 7 9 6 1 7 5
5 6 4 3 8 1 3 2 8
7 1 9 2 5 4 4 6 9
8 2 6 4 2 3 6 5 1
3 9 7 6 1 8 7 4 2
4 5 1 9 7 5 9 8 3
这里有很多错误,但我在最后一行中提到了两个 9-s(位置 75 和 78)。对 isLegal(testGrid,78,'9') 执行了手动检查 returns FALSE,但是当我使用循环 isLegal(testGrid,i,cellValue) returns TRUE 时:
isLegal(testGrid,78,9) = 0
isLegal(testGrid,0,6) = 1
isLegal(testGrid,1,4) = 1
isLegal(testGrid,2,2) = 1
isLegal(testGrid,3,5) = 1
.....
isLegal(testGrid,78,9) = 1
isLegal(testGrid,79,8) = 1
isLegal(testGrid,80,3) = 1
我的问题是为什么当我在 ' ' 引号中使用 char 变量时(代码中的 isLegal(testGrid,78,'9'))它显示正确的结果,但当我使用 cellValue 变量时却没有?
如何解决?
谢谢!
添加附加信息:
#define MIN_VALUE '1'
#define MAX_VALUE '9'
#define EMPTY_VALUE '.'
#define NUM_VALUES (MAX_VALUE - MIN_VALUE + 1)
#define GRID_SIZE (NUM_VALUES * NUM_VALUES)
#define MAX_CELL (GRID_SIZE - 1)
#define TRUE 1
#define FALSE 0
#define MINI_SQUARE_SIZE 3
#define SQUARE_SIZE 9
typedef int cell;
typedef char value;
typedef value sudokuGrid[GRID_SIZE];
是合法函数:
int isLegal (sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
return (isLegalLine(game,location,candidateDigit) &&
isLegalColumn(game,location,candidateDigit) &&
isLegalSquare(game,location,candidateDigit));
}
static int isLegalLine(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int lineNumber = location / SQUARE_SIZE;
result = TRUE;
for (i = 0; i < GRID_SIZE; i++){
if (( i / SQUARE_SIZE ) == lineNumber){
if ( game[i] != candidateDigit ){
mid_result = TRUE;
}
else{
mid_result = FALSE;
}
result = result && mid_result;
}
}
return result;
}
static int isLegalColumn(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int columnNumber = location % SQUARE_SIZE;
result = TRUE;
for (i = 0; i < GRID_SIZE; i++){
if (( i % SQUARE_SIZE ) == columnNumber){
if ( game[i] != candidateDigit )
mid_result = TRUE;
else
mid_result = FALSE;
result = result && mid_result;
}
}
return result;
}
static int isLegalSquare(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int lineNumber = location / SQUARE_SIZE;
int columnNumber = location % SQUARE_SIZE;
// int squareNumber;
if ( lineNumber < MINI_SQUARE_SIZE){
lineNumber = 0;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 1;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 2;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 3;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
else if (lineNumber < 2*MINI_SQUARE_SIZE){
lineNumber = MINI_SQUARE_SIZE;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 4;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 5;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 6;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
else{
lineNumber = 2*MINI_SQUARE_SIZE;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 7;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 8;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 9;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
result = TRUE;
int squareStartLocation = columnNumber + ( SQUARE_SIZE * lineNumber);
int k = 0;
int squareStartLocationLineEnd;
while (k < MINI_SQUARE_SIZE){
squareStartLocationLineEnd = squareStartLocation + MINI_SQUARE_SIZE;
for (i = squareStartLocation; i < squareStartLocationLineEnd; i++){
if (game[i] != candidateDigit)
mid_result = TRUE;
else
mid_result = FALSE;
result = result && mid_result;
}
k++;
squareStartLocation += SQUARE_SIZE;
result = result && mid_result;
}
return result;
}
稍微想想这是什么:
testGrid[i] = EMPTY_VALUE;
将在下一行对 isLegal() 执行操作:
printf("isLegal(testGrid,%d,%c) = %d\n",i,cellValue,isLegal(testGrid,i,cellValue));
也许这在 isLegal() 中做了一些你不想要的事情
如果您这样做 char a = 9
,您就使 a
具有 ASCII 值。
例如:
char letter = 80;
等同于 char letter = 'P';
参数 candidateDigit 将 作为 char 类型传递给 isLegal()。
它必须是导致函数始终 return TRUE 的循环上下文,因此您需要:
- 向我们展示 isLegal() 的代码
- 告诉我们 EMPTY_VALUE
的价值
更新 1:感谢您提供额外信息。我插入了您填写的 "bad" 数据,将解决方案设置为 TRUE,并且测试停止在位置 14 失败(正确,因为该位置包含“2”并且同一行中还有另一个)。所以看来你的代码是正确的!至少就这个测试而言。
测试网格:
sudokuGrid testGrid = {
'6','4','2','5','3','9','8','1','7',
'1','7','5','8','6','2','2','3','4',
'9','3','8','1','4','7','5','9','6',
'2','8','3','7','9','6','1','7','5',
'5','6','4','3','8','1','3','2','8',
'7','1','9','2','5','4','4','6','9',
'8','2','6','4','2','3','6','5','1',
'3','9','7','6','1','8','7','4','2',
'4','5','1','9','7','5','9','8','3'
};
测试输出:
isLegal(testGrid,78,9) = 0
isLegal(testGrid,0,6) = 1
isLegal(testGrid,1,4) = 1
isLegal(testGrid,2,2) = 1
isLegal(testGrid,3,5) = 1
isLegal(testGrid,4,3) = 1
isLegal(testGrid,5,9) = 1
isLegal(testGrid,6,8) = 1
isLegal(testGrid,7,1) = 1
isLegal(testGrid,8,7) = 1
isLegal(testGrid,9,1) = 1
isLegal(testGrid,10,7) = 1
isLegal(testGrid,11,5) = 1
isLegal(testGrid,12,8) = 1
isLegal(testGrid,13,6) = 1
isLegal(testGrid,14,2) = 0
[NOK]
NB 只有我所做的其他代码更改是将 isLegal() 移动到它调用的函数下方(以避免默认提升 return 类型)并注释掉对 hasSolution() 和 showGrid() 的调用.
我编写了一个数独求解器程序,该程序具有检查在特定位置设置值是否合法的功能:
typedef int cell;
typedef char value;
typedef value sudokuGrid[GRID_SIZE]; // GRID_SIZE is 81
int isLegal (sudokuGrid game, cell location,value candidateDigit);
我还写了一个函数来测试 isLegal 函数,给它一个数独谜题,一旦计算出解决方案,检查所有设置值是否正确:
static void testIsLegal(){
int i, solution;
int mid_result, result;
sudokuGrid testGrid = {
'6','4','.','.','.','.','8','1','7',
'1','7','.','8','6','.','2','.','4',
'.','.','.','.','.','.','.','9','6',
'.','8','.','.','9','6','.','.','.',
'.','6','.','3','.','1','.','2','.',
'.','.','.','2','5','.','.','6','.',
'8','2','.','.','.','.','.','.','.',
'3','.','7','.','1','8','.','4','2',
'4','5','1','.','.','.','.','8','3'
};
printf("Testing isLegal() function ............\n");
result = TRUE;
solution = hasSolution(testGrid);
showGame(testGrid);
int f = isLegal(testGrid,78,'9');
printf("isLegal(testGrid,78,9) = %d\n\n",f);
i = 0;
result = TRUE;
value cellValue;
if (solution){
while ((result == TRUE) && (i < GRID_SIZE)){
cellValue = testGrid[i];
testGrid[i] = EMPTY_VALUE;
printf("isLegal(testGrid,%d,%c) = %d\n",i,cellValue,isLegal(testGrid,i,cellValue));
result = result && isLegal(testGrid,i,cellValue);
testGrid[i] = cellValue;
i++;
}
}
if (result)
printf("\t\t\t\t\t [OK]\n");
else
printf("\t\t\t\t\t[NOK]\n");
}
执行这个函数错误的结果是:
6 4 2 5 3 9 8 1 7
1 7 5 8 6 2 2 3 4
9 3 8 1 4 7 5 9 6
2 8 3 7 9 6 1 7 5
5 6 4 3 8 1 3 2 8
7 1 9 2 5 4 4 6 9
8 2 6 4 2 3 6 5 1
3 9 7 6 1 8 7 4 2
4 5 1 9 7 5 9 8 3
这里有很多错误,但我在最后一行中提到了两个 9-s(位置 75 和 78)。对 isLegal(testGrid,78,'9') 执行了手动检查 returns FALSE,但是当我使用循环 isLegal(testGrid,i,cellValue) returns TRUE 时:
isLegal(testGrid,78,9) = 0
isLegal(testGrid,0,6) = 1
isLegal(testGrid,1,4) = 1
isLegal(testGrid,2,2) = 1
isLegal(testGrid,3,5) = 1
.....
isLegal(testGrid,78,9) = 1
isLegal(testGrid,79,8) = 1
isLegal(testGrid,80,3) = 1
我的问题是为什么当我在 ' ' 引号中使用 char 变量时(代码中的 isLegal(testGrid,78,'9'))它显示正确的结果,但当我使用 cellValue 变量时却没有? 如何解决?
谢谢!
添加附加信息:
#define MIN_VALUE '1'
#define MAX_VALUE '9'
#define EMPTY_VALUE '.'
#define NUM_VALUES (MAX_VALUE - MIN_VALUE + 1)
#define GRID_SIZE (NUM_VALUES * NUM_VALUES)
#define MAX_CELL (GRID_SIZE - 1)
#define TRUE 1
#define FALSE 0
#define MINI_SQUARE_SIZE 3
#define SQUARE_SIZE 9
typedef int cell;
typedef char value;
typedef value sudokuGrid[GRID_SIZE];
是合法函数:
int isLegal (sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
return (isLegalLine(game,location,candidateDigit) &&
isLegalColumn(game,location,candidateDigit) &&
isLegalSquare(game,location,candidateDigit));
}
static int isLegalLine(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int lineNumber = location / SQUARE_SIZE;
result = TRUE;
for (i = 0; i < GRID_SIZE; i++){
if (( i / SQUARE_SIZE ) == lineNumber){
if ( game[i] != candidateDigit ){
mid_result = TRUE;
}
else{
mid_result = FALSE;
}
result = result && mid_result;
}
}
return result;
}
static int isLegalColumn(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int columnNumber = location % SQUARE_SIZE;
result = TRUE;
for (i = 0; i < GRID_SIZE; i++){
if (( i % SQUARE_SIZE ) == columnNumber){
if ( game[i] != candidateDigit )
mid_result = TRUE;
else
mid_result = FALSE;
result = result && mid_result;
}
}
return result;
}
static int isLegalSquare(sudokuGrid game, cell location,value candidateDigit){
assert (location >= 0);
assert (location <= GRID_SIZE);
assert (candidateDigit >= MIN_VALUE);
assert (candidateDigit <= MAX_VALUE);
int result, mid_result;
int i;
int lineNumber = location / SQUARE_SIZE;
int columnNumber = location % SQUARE_SIZE;
// int squareNumber;
if ( lineNumber < MINI_SQUARE_SIZE){
lineNumber = 0;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 1;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 2;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 3;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
else if (lineNumber < 2*MINI_SQUARE_SIZE){
lineNumber = MINI_SQUARE_SIZE;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 4;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 5;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 6;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
else{
lineNumber = 2*MINI_SQUARE_SIZE;
if (columnNumber < MINI_SQUARE_SIZE){
// squareNumber = 7;
columnNumber = 0;
}
else if (columnNumber < 2*MINI_SQUARE_SIZE){
// squareNumber = 8;
columnNumber = MINI_SQUARE_SIZE;
}
else{
// squareNumber = 9;
columnNumber = 2*MINI_SQUARE_SIZE;
}
}
result = TRUE;
int squareStartLocation = columnNumber + ( SQUARE_SIZE * lineNumber);
int k = 0;
int squareStartLocationLineEnd;
while (k < MINI_SQUARE_SIZE){
squareStartLocationLineEnd = squareStartLocation + MINI_SQUARE_SIZE;
for (i = squareStartLocation; i < squareStartLocationLineEnd; i++){
if (game[i] != candidateDigit)
mid_result = TRUE;
else
mid_result = FALSE;
result = result && mid_result;
}
k++;
squareStartLocation += SQUARE_SIZE;
result = result && mid_result;
}
return result;
}
稍微想想这是什么:
testGrid[i] = EMPTY_VALUE;
将在下一行对 isLegal() 执行操作:
printf("isLegal(testGrid,%d,%c) = %d\n",i,cellValue,isLegal(testGrid,i,cellValue));
也许这在 isLegal() 中做了一些你不想要的事情
如果您这样做 char a = 9
,您就使 a
具有 ASCII 值。
例如:
char letter = 80;
等同于 char letter = 'P';
参数 candidateDigit 将 作为 char 类型传递给 isLegal()。 它必须是导致函数始终 return TRUE 的循环上下文,因此您需要:
- 向我们展示 isLegal() 的代码
- 告诉我们 EMPTY_VALUE 的价值
更新 1:感谢您提供额外信息。我插入了您填写的 "bad" 数据,将解决方案设置为 TRUE,并且测试停止在位置 14 失败(正确,因为该位置包含“2”并且同一行中还有另一个)。所以看来你的代码是正确的!至少就这个测试而言。
测试网格:
sudokuGrid testGrid = {
'6','4','2','5','3','9','8','1','7',
'1','7','5','8','6','2','2','3','4',
'9','3','8','1','4','7','5','9','6',
'2','8','3','7','9','6','1','7','5',
'5','6','4','3','8','1','3','2','8',
'7','1','9','2','5','4','4','6','9',
'8','2','6','4','2','3','6','5','1',
'3','9','7','6','1','8','7','4','2',
'4','5','1','9','7','5','9','8','3'
};
测试输出:
isLegal(testGrid,78,9) = 0
isLegal(testGrid,0,6) = 1
isLegal(testGrid,1,4) = 1
isLegal(testGrid,2,2) = 1
isLegal(testGrid,3,5) = 1
isLegal(testGrid,4,3) = 1
isLegal(testGrid,5,9) = 1
isLegal(testGrid,6,8) = 1
isLegal(testGrid,7,1) = 1
isLegal(testGrid,8,7) = 1
isLegal(testGrid,9,1) = 1
isLegal(testGrid,10,7) = 1
isLegal(testGrid,11,5) = 1
isLegal(testGrid,12,8) = 1
isLegal(testGrid,13,6) = 1
isLegal(testGrid,14,2) = 0
[NOK]
NB 只有我所做的其他代码更改是将 isLegal() 移动到它调用的函数下方(以避免默认提升 return 类型)并注释掉对 hasSolution() 和 showGrid() 的调用.