【问题标题】:replace line in a file C++替换文件 C++ 中的行
【发布时间】:2010-12-21 12:12:30
【问题描述】:

我正在尝试找到一种方法,用新行替换文件中包含字符串的行。

如果文件中不存在该字符串,则将其附加到文件中。

谁能给个示例代码?

编辑:如果我需要替换的行在文件末尾,是否还有?

【问题讨论】:

标签: c++ file


【解决方案1】:

虽然我认识到这不是最聪明的做法,但以下代码逐行读取 demo.txt 并搜索单词 cactus 来替换它oranges,同时将输出写入名为 result.txt 的辅助文件。

别担心,我为你保存了一些工作。阅读评论:

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;


int main()
{
  string search_string = "cactus";
  string replace_string = "oranges";
  string inbuf;
  fstream input_file("demo.txt", ios::in);
  ofstream output_file("result.txt");

  while (!input_file.eof())
  {
      getline(input_file, inbuf);

      int spot = inbuf.find(search_string);
      if(spot >= 0)
      {
         string tmpstring = inbuf.substr(0,spot);
         tmpstring += replace_string;
         tmpstring += inbuf.substr(spot+search_string.length(), inbuf.length());
         inbuf = tmpstring;
      }

      output_file << inbuf << endl;
  }

  //TODO: delete demo.txt and rename result.txt to demo.txt
  // to achieve the REPLACE effect.
}

【讨论】:

  • 谢谢。如果我只需要用 2 个新行完全替换文件的最后 2 行怎么办?
  • @Prasanth 对我来说听起来像是一个新问题。您可以阅读整个文件一次以了解其中有多少行文本。然后将此值减去 2,您就会知道应该替换哪些行。再次阅读文件,停在有趣的行号上,然后施展你的魔法。
  • 这听起来不错,但是在 VS 2010 中我得到了完全错误的行为(没有编译器错误)。我的历史包括 C 并且还不是 C++ 向导,所以我发现 find 方法没有以标准方式使用。请参阅下面的我的 sn-p。想知道 C++ 向导在这里说什么。我在 SE 上没有发现比这更好的 sn-p,这非常令人惊讶。
  • @TedLyngmo 谢谢!如果您认为值得,请随意调整这个 10 年前的答案的代码。
【解决方案2】:

要替换文件中的最后两行:

  • 使用fopen()打开文件
  • fgetpos()获取当前文件位置
  • 始终存储最后两个文件位置并逐行读取
  • 当您到达文件末尾时:较低的位置是您必须使用fseek() 定位到的位置
  • 现在您可以fprintf() 将新行添加到文件中,然后使用fclose() 将其关闭。

【讨论】:

    【解决方案3】:

    如前所述,KarlPhilip 的代码是一个很好的起点(谢谢),但根据 ">= 0" 不能正常工作。与“0”相比,它以 MS CString 类型和 C# 等而闻名,但它似乎不适用于 STL。例如。在 VS 2010(仅发行版)中,C++ 代码在此比较中表现错误而不会引发错误!

    这是对 C++ 标准的更正:如果某些向导有改进,请发布。我认为,这是一个非常有用且重要的问题/sn-p。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    
    using namespace std;    
    
    int main() 
    {   
       string search_string = "cactus";   
       string replace_string = "oranges";   
       string inbuf;
       // Todo: Check, if input_file exists before. 
       // Todo: Try/catch or check, if you have write access to the output file.
       fstream input_file("demo.txt", ios::in);   
       ofstream output_file("result.txt");
    
       while (!input_file.eof())   
       {
          getline(input_file, inbuf);
          size_t foundpos = inbuf.find(search_string);
          if(foundpos != std::string::npos)
          {
             string tmpstring = inbuf.substr(0,spot);
             tmpstring += replace_string;
             tmpstring += inbuf.substr(spot+search_string.length(), inbuf.length());
             inbuf = tmpstring;
          }
    
          output_file << inbuf << endl;   
       }
    
       //TODO: delete demo.txt and rename result.txt to demo.txt      
       // to achieve the REPLACE effect. 
    }
    

    我在另一个 SO 问题的“if”中使用了以下替换部分 (上面的代码只替换了第一次出现):

    if(foundpos != std::string::npos)
       replaceAll(inbuf, search_string, replace_string); 
    
    //http://stackoverflow.com/questions/3418231/c-replace-part-of-a-string-with-another-string
    //
    void replaceAll(std::string& str, const std::string& from, const std::string& to) 
    {
        size_t start_pos = 0;
        while((start_pos = str.find(from, start_pos)) != std::string::npos) 
        {
            size_t end_pos = start_pos + from.length();
            str.replace(start_pos, end_pos, to);
            start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
        }
    }
    

    【讨论】:

      【解决方案4】:

      如果您想更改(或删除)文件中间一行的长度,您将不得不重新编写所有后续行。

      没有办法简单地将字符删除或插入到现有文件中。

      【讨论】:

      • 我需要在文件末尾插入或删除内容。这可能吗?
      • @Prasanth。这称为追加和截断。是的,这是可能的。
      • 抱歉,这在 Windows 上可能是不可能的,但在 BS2000 上使用 ISAM 文件是可能的! (顺序索引文件):-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      相关资源
      最近更新 更多