You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

扩展说明

如果需要新增校验规则(比如特殊字符限制、不允许连续特殊字符等),只需要两步:

  1. 编写独立的校验函数,入参根据规则需要传入邮箱字符串、已记录的特殊字符位置即可,校验失败打印对应错误、返回0,通过返回1
  2. 在主循环的校验流程中,按需要的顺序插入新的校验函数调用即可,不需要修改原有其他校验逻辑

内容的提问来源于stack exchange,提问作者Ivan Geljić

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:01:05