C语言for循环中调用scanf实现注册信息输入功能异常问题求解
Code::Blocks gcc环境下for循环scanf异常问题解决方案
核心错误点
- 结构体字符串成员未分配可写内存:
password结构体中的name/userID/pwd/emailID都是字符指针,初始化时指向只读的字符串常量区,scanf写入操作会触发内存访问异常,直接导致程序崩溃。 fflush(stdin)属于未定义行为:C标准仅规定fflush对输出流有效,gcc环境下调用fflush(stdin)无法保证清空输入缓冲区,会导致后续scanf读取到残留的换行符或垃圾值,出现光标跳转异常。scanf格式符错误:读取姓名用的%30[^\n]s多写了末尾的s,%[^\n]本身就是完整的格式符,加s会要求匹配输入里的字面量s,导致读取逻辑异常。- 基础语法/逻辑问题:
y1=7、x2=167末尾漏写分号,increment变量未定义,REGISTER数组下标从0开始,原循环i<=row_1会触发数组越界访问。
修复方案
- 修改结构体定义,给字符串成员分配固定大小的数组空间,避免野指针写入问题:
typedef struct{ int id; char name[31]; // 对应%30[^\n],预留1位存储结束符'\0' char userID[13]; // 对应%12s char pwd[16]; // 对应%15s char emailID[31]; // 对应%30s } password;
- 替换
fflush(stdin)为标准的输入缓冲区清空逻辑,封装通用清空函数:
void clear_stdin() { int c; while ((c = getchar()) != '\n' && c != EOF); }
- 修正
scanf格式符:将姓名读取的scanf("%30[^\n]s",pw.name);改为scanf("%30[^\n]", pw.name);,每次读取完成后调用clear_stdin()清空缓冲区残留的换行符,避免影响后续输入。 - 修复其他语法/逻辑问题:
- 补全
y1=7;、x2=167;的分号 - 定义
increment变量(根据实际界面布局设置合适值,示例设为2) - 调整循环边界为
for (int i=1; i<row_1; i++),避免数组越界
- 补全
修正后的核心代码示例
#include <stdio.h> #include <string.h> #include <conio.h> // 含gotoxy函数的头文件,根据实际环境调整 #define REGISTER (char *[5]) {"REGISTER NEW USER ACCOUNT", "Name:","User ID:", "Password:","Email ID:"} typedef struct{ int id; char name[31]; char userID[13]; char pwd[16]; char emailID[31]; } password; void clear_stdin() { int c; while ((c = getchar()) != '\n' && c != EOF); } int main() { password pw={0,"","","",""}; int step=1; int padding=15; int y1=7; int x1=0; int x2=167; int increment = 2; // 按界面布局需求调整步长 int j; int row_1 = sizeof(REGISTER) / sizeof(REGISTER[0]); for (int i=1; i<row_1; i++){ j=(((x2-x1)-strlen(REGISTER[i]))/2)+strlen(REGISTER[i]); step += increment; gotoxy(((x1-padding)+j), (y1+step)); if (i==1){ scanf("%30[^\n]",pw.name); clear_stdin(); } else if (i==2){ scanf("%12s",pw.userID); clear_stdin(); } else if (i==3){ scanf("%15s",pw.pwd); clear_stdin(); } else { scanf("%30s",pw.emailID); clear_stdin(); } } // 后续业务逻辑 return 0; }
内容的提问来源于stack exchange,提问作者Anil
相关产品推荐
相关产品推荐

