C语言宾果校验程序触发Signal 11错误的问题排查求助
问题分析与修复
你的程序抛出Signal 11(段错误)的核心原因是指针数组未分配有效内存就直接读写,同时存在多处类型不匹配和逻辑错误,下面逐个拆解问题并给出修复方案:
主要错误点
1. 指针数组误用,未分配内存
你定义的bingoPattern、playerBoard、playerPattern都是char*类型的二维数组,但这些指针并没有指向任何有效的内存空间。比如用fscanf("%d", &bingoPattern[i][j])直接写入指针本身的地址,或者后续用strcmp、strcpy操作这些未初始化的指针,都会导致非法内存访问,触发段错误。
2. 变量类型不匹配
char singleNumber;应该改为char *singleNumber;:strtok返回的是字符串指针,赋值给char类型会截断地址,导致后续循环中使用非法地址。currentArrayElem = &playerBoard[row][col];中,&playerBoard[row][col]是char**类型,而currentArrayElem是char*类型,类型不匹配,直接赋值会导致strcmp访问错误的内存区域。
3. 字符串处理逻辑错误
inputNumString[strlen(inputNumString + 1)] = 32; 这行逻辑完全错误:strlen(inputNumString +1)是从第二个字符开始计算的字符串长度,修改这个位置的字符可能越界,而且你实际想做的应该是去除fgets读取的换行符,而不是随意修改字符。
4. strcpy的非法使用
strcpy(&playerPattern[row][col], "1"); 中,&playerPattern[row][col]是char**类型,不符合strcpy第一个参数需要char*的要求,同时playerPattern的指针未分配内存,写入操作会直接触发段错误。
修复方案(改用int类型存储数字,更简单高效)
因为宾果游戏中的数字都是整数,完全没必要用字符串存储,改用int数组可以避免所有指针和字符串的问题,代码更简洁可靠:
#include <stdio.h> #include <string.h> #include <stdlib.h> // 用于atoi函数 int main() { // 改用int数组存储,避免指针和字符串的复杂操作 int bingoPattern[5][5]; int playerBoard[5][5]; int playerPattern[5][5]; // 用int标记:1表示已呼叫,0表示未呼叫 char inputNumString[225]; // 读取宾果图案 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { fscanf(stdin, "%d", &bingoPattern[i][j]); } } // 读取呼叫的数字字符串,处理换行符 // 先跳过可能的空行 while (fgets(inputNumString, 225, stdin) != NULL && inputNumString[0] == '\n'); // 处理读取到的数字字符串 int numbersCalled[75]; int numCalledCount = 0; char *token = strtok(inputNumString, " \n"); while (token != NULL) { numbersCalled[numCalledCount++] = atoi(token); token = strtok(NULL, " \n"); } // 读取玩家卡片 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { fscanf(stdin, "%d", &playerBoard[i][j]); } } // 初始化playerPattern为0 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { playerPattern[i][j] = 0; } } // 标记已呼叫的数字 for (int idx = 0; idx < numCalledCount; idx++) { int currentNum = numbersCalled[idx]; for (int row = 0; row < 5; row++) { for (int col = 0; col < 5; col++) { if (playerBoard[row][col] == currentNum) { playerPattern[row][col] = 1; } } } } // 宾果校验逻辑:检查行、列、对角线是否全为1 int bingo = 0; // 检查所有行 for (int row = 0; row < 5; row++) { int fullRow = 1; for (int col = 0; col < 5; col++) { if (playerPattern[row][col] != 1) { fullRow = 0; break; } } if (fullRow) { bingo = 1; break; } } // 检查列 if (!bingo) { for (int col = 0; col < 5; col++) { int fullCol = 1; for (int row = 0; row < 5; row++) { if (playerPattern[row][col] != 1) { fullCol = 0; break; } } if (fullCol) { bingo = 1; break; } } } // 检查对角线 if (!bingo) { int diag1 = 1, diag2 = 1; for (int i = 0; i < 5; i++) { if (playerPattern[i][i] != 1) diag1 = 0; if (playerPattern[i][4 - i] != 1) diag2 = 0; } if (diag1 || diag2) bingo = 1; } printf(bingo ? "Bingo!\n" : "No Bingo.\n"); return 0; }
关键修复说明
- 把所有存储数字的数组改为
int类型,彻底避免指针和字符串操作的内存问题。 - 修正了读取呼叫数字的逻辑,正确处理换行符,用
atoi把字符串转为整数。 - 标记已呼叫数字时直接用整数比较,替代原来的
strcmp,逻辑更清晰。 - 添加了完整的宾果校验逻辑(行、列、对角线),完成程序的核心功能。
内容的提问来源于stack exchange,提问作者anthonyvn
相关产品推荐
相关产品推荐

