【问题标题】:Search and replace string in txt file in c++在C++中搜索和替换txt文件中的字符串
【发布时间】:2014-02-06 11:01:49
【问题描述】:

我想在文件中查找一个字符串并将其替换为用户输入。
这是我的粗略代码。

#include <iostream>
#include <fstream.h>
#include <string.h>

int main(){
    istream readFile("test.txt");

    string readout,
         search,
         replace;

    while(getline(readFile,readout)){
        if(readout == search){
            // How do I replace `readout` with `replace`?
        }
    }
}

更新
这是解决我问题的代码

test.txt:

id_1
arfan
haider

id_2
saleem
haider

id_3
someone
otherone

C++ 代码:

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

using namesapce std;

int main(){
    istream readFile("test.txt");
    string readout,
           search,
           firstname,
           lastname;

    cout << "Enter the id which you want to modify";
    cin >> search;

    while(getline(readFile,readout)){
        if(readout == search){
            /*
                id remains the same
                But the First name and Last name are replaced with
                the user `firstname` and `lastname` input
            */
            cout << "Enter new First name";
            cin >> firstname;

            cout << "Enter Last name";
            cin >> lastname;  
        }
    }
}  

假设:
用户搜索 id id_2。在该用户之后输入名字和姓氏ShafiqAhmed。 运行此代码后,test.txt 文件必须像这样修改记录:

…

id_2
Shafiq
Ahmad

…

只有id_2 记录发生变化,其余文件将保持不变。

【问题讨论】:

  • 建议:写入一个新文件并将其移到原始文件上 + std::string 具有查找和替换成员函数。
  • 我刚刚看到你想替换完整的行,所以只有我的第一个建议是有效的。二是更换部分线路。文件中的内联替换仅适用于相同大小的替换。

标签: c++ file search replace


【解决方案1】:
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char **argv) {

if (argc < 4) {
    cout << "Invalid input" << endl;
    cout << "\tchange <old_word> <new_word> <file_list>";
}

fstream fs;
string tmp;
string oldw = argv[1];
string neww = argv[2];

for (int i = 3; i < argc; i++) {
    fs.open(argv[i] , ios::in);

    while (!fs.eof()) {
        getline(fs, tmp);

        while (tmp.find(oldw) != string::npos)
            tmp.replace(tmp.find(oldw), sizeof(oldw), neww);    

        cout << tmp << endl;
    }

}

fs.close();
return 0;    
}

用法:

./a.out old_word    new_word    filename

【讨论】:

    【解决方案2】:

    我会按照@stefaanv 所说的去做:

    #include <iostream>
    #include <fstream.h>
    #include <string.h>
    
    int main(){
      ostream outFile("replaced.txt");
      istream readFile("test.txt");
      string readout;
      string search;
      string replace;
      while(getline(readFile,readout)){
        if(readout == search){
          outFile << replace;
        }
        else {
          outFile << readout;
        }
      }
    }
    

    编辑:如果每行的信息独立于其他行的信息,则上述解决方案有效。在您的更新中,名称行上的信息取决于 id 行上的信息。因此,要扩展上述技术,您需要在 while 循环中维护状态,以指示您何时到达一个数据块的末尾。

    #include <iostream>
    #include <fstream.h>
    #include <string.h>
    
    int main(){
      ostream outFile("replaced.txt");
      istream readFile("test.txt");
      string readout;
      string search, Fname, Lname;
      unsigned int skipLines = 0;
    
      cout << "Enter id which you want Modify";
      cin >> search;
      cout << "Enter new First name";
      cin >> Fname;
      cout << "Enter Last name";
      cin >> Lname;  
    
      while(getline(readFile,readout)) {
        if (skipLines != 0) {
          skipLines--;
          continue;
        }
        else if (readout == search) {
          outFile << search << endl;
          outFile << Fname << endl;
          outFile << Lname << endl;
          skipLines = 2;
        }
        else {
          outFile << readout;
        }
      }
    }
    

    稍微更优雅的方法是将每个数据块存储在一个结构中,这允许您使用重载运算符 >。这使得文件读写的代码更加清晰——它实际上与“每行数据独立”情况下的代码相同。

    #include <iostream>
    #include <fstream.h>
    #include <string.h>
    
    struct NameRecord {
      string id;
      string fname;
      string lname;
    
      friend std::ostream& operator<<(std::ostream &os, const NameRecord &src);
      friend std::istream& operator>>(std::istream &is, NameRecord &dst);
    };
    
    std::ostream& operator <<(std::ostream &os, const NameRecord &src) {
      os << src.id << endl << src.fname << endl << src.lname << endl;
    
      return os;
    }
    
    std::istream& operator >>(std::istream &is, NameRecord &dst) {
      // may need to have more code to ignore whitespace, I'm not sure
      if (is.good ()) {
        is >> dst.id;
      }
      if (is.good ()) {
        is >> dst.fname;
      }
      if (is.good ()) {
        is >> dst.lname;
      }
    
      return is;
    }
    
    int main(){
      ostream outFile("replaced.txt");
      istream readFile("test.txt");
    
      NameRecord inRecord, replaceRecord;
      cout << "Enter id which you want Modify";
      cin >> replaceRecord.id;
      cout << "Enter new First name";
      cin >> replaceRecord.Fname;
      cout << "Enter Last name";
      cin >> replaceRecord.Lname;  
    
      while (readFile.good()) {
        // the >> operator reads the whole record (id, fname, lname)
        readFile >> inRecord;
    
        // the << operator writes the whole record
        if (inRecord.id == replaceRecord.id) {
          outFile << replaceRecord;
        }
        else {
          outFile << inRecord;
        }
      }
    } 
    

    【讨论】:

      【解决方案3】:

      这应该可行。我使用string::find 在每一行中查找所需的子字符串,并使用string::replace 在找到某些内容时替换它。

      编辑:我忘记了单词每行出现多次的情况。添加了while 来解决此问题。

      #include <fstream>
      #include <iostream>
      using namespace std;
      
      int main(int argc, char **argv)
      {
          ifstream in(argv[1]);
          ofstream out(argv[2]);
          string wordToReplace(argv[3]);
          string wordToReplaceWith(argv[4]);
      
          if (!in)
          {
              cerr << "Could not open " << argv[1] << "\n";
              return 1;
          }
      
          if (!out)
          {
              cerr << "Could not open " << argv[2] << "\n";
              return 1;
          }
      
          string line;
          size_t len = wordToReplace.length();
          while (getline(in, line))
          {
              while (true)
              {
                  size_t pos = line.find(wordToReplace);
                  if (pos != string::npos)
                      line.replace(pos, len, wordToReplaceWith);
                  else 
                      break;
              }
      
              out << line << '\n';
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-12
        • 2019-05-19
        • 2021-10-20
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        • 2012-05-05
        相关资源
        最近更新 更多