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

使用fgets()函数有特定规则吗?为何读取字符串会出现垃圾值?

问题原因与解决方案

你的问题核心是fgets会把输入时的换行符\n也读进字符串里,而gets和scanf("%s")不会,导致后续处理换行符时输出了奇怪的字符(也就是你说的“垃圾值”)。

为什么fgets会出现这种情况?

fgets的行为和gets/scanf有明确区别:

  • fgets会读取输入中的所有字符,包括换行符\n,直到达到你指定的长度-1(这里是99),或者遇到换行/EOF为止,之后自动在末尾加\0终止符。
  • gets会自动丢弃输入末尾的换行符,不会把它存在字符串里,但gets不检查缓冲区长度,容易造成溢出,已经被C标准废弃了。
  • scanf("%s")只读取到空格或换行符就停止,同样不会把换行符读进字符串,但它无法读取带空格的字符串。

你输入字符串后按回车,这个回车的\n被fgets存在了s里,循环处理到\n时,它的ASCII值是10,远小于65('A'的ASCII),会进入第一个分支计算:10 +26 -k,这个结果对应的字符就是你看到的“垃圾值”。

fgets的使用规则

  • 必须指定读取的最大长度(第二个参数),一般用sizeof(s),避免缓冲区溢出,这是它比gets安全的核心原因。
  • 记得处理可能存在的换行符,否则会影响后续字符串处理。
  • fgets可以读取带空格的字符串,这是它比scanf("%s")灵活的地方。

修复后的代码

在读取字符串后,手动去掉换行符即可:

#include<stdio.h>
#include<string.h>
int main()
{
    int k,i;
    char s[100];
    fgets(s, sizeof(s), stdin);
    
    // 查找换行符并替换为终止符
    char *newline_pos = strchr(s, '\n');
    if (newline_pos != NULL) {
        *newline_pos = '\0';
    }
    
    scanf("%d", &k);

    for(i=0; s[i]!='\0'; i++)
    {
        // 只处理大写字母,避免非字母字符被错误转换
        if (s[i] >= 'A' && s[i] <= 'Z') {
            if( (s[i]-k) < 'A') 
            {
                printf("%c", s[i] +26 -k);
            }
            else printf("%c", s[i]-k);
        } else {
            printf("%c", s[i]);
        }
    }
    return 0;
}

额外加了个判断,只处理大写字母,避免空格、数字等其他字符被错误转换,让程序更健壮。

内容的提问来源于stack exchange,提问作者MD NUR_ 33

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:50:51