C++ 在C++中搜索和替换txt文件中的字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21180412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:31:32  来源:igfitidea点击:

Search and replace string in txt file in c++

c++filesearchreplace

提问by Axeem

I want to find a string in a file and replace it with user input.
Here is my rough code.

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

#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`?
        }
    }
}

UPDATE
Here is the code that solved my problem

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

test.txt:

测试.txt:

id_1
arfan
haider

id_2
saleem
haider

id_3
someone
otherone

C++ Code:

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

Suppose:
A user searches for id id_2. After that user enter First name and Last name Shafiqand Ahmed. After runing this code the test.txtFile must modify the record like that:

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

…

id_2
Shafiq
Ahmad

…

Only the id_2record changes, the remaining file will stay the same.

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

回答by JorenHeit

This should work. I used string::findto find the desired substring within each line, and string::replaceto replace it if something has been found.

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

Edit:I forgot about the case where the word occurs multiple times per line. Added a whileto fix this.

编辑:我忘记了单词每行多次出现的情况。添加了一个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';
    }
}

回答by Avi Tevet

I would do what @stefaanv said:

我会做@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;
    }
  }
}

Edit: the above solution works if the information on each line is independent of the information on the other lines. In your update, the information on the name lines is dependent on the information on the id lines. So, to extend the above technique, you'll need to maintain state in the while loop that indicates when you've reached the end of one data block.

编辑:如果每行上的信息独立于其他行上的信息,则上述解决方案有效。在您的更新中,名称行上的信息取决于 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;
    }
  }
}

A slightly more elegant approach would be to store each data block in a struct, which allows you to use overloaded operators << & >>. This makes the code for file reading & writing more clear - it's practically the same as the code for the "data on each line is independent" situation.

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

#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;
    }
  }
} 

回答by Sumeet

#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;    
}

Usage:

用法:

./a.out old_word    new_word    filename