【问题标题】:Find and Replace in a C File在 C 文件中查找和替换
【发布时间】:2010-08-09 15:04:08
【问题描述】:

问题是在 C 文件中查找和替换字符串

我是 C 文件的新手。我尝试了以下代码,但没有得到任何输出:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        FILE *f1,*f2;
        char *src,*dest,*s1,ch,ch1,ch2,ch3;
        int i;
        f1=fopen("input.txt","rw");
        f2=fopen("dummy.txt","rw");
        src="mor";
        dest="even";
        while(ch!=EOF)
        {
         ch=fgetc(f1);
         if(ch==src[0])                      //Finding 1st char of src
         {
         fgets(s1,strlen(src),f1);
         if(strcmp(src+1,s1)==0)         //Finding occurance of "src" in file
         {
          fseek(f1,strlen(src)-1,SEEK_CUR);
          while(ch1!=EOF)             //Copying remaining data into another file
          {
          ch1=fgetc(f1);
          fputc(ch1,f2);
          }
      fseek(f1,-strlen(src),SEEK_CUR);
      for(i=0;i<strlen(dest);i++)  //replacing "src" with "dest"
      {
          ch2=dest[i];
          fputc(ch2,f1);
      }
      fclose(f1);
      f1=fopen("input.txt","a");
      while(ch3!=EOF)      //Appending previosly copied data into 1st file
      {
          ch3=fgetc(f2);
          fputc(ch3,f1);
      }
     }
   }
 }
     fclose(f1);
     fclose(f2);
}

input.txt 的内容是“早上”。

请指出逻辑中的错误,并为此提供有效的代码。

提前致谢。

【问题讨论】:

  • 最明显的高效代码类似于:sed "s/src/dest/g" input.txt。直接在 C 中执行此操作没有多大意义(至少在我看来)。
  • @Jerry Coffin... 先生,但这个问题是为了测试我们对在 C 中处理文件的理解!!!
  • “这个问题是为了测试我们对在 C 中使用文件的理​​解” - 这是一个家庭作业问题吗?如果是这样,您可能需要添加“作业”标签。
  • @Merlyn....我没有添加,但上次登录时添加了其他人...。看来其他人又删除了它!!!!

标签: c file find


【解决方案1】:

在 C 中读取文件通常有点混乱。我看到的第一个问题是 ch 在主循环中的使用方式。第一次

while (ch != EOF)

被执行,ch 未初始化,如果它恰好持有EOF,主循环将根本不会执行。我通常使用以下结构来读取文件:

FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */

for (;;)
{
    ch = fgetc(fInput);
    if (ch == EOF) break;

    ...
}

此外,您可能需要阅读文件指针概念。例如,在阅读完src 的其余部分后,您将fseek() 转发,并在将数据复制到f2 之前跳过更多字符。本质上,您阅读m,阅读or(使用fgets() - 并进入一个未分配的缓冲区s1,这将在不久的将来对您产生影响),再跳过2个字符(现在是您的指针是 "morning" 的最后 n),将 "ng" 复制到 f2,尝试在此循环中将 EOF 写入 f2(因此上述模式用于读取直到 EOF),返回两个字符(可能会失败一次你到达EOF,这些天我的C文件函数有点生疏了),写“偶数”到f1(如果我在寻找EOF时出错,应该将输入文件设置为“mornieven”,而不是改变如果我是正确的,它)。总而言之,我不认为代码做你想做的事。

我会建议建立你的功能。以下每一项都可以写成一个程序,您应该在进行下一步之前测试并完成它:

  1. 安全读取文件并打印出来
  2. 检测src 的内容,并打印输入的其余部分
  3. 将输入的其余部分保存到第二个文件而不是打印
  4. 在第一个文件中将src 替换为dest,并忽略其余部分(因为您使用'rw' 打开输入文件,这将截断输入的其余部分)。您可能需要执行 fseek() 来清除 EOF 状态。另请查看ftell() 记录可以使用fseek() 跳回的位置
  5. 最后,将src替换为dest后,将保存的所有内容复制到第二个文件中(此处无需关闭f1。但最好以写入方式打开f2,从第一个文件复制后关闭,然后重新打开读取以执行复制回 f1)。

此外,当您需要缓冲区(例如 s1)时,暂时只需使用足够大的数组,但请查看 malloc()free() 函数以针对此类情况执行动态内存分配。

【讨论】:

  • 非常感谢您为分析整个事情所做的努力。我不能感谢你。我在发现“src”bcos 的出现后使用了 fseek,因为我不知道 fgets 会移动文件指针。我应该更好地阅读这些概念。因此,如果该事情得到处理,该程序会执行我打算做的事情吗?我也会试试你给的方法...再次感谢!!!
【解决方案2】:

进行替换的一种简单方法是首先将整个文件读入缓冲区

例如

FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);

现在在写入文件时,检查你的字符串

char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
   if ( !memcmp( ch, src, lenSrc ) )
   {
     fwrite( dest, 1,lenDest, fpOut );
     ch += lenSrc;
   }
   else 
   {
     fputc( *ch, fp );
   }
}

免责声明:尚未编译此

【讨论】:

  • @Andres K,非常感谢先生...我会尝试您给先生的方法,我认为它会比搜索和替换文件更容易!
【解决方案3】:

您在输出中打印了错误的内容。打印,“ch”,而不是文件指针。

而(ch!=EOF) { ch=getc(f1); printf("%c",ch); } 而(ch!=EOF) { ch=getc(f2); printf("%c",ch); }

此外,f2 在您的输出过程中最后关闭。您必须重新打开它(就像使用 f1 一样。)

【讨论】:

  • @Starsky,先生,我明白了。我已经在代码中更改了它。我已经删除了打印部分。请检查替换逻辑中的任何错误先生。 input.txt 文件在运行时没有改变,原始内容被保留....感谢您的帮助先生...
【解决方案4】:

乍一看,我发现您调用 fgets 的代码是错误的。您尚未分配任何内存,并且正在将字符串读入未初始化的指针。读入数组或动态分配的内存。

【讨论】:

  • 正如你所指出的,fgets 似乎没有问题。它编译良好并正确执行..我正在将它读入一个预先声明的字符串.....
  • @Shyam 您的fgets 不正确。 s1 不是字符串,它是一个指向字符数组的指针,并且它是未初始化的。您正在写入未分配的内存。这不是编译错误;这是一个更严重的逻辑错误,会导致未定义的行为。
  • @meager.... s1 未初始化,逻辑上它不正确.. 我知道。但由于我没有收到任何错误,我将保持原样。你可以检查我在程序中使用的逻辑中的任何错误吗?谢谢
  • @Shyam:这是一个逻辑错误。你不知道未初始化的指针在做什么。如果幸运的话,它只会在使用时使程序崩溃,而不是导致难以追踪的问题。至少,将其声明为char s1[500]; 之类的内容,或者您​​喜欢的任何大小。
【解决方案5】:

另一个问题是您将ch 声明为charfgetc() 返回一个 int,这是有充分理由的。能够返回任何可能的字符或EOF 是很好的,所以EOF 不应该是字符,所以理想情况下fgetc() 返回比char 更大的类型。

结果是循环可能永远不会结束,因为ch 在某些标准实现上不可能保持EOF。将它(以及ch1ch3)声明为int

【讨论】:

    猜你喜欢
    • 2011-07-18
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多