web-dev-qa-db-ja.com

C ++でtxtファイルの文字列を検索して置換します

ファイル内の文字列を見つけて、ユーザー入力に置き換えたい。
これが私の大まかなコードです。

#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 [〜#〜]
これが私の問題を解決したコードです

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

仮定:
ユーザーがIDid_2を検索します。その後、ユーザーは姓名ShafiqAhmedを入力します。このコードを実行した後、test.txtファイルは次のようにレコードを変更する必要があります。

…

id_2
Shafiq
Ahmad

…

id_2レコードのみが変更され、残りのファイルは同じままになります。

5
Axeem

これはうまくいくはずです。 string::findを使用して各行内の目的の部分文字列を検索し、string::replaceを使用して何かが見つかった場合はそれを置き換えました。

編集: Wordが1行に複数回出現する場合を忘れてしまいました。これを修正するために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';
    }
}
6
JorenHeit

私は@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行の情報に依存しています。したがって、上記の手法を拡張するには、1つのデータブロックの終わりに到達したことを示す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;
    }
  }
} 
5
Avi Tevet
#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
0
Sumeet