同时读写一个文件的方法

3

我一直在尝试同时读写文件,并且我正在尝试将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的内容如下:

嗨\t我的\t名字\t是\t杰克!

当我运行这段代码时,文本文件中的输出只有空格。没有任何字符。我该怎么做才能使替换按预期工作?


尝试阅读一些文档。 - moffeltje
1
这可能不是您的根本问题,但您不能假设可以使用“num”进行算术运算。POSIX规范并没有说您可以这样做,例如,此OS X manpage明确警告:“尽管fpos_t传统上是整数类型,但应用程序不能假定它是; 特别是,它们不能对此类型的对象执行算术运算。” - Norman Gray
你确定可以对 fpos_t num 进行递减操作吗?它不是一个结构体吗?如果是的话,你应该阅读文档 :) - Amina
4个回答

8
你的代码存在三个主要问题:
  1. 使用模式"w+"打开文件会截断文件(删除所有内容)。虽然你可以读写该文件,但原始内容将丢失。使用模式"r+"可读写文件而不更改其内容,并使文件位置初始位于文件开头。

  2. fpos_t类型的值执行算术运算是不安全的。此外,有一种更简单的方法可以相对移动文件位置。

  3. 完成操作后,你没有关闭文件。

以下是我修改后的代码:

#include <stdio.h>

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);
       }
   }
   fclose(filePtr);
   return 0;
}

@AnasAyubi,我很高兴你找到了解决方案。然而,如果确实我发布的代码不能正确地完成你所描述的工作,那么你的C语言实现存在严重问题。 - John Bollinger

2

引用自cplusplus.com

"w+" 写入/更新:创建一个空文件并打开它以进行更新(既可输入又可输出)。如果已存在同名文件,则其内容将被丢弃,该文件将被视为新的空文件。

您应该使用"r+"。

"r+" 读取/更新:打开一个文件以进行更新(既可输入又可输出)。该文件必须存在。


1
\t 是制表符。你的文本中有制表符,还是你真的写了 \t? - utarid
\t 是一个制表符字符。 - Anas Ayubi

1
这里有两个主要问题:
  1. 必须使用"r+"模式,而不是"w+"。

"w+"模式会删除文件中所有内容(如果之前存在),然后写入到该文件,而"r+"模式使您能够使用之前的现有数据。

  1. 在从读取切换到写入或从写入切换到读取数据时,必须使用位置设置函数。

来自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;
}

0
问题在于您正在使用w+ fopen标志,并尝试递减一个复杂类型的fpos_t变量。您应该使用r+,然后递减num.__pos以使其正常工作。

不存在名为 "nun.__pos" 的东西。 - Anas Ayubi
fpos_t的定义在哪里?如果我使用你的版本,每个单词的第一个字符都会被擦除。 - Amina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接