从安全与无Bug角度看C语言字符串输入:我的代码是否最优?求改进
代码安全与优化分析
原代码的安全优势
你的代码选用fgets()读取输入是正确的,它能通过指定缓冲区大小避免缓冲区溢出,这是字符串输入里最关键的安全点,比gets()这类不安全函数靠谱得多。
现存问题与改进建议
重复调用
strlen()浪费效率
每次strlen()都要遍历整个字符串找终止符'\0',你在代码里多次调用,完全可以把长度先存到变量里复用:size_t len = strlen(msg);用
size_t类型比int更合适,因为字符串长度不可能是负数。剩余输入处理逻辑有漏洞
当输入长度超过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); }未处理
fgets()返回NULL的情况
当输入遇到EOF(比如Ctrl+D),fgets()会返回NULL,此时msg内容未定义,继续调用strlen()会触发未定义行为,必须在调用后检查返回值:if (fgets(msg, MSG_LEN, stdin) == NULL) { // 处理EOF,比如退出循环 break; }输出逻辑冗余
你用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
相关产品推荐
相关产品推荐

