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

C语言中fgets读取文件行后输出末尾出现乱码的原因及解决方法

为什么用fgets读取文件会输出乱码?

嘿,我帮你定位到问题所在了——乱码的根源是translate函数在处理带换行符的行时,会越界访问栈上的随机内存,具体细节如下:

问题本质

当你用fgets读取文件行时,它会把换行符\n和字符串结束符\0一起写入buf数组。但你的translate函数里,允许保留的字符列表里既不包含\n,也没考虑\0的边界问题:

  • 当处理到\n时,代码会进入else分支的while循环,目的是跳过所有非允许字符。但这个循环的条件里没有检查s[i] != '\0',导致当i指向\0时,循环还会继续执行,i不断往栈内存的深处走(超出buf的范围),去访问那些随机的垃圾数据。
  • 这些栈里的随机字节中,万一碰到了属于允许列表的字符(比如字母、数字或者标点),循环就会停下来。之后的代码会把这些栈里的垃圾字符也计入结果的长度,最后设置的\0结束符位置错误,输出时就带上了这些乱码。

而直接处理字符串常量时没问题,是因为那些字符串末尾只有\0,没有\n,translate的循环会在碰到\0时直接终止,不会触发越界的循环。

修复方法

我们需要做两处调整(第二处可选,看你需求):

1. 给translate函数加上边界检查

在translate的while循环条件里,加上s[i] != '\0',确保不会越界访问内存:

char *translate(char *s) {
    int count = 0;
    for (int i = 0; s[i] != '\0'; i++) {
        if ( (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= '0' && s[i] <= '9') || s[i] == '.' || s[i] == ',' || s[i] == '!' || s[i] == '?' || s[i] == ' ') {
            s[count++] = s[i];
        } else {
            // 新增s[i] != '\0',防止越界读取栈垃圾
            while (s[i] != '\0' && (s[i] < 'a' || s[i] > 'z') && (s[i] < 'A' || s[i] > 'Z') && (s[i] < '0' || s[i] > '9') && s[i] != '.' && s[i] != ',' && s[i] != '!' && s[i] != '?' && s[i] != ' ') {
                i++;
            }
            i--;
        }
    }
    s[count] = '\0';
    return s;
}

2. 可选:提前去掉fgets的换行符

因为你的unspace函数会把\n转换成空格,如果你不想输出结果末尾多一个空格,可以在处理前先把换行符删掉,顺便加一些健壮性判断:

int main() {
    FILE *fp = fopen("data.txt", "r");
    if (!fp) { // 增加文件打开失败的判断
        perror("Failed to open file");
        return EXIT_FAILURE;
    }
    char buf[BUFLEN] = {0};
    while (fgets(buf, BUFLEN, fp)) {
        // 去掉换行符(如果存在)
        size_t len = strlen(buf);
        if (len > 0 && buf[len-1] == '\n') {
            buf[len-1] = '\0';
        }
        puts(unspace(toUpper(translate(buf))));
    }
    fclose(fp); // 记得关闭文件
}

修复后的效果

调整完再运行程序,输出就完全正常了:

$ ./a.out
AHOJ, JAK SE MAS?
MAM SE DOBRE! DNES JE 33 STUPNU.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:47:33