C语言读取文件时文本开头出现异常字符的问题解决
问题:文件字符替换时开头出现异常字符
需求说明
从文件读取两个空格分隔的字母,再读取下一行文本,将文本中所有第一个字母替换为第二个字母,最终覆盖原文件。
输入示例
a x abecedar avion nuca
需将字母a替换为x。
我编写的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *in; in = fopen("in.txt", "r+"); char litera1 = 0, litera2 = 0, s[100], aux[100] = ""; fscanf(in, " %c", &litera1); fgetc(in); fscanf(in, " %c", &litera2); strcpy(aux, ""); printf("%c %c\n", litera1, litera2); while (fscanf(in, "%s", aux) != EOF) { strcat(s, aux); strcat(s, " "); } s[strlen(s) - 1] = NULL; printf("%s\n", s); for (int i = 0; i < 9; i++) printf("%c\n", s[i]); for (int i = 0; i < strlen(s); i++) { if (s[i] == litera1) s[i] = litera2; } /* rewind(in); fprintf(in,"%s", s); i have to overwrite in the same file fflush(in); fclose(in); */ return 0; }
运行输出
a x @§@abecedar avion nuca @ § @ a b e c e d
另外,我写的另一个大小写转换程序也有类似问题:转换功能正常,但文本开头出现⌡字符。逐字符排查后没找到原因,怀疑是换行处理的问题,求解决异常字符的方法。
问题根源与解决办法
1. 未初始化数组导致的垃圾字符
你定义了char s[100];但未初始化,数组默认填充内存中的随机垃圾值。strcat(s, aux)从s的随机初始位置开始拼接,直接导致开头出现异常字符。
解决: 初始化s为空字符串:char s[100] = "";
2. 换行与分隔符处理不当
你用fgetc(in)手动跳过空格,但第一行读完两个字母后,剩余的换行符未被正确处理,可能干扰后续读取。更可靠的方式是用fscanf一次性读取两个字符,它会自动跳过空格、换行等分隔符:
// 替换原有的fscanf和fgetc代码 fscanf(in, "%c %c", &litera1, &litera2);
3. 覆盖原文件的正确姿势
用r+模式打开文件时,直接rewind后写入可能因原文件与新内容长度不同导致残留。稳妥的流程是:
- 读取所有内容到内存
- 关闭文件
- 用
w模式重新打开文件,写入修改后的内容 - 关闭文件
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *in; in = fopen("in.txt", "r"); if (!in) { // 增加文件打开失败判断 perror("Failed to open file"); return 1; } char litera1, litera2; char s[100] = ""; // 初始化空字符串 char aux[100]; // 一次性读取两个替换字符,自动跳过分隔符 fscanf(in, "%c %c", &litera1, &litera2); printf("%c %c\n", litera1, litera2); // 读取第二行文本,用fgets保留原格式 fgets(s, sizeof(s), in); // 去掉fgets可能读取的末尾换行符 s[strcspn(s, "\n")] = '\0'; printf("%s\n", s); for (int i = 0; s[i] != '\0' && i < 9; i++) printf("%c\n", s[i]); // 替换字符 for (int i = 0; s[i] != '\0'; i++) { if (s[i] == litera1) s[i] = litera2; } // 关闭文件后重新打开写入 fclose(in); in = fopen("in.txt", "w"); if (!in) { perror("Failed to open file for writing"); return 1; } // 写入完整内容(替换规则+修改后的文本) fprintf(in, "%c %c\n%s\n", litera1, litera2, s); fclose(in); return 0; }
额外说明
- 用
fgets读取整行比fscanf("%s")更合适,后者会把空格当作分隔符拆分单词,破坏原文本格式。 - 始终检查文件是否成功打开,避免空指针操作。
- 局部数组未初始化会包含随机值,直接使用会导致不可预测的行为,这是C语言中常见的坑。
内容的提问来源于stack exchange,提问作者Catalin Ionita
相关产品推荐
相关产品推荐

