C语言拆分函数实现邮箱校验 输入错误时提示并重新获取输入
C语言邮箱校验程序重构方案
核心要求
- 输入为空或不符合规则时,明确提示错误原因,循环要求用户重新输入
- 单条校验逻辑完全拆分为独立函数,支持后续灵活扩展特殊字符校验等新规则
- 校验流程固定为:获取输入→按顺序执行单条校验→全部通过判定为合法邮箱,任意环节失败直接回到输入步骤
预设校验规则(按执行顺序)
- 输入内容不能为空
- 邮箱字符串必须包含
@字符 - 邮箱字符串在
@之后必须包含.字符 @符号前的本地部分至少有3个字符@符号和.符号之间的域名主体至少有3个字符.符号后的域名后缀至少有2个字符
原有代码问题
- 无循环重输逻辑,单次输入后直接结束程序
- 校验逻辑全部耦合在同一个函数中,无法单独调整/扩展单条规则
- 使用存在缓冲区溢出风险的不安全函数
gets() - 函数返回值定义与实际逻辑不匹配
- 未处理
.出现在@之前、多个@/.等异常场景
重构后完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_EMAIL_LEN 100 // 获取用户输入 void getInput(char *emailBuf) { printf("请输入邮箱地址: "); fgets(emailBuf, MAX_EMAIL_LEN, stdin); // 去除fgets读取到的末尾换行符 size_t len = strlen(emailBuf); if (len > 0 && emailBuf[len-1] == '\n') { emailBuf[len-1] = '\0'; } } // 校验1:输入非空 int validateNotEmpty(const char *email) { if (strlen(email) == 0) { printf("错误:输入不能为空,请重新输入\n"); return 0; } return 1; } // 校验2:存在@符号,同时记录@的位置 int validateHasAt(const char *email, int *atPos) { *atPos = -1; int atCount = 0; for (int i = 0; email[i] != '\0'; i++) { if (email[i] == '@') { *atPos = i; atCount++; } } if (atCount != 1 || *atPos == -1) { printf("错误:邮箱必须包含且仅包含一个@符号\n"); return 0; } return 1; } // 校验3:@后存在.符号,同时记录最后一个有效.的位置 int validateHasDotAfterAt(const char *email, int atPos, int *dotPos) { *dotPos = -1; int len = strlen(email); // 从@后面开始找最后一个.的位置 for (int i = len - 1; i > atPos; i--) { if (email[i] == '.') { *dotPos = i; break; } } if (*dotPos == -1) { printf("错误:@后必须包含.符号\n"); return 0; } return 1; } // 校验4:@前至少3个字符 int validateLocalPartLen(int atPos) { if (atPos < 3) { printf("错误:@符号前至少需要3个字符\n"); return 0; } return 1; } // 校验5:@和.之间至少3个字符 int validateDomainMainLen(int atPos, int dotPos) { int mainLen = dotPos - atPos - 1; if (mainLen < 3) { printf("错误:@和.之间至少需要3个字符\n"); return 0; } return 1; } // 校验6:.后至少2个字符 int validateDomainSuffixLen(const char *email, int dotPos) { int suffixLen = strlen(email) - dotPos - 1; if (suffixLen < 2) { printf("错误:.符号后至少需要2个字符\n"); return 0; } return 1; } int main() { char email[MAX_EMAIL_LEN]; int atPos, dotPos; while (1) { getInput(email); // 按顺序执行所有校验,任意一步失败则跳过后续校验,重新输入 if (!validateNotEmpty(email)) continue; if (!validateHasAt(email, &atPos)) continue; if (!validateHasDotAfterAt(email, atPos, &dotPos)) continue; if (!validateLocalPartLen(atPos)) continue; if (!validateDomainMainLen(atPos, dotPos)) continue; if (!validateDomainSuffixLen(email, dotPos)) continue; // 所有校验通过 printf("校验通过,邮箱格式合法:%s\n", email); break; } return 0; }
扩展说明
如果需要新增校验规则(比如特殊字符限制、不允许连续特殊字符等),只需要两步:
- 编写独立的校验函数,入参根据规则需要传入邮箱字符串、已记录的特殊字符位置即可,校验失败打印对应错误、返回0,通过返回1
- 在主循环的校验流程中,按需要的顺序插入新的校验函数调用即可,不需要修改原有其他校验逻辑
内容的提问来源于stack exchange,提问作者Ivan Geljić
相关产品推荐
相关产品推荐

