C语言My_Mastermind小游戏超4位数字输入校验失效问题求助
问题描述
C语言实现My_Mastermind猜数字小游戏时,输入校验逻辑存在不符合设计规则的异常:
- 游戏要求玩家输入的猜测密码必须为严格4位数字
- 输入不足4位数字(如123)时,程序可正常触发错误提示,表现符合预期
- 输入长度超过4位的数字串(如5位的01234、6位及更长内容)时,程序未抛出输入错误,反而直接截取输入前4位字符执行游戏逻辑,违反设计要求
根因定位
逐行排查逻辑后,定位到4个直接/关联缺陷:
- 校验顺序倒置:用户输入读取完成后,程序先调用
size_of_function强制截取前4位字符,再将截断后的内容传入校验函数,超长输入在进入校验环节前已经被裁为4位,长度校验完全失效 - 长度校验代码被注释:
wrong_input函数中用于判断输入长度是否为4位的代码块被整段注释,没有执行 - 输入读取逻辑存在漏洞:
input_function使用read读取标准输入时,没有将用户输入末尾的换行符替换为字符串结束符\0,会导致my_strlen计算长度时出现随机偏差 - 附加逻辑bug:
mis_placed_pieces(错位数字统计)函数循环逻辑错误,i从0开始先自增再判断,会跳过第0位元素、越界访问数组第4位内存,统计结果完全错误
修复方案
针对上述问题逐一修复:
- 调整校验顺序:拿到原始用户输入后,先完成长度、字符合法性校验,校验通过后再提取有效4位内容传入后续游戏逻辑
- 补全长度校验:在数字字符校验前增加长度判断,有效长度不等于4位直接判定为非法输入
- 修复输入读取逻辑:读取输入后遍历字符串,将末尾换行符替换为
\0,确保字符串终止正确,长度计算准确 - 修正错位数字统计逻辑,避免数组越界,同步修复已知内存泄漏问题
修复后完整代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> typedef struct s_mastermind { int my_attempt; char* my_code; } my_mastermind; my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv); int checking_for_correctness_num(char* _string, int len); int wrong_input(int progress,char* num_code); my_mastermind* my_function(); int check_function(char* string); char* input_function(); int mis_placed_pieces(char* bit, char* num_code); int well_placed_pieces(char* bit, char* num_code); int code_checker(char* bit, char* num_code); char* get_valid_code(char* strye); int my_strlen(char* num1) { return (*num1) ? my_strlen(++num1) + 1 : 0; } char* my_strcpy(char* num1, char* num2) { for(int i = 0; num2[i] != 0; i++) { num1[i] = num2[i]; } num1[my_strlen(num2)] = '\0'; return num1; } my_mastermind* my_function() { my_mastermind* num = malloc(sizeof(my_mastermind)); num->my_code = malloc(5); num->my_code[4] = '\0'; my_strcpy(num->my_code, "0000"); num->my_attempt = 10; return num; } my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv) { for(int i = 0; i < argc; i++) { if (my_strlen(argv[i]) == 2 && argv[i][0] == '-') { if(argv[i][1] == 'c') { if(i+1 >= argc) break; char* num_code = argv[i + 1]; if(wrong_input(argc,num_code) != 0) { break; } my_strcpy(mastermind->my_code, num_code); }else if(argv[i][1] == 't') { if(i+1 >= argc) break; if(checking_for_correctness_num(argv[i + 1], my_strlen(argv[i+1])) == 0) { mastermind->my_attempt = check_function(argv[i + 1]); } } else { printf("WRONG FLAG RESTART THE GAME!!!\n"); } } } return mastermind; } int wrong_input(int progress,char* num_code) { int len = my_strlen(num_code); if(len != 4) { printf("Wrong input! Please enter exactly 4 digits.\n> "); fflush(stdout); return 1; } if(checking_for_correctness_num(num_code, len) == 1) { printf("Wrong input! Please enter valid digits.\n> "); fflush(stdout); return 1; } return 0; } int checking_for_correctness_num(char* _string, int len) { for(int i = 0; i < len; i++) { if(!(_string[i] >= '0' && _string[i] <= '9')) { return 1; } } return 0; } int check_function(char* string) { int check_num = 0; for(int i = 0; string[i] != '\0'; i++) { check_num = check_num * 10 + (string[i] - '0'); } return check_num; } char* input_function() { char* getting = malloc(101); int read_len = read(0, getting, 100); for(int i = 0; i < read_len; i++) { if(getting[i] == '\n') { getting[i] = '\0'; break; } } getting[read_len] = '\0'; fflush(stdout); return getting; } int game_progress(int progress, char* bit) { printf("Round: %d\n> ", progress); fflush(stdout); char* code = input_function(); int results = 1; if(wrong_input(progress,code) == 0) { char* valid_code = get_valid_code(code); results = code_checker(bit, valid_code); free(valid_code); } free(code); return results; } void game_action(my_mastermind* mastermind) { int current_try = 0; for (;current_try < mastermind->my_attempt;) { int results = game_progress(current_try, mastermind->my_code); current_try += 1; if(results == 0) { printf("Congratz! You did it!\n"); break; } } } int code_checker(char* bit, char* num_code) { int good_w = well_placed_pieces(bit, num_code); int not_good_m = mis_placed_pieces(bit, num_code); if(good_w > 0 || not_good_m > 0){ printf("Well placed pieces: %d\nMisplaced pieces: %d\n---\n", good_w,not_good_m); } if(good_w == 4) { return 0; } else { return 1; } } int well_placed_pieces(char* bit, char* num_code) { int number = 0; for(int i = 0; i < 4; i++) { if (bit[i] == num_code[i]) { number += 1; } } return number; } int mis_placed_pieces(char* bit, char* num_code) { int number = 0; int used_bit[4] = {0}; int used_code[4] = {0}; for(int i = 0; i <4; i++) { if(bit[i] == num_code[i]) { used_bit[i] = 1; used_code[i] = 1; } } for(int i = 0; i <4; i++) { if(used_bit[i]) continue; for(int j = 0; j<4; j++) { if(!used_code[j] && bit[i] == num_code[j]) { number++; used_code[j] = 1; break; } } } return number; } char* get_valid_code(char* strye) { char* new_string = malloc(5); new_string[4] = '\0'; for(int i = 0; i < 4;i++){ new_string[i] = strye[i]; } return new_string; } int main(int argc, char** argv) { printf("Will you find the secret code?\n---\n"); my_mastermind* mastermind = my_function(); settings_function(mastermind, argc, argv); game_action(mastermind); free(mastermind->my_code); free(mastermind); return 0; }
修复验证
修复后测试表现符合设计要求:
- 输入3位数字:触发错误提示,要求输入4位数字
- 输入5位及以上数字:触发错误提示,要求输入4位数字
- 输入含非数字字符:触发错误提示,要求输入合法数字
- 输入严格4位数字:正常进入比对逻辑,正确输出对位、错位统计结果
- 所有动态申请的内存均正确释放,无内存泄漏问题
内容的提问来源于stack exchange,提问作者Alucard11123
相关产品推荐
相关产品推荐

