我一直在尝试同时从文件中读取和写入,并且尝试将 text.txt 内容中的所有制表符替换为空格。这是我的代码:
int main()
{
FILE* filePtr = fopen("text.txt", "w+");
char c;
c = fgetc(filePtr);
fpos_t num;
while(c != EOF)
{
if(c == '\t')
{
fgetpos(filePtr, &num);
num--;
fsetpos(filePtr, &num);
fputc(' ', filePtr);
}
c = fgetc(filePtr);
}
}
text.txt的内容是这样的:
嗨,我的名字是杰克!
当我运行此代码时,text.txt 文件中的输出只是空格。那里没有人物。我应该怎么做才能使替换按预期进行?
您的代码存在三个主要问题:
使用模式打开文件
"w+"
截断文件(删除所有内容)。您可以对其进行读取和写入,但原始内容会丢失。模式"r+"
将打开它进行读写,而不更改内容,并且文件位置最初位于文件的开头。
对
fpos_t
类型的值执行算术运算是不安全的。无论如何,这是没有必要的;有一种更简单的方法可以将文件位置移动相对量。
完成后不要关闭文件。
以及至少两个次要问题:
fgetc()
返回 int
,而不是 char
,其值在 unsigned char
范围内,加上 EOF
,保证在该范围之外。如果将结果转换为 char
,那么最多只会有一个真实的字符值,您无法将其与 EOF
区分开来。
为了更优雅的失败行为,您应该检查
fopen()
的返回值以验证其是否成功,如果未成功则进行相应处理。 (下面不演示。)
您的代码的这种变体对我有用:
#include <stdio.h>
int main(void)
{
FILE* filePtr = fopen("text.txt", "r+");
int c;
while((c = fgetc(filePtr)) != EOF)
{
if(c == '\t')
{
fseek(filePtr, -1, SEEK_CUR);
fputc(' ', filePtr);
}
}
fclose(filePtr);
return 0;
}
“w+”写入/更新:创建一个空文件并打开它进行更新(两者 用于输入和输出)。如果同名文件已经存在 内容将被丢弃,文件将被视为新的空文件。
“r+”读取/更新:打开文件进行更新(输入和输出)。 该文件必须存在。
这里的代码有两个主要问题:
“w+”模式会删除之前退出的文件的所有内容,然后写入文件,而“r+”模式则允许您使用之前存在的数据。
来自 Pelles C 帮助文件:
当使用更新模式打开文件时(“+”作为模式参数中的第二个或第三个字符),可以在关联的流上执行输入和输出。但是,如果没有对 fflush 函数或文件定位函数(fseek、fsetpos 或 rewind)的中间调用,输出后面不得直接跟有输入,并且在没有对文件定位的中间调用的情况下,输入后面不得直接跟有输出函数,除非输入操作遇到文件结尾。
这是对我有用的代码:
int main(void)
{
FILE* filePtr = fopen("text.txt", "r+");
char c;
while( (c = fgetc(filePtr)) != EOF )
{
if(c == '\t')
{
fseek(filePtr, -1, SEEK_CUR);
fputc(' ', filePtr);
fseek(filePtr, 0, SEEK_CUR);
}
}
fclose(filePtr)
return 0;
}
问题是您正在使用
w+
fopen 标志并尝试减少复杂类型的 fpos_t
变量。您应该使用 r+
,然后递减 num.__pos
才能使其正常工作