C语言读取stdin创建结构体时遇0/2中断的问题求助
C语言输入读取崩溃问题的分析与解决
问题描述
尝试从标准输入读取以下格式的内容,用来创建结构体并填充状态,但程序读取到0或2时停止运行:
3 0 -1 1 -1 2 2 0 -1 -1 -1 2 -1 -1 0 -1 4 1 0 1 2 2 2 0 1
程序可正常编译,但运行时出现类似如下错误(注:该错误实际是PowerShell的解析错误,并非C程序本身的错误):
2 0 -1 -1 -1
ParserError:
Line |
1 | 2 0 -1 -1 -1
| ~
| Unexpected token '0' in expression or statement.
代码问题排查与修复
1. scanf参数未传地址,导致未定义行为
scanf读取变量时必须传入变量的地址(指针),原代码中读取结构体成员时直接传递了成员变量的值,会导致程序内存访问错误,这是崩溃的核心原因。
- 原错误代码:
scanf("%d %d %d %d %d", rooms[i].state, rooms[i].northState, rooms[i].southState, rooms[i].eastState, rooms[i].westState); - 修正后:
scanf("%d %d %d %d %d", &rooms[i].state, &rooms[i].northState, &rooms[i].southState, &rooms[i].eastState, &rooms[i].westState); - 读取
Creature结构体时同理,需给成员变量加&:scanf("%d %d", &creatures[i].type, &creatures[i].location);
2. getCurrentRoom函数参数与调用不匹配
- 调用
getCurrentRoom时,creatures是数组名,本身就是指向数组首元素的指针,不需要加&,原代码&creatures会传递数组的地址(双重指针),与函数参数类型不匹配。 - 函数循环条件错误:遍历生物列表应该用生物的数量,而非房间数量,参数名需修正避免混淆。
- 函数缺少默认返回值:如果找不到
type为0的生物,函数无返回值会导致未定义行为,需添加默认返回。
修正后的getCurrentRoom函数及调用:
// 函数定义修正参数名 int getCurrentRoom(int nrOfCreatures, struct Creature *creature) { for(int i = 0; i < nrOfCreatures; i++) { if (creature[i].type == 0){ return creature[i].location; } } return -1; // 默认返回,避免未定义行为 } // 调用修正 int playerLocation = getCurrentRoom(nrOfCreatures, creatures);
3. strupr函数的可移植性问题
strupr不是C标准库函数,部分编译器(如GCC)不支持,建议手动实现字符串转大写的逻辑:
void toUpper(char *str) { while (*str) { *str = toupper((unsigned char)*str); str++; } } // 替换原strupr调用 toUpper(input); if(strcmp(input, "LOOK") == 0) { // ... }
注意需要包含ctype.h头文件。
4. 错误提示的正确理解
你看到的ParserError是PowerShell的错误,原因是直接在PowerShell命令行输入了程序的输入内容,而非将输入传递给编译后的可执行程序。正确的运行方式:
- 编译程序生成可执行文件(如
game.exe) - 方式一:运行程序后手动输入所有内容
- 方式二:将输入内容保存到
input.txt,执行./game.exe < input.txt
修正后的完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> void toUpper(char *str); int getNrOfX(); int getCurrentRoom(int nrOfCreatures, struct Creature *creature); struct Room { int state; int northState; int southState; int eastState; int westState; }; struct Creature { int type; int location; }; int main() { // 创建初始房间和生物 int nrOfRooms = getNrOfX(); struct Room rooms[nrOfRooms]; for(int i = 0; i < nrOfRooms; i++){ scanf("%d %d %d %d %d", &rooms[i].state, &rooms[i].northState, &rooms[i].southState, &rooms[i].eastState, &rooms[i].westState); } int nrOfCreatures = getNrOfX(); struct Creature creatures[nrOfCreatures]; for(int i = 0; i < nrOfCreatures; i++){ scanf("%d %d", &creatures[i].type, &creatures[i].location); } // 游戏循环 while (1) { char input[30]; scanf("%s", input); toUpper(input); if(strcmp(input, "LOOK") == 0) { int playerLocation = getCurrentRoom(nrOfCreatures, creatures); if (playerLocation != -1) { printf("Room State %d\n", rooms[playerLocation].state); printf("%d\n", rooms[playerLocation].northState); } else { printf("Player not found\n"); } break; } } return 0; } int getNrOfX() { int nrOfX; scanf("%d", &nrOfX); return nrOfX; } int getCurrentRoom(int nrOfCreatures, struct Creature *creature) { for(int i = 0; i < nrOfCreatures; i++) { if (creature[i].type == 0){ return creature[i].location; } } return -1; } void toUpper(char *str) { while (*str) { *str = toupper((unsigned char)*str); str++; } }
内容的提问来源于stack exchange,提问作者Xander O'Hara
相关产品推荐
相关产品推荐

