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

从安全与无Bug角度看C语言字符串输入:我的代码是否最优?求改进

代码安全与优化分析

原代码的安全优势

你的代码选用fgets()读取输入是正确的,它能通过指定缓冲区大小避免缓冲区溢出,这是字符串输入里最关键的安全点,比gets()这类不安全函数靠谱得多。

现存问题与改进建议

  1. 重复调用strlen()浪费效率
    每次strlen()都要遍历整个字符串找终止符'\0',你在代码里多次调用,完全可以把长度先存到变量里复用:

    size_t len = strlen(msg);
    

    用size_t类型比int更合适,因为字符串长度不可能是负数。

  2. 剩余输入处理逻辑有漏洞
    当输入长度超过MSG_LEN-1时,你的循环只判断strlen(msg) == MSG_LEN-1,如果最后一次读取的剩余内容不足MSG_LEN-1但没到换行/EOF,或者遇到EOF时,会出现逻辑异常。正确做法是读取到换行符或者EOF才停止清理缓冲区:

    // 清理缓冲区剩余内容
    if (len > 0 && msg[len-1] != '\n') {
        int c;
        while ((c = getchar()) != '\n' && c != EOF);
    }
    
  3. 未处理fgets()返回NULL的情况
    当输入遇到EOF(比如Ctrl+D),fgets()会返回NULL,此时msg内容未定义,继续调用strlen()会触发未定义行为,必须在调用后检查返回值:

    if (fgets(msg, MSG_LEN, stdin) == NULL) {
        // 处理EOF,比如退出循环
        break;
    }
    
  4. 输出逻辑冗余
    你用for循环逐个字符输出,完全可以直接用fputs(msg, stdout)替代,简洁又高效。另外,输入被截断时手动加'\n'的逻辑可以整合到剩余输入处理的判断里。

改进后的代码

#include <stdio.h>
#include <string.h>

#define MSG_LEN 25

int main(void) {
    char msg[MSG_LEN];
    
    while (1) {
        putchar(':');
        // 检查fgets是否成功读取
        if (fgets(msg, MSG_LEN, stdin) == NULL) {
            putchar('\n');
            break;
        }
        
        size_t len = strlen(msg);
        fputs(msg, stdout);
        
        // 判断输入是否被截断(没读到换行)
        if (len > 0 && msg[len - 1] != '\n') {
            putchar('\n'); // 补换行
            // 清理缓冲区剩余内容
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
            // 如果遇到EOF,退出循环
            if (c == EOF) {
                break;
            }
        }
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者CiberNux

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:56:09