Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search and replace string in txt file in c++

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:

id_1
arfan
haider

id_2
saleem
haider

id_3
someone
otherone

C++ Code:

#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 Shafiq and Ahmed. After runing this code the test.txt File must modify the record like that:

…

id_2
Shafiq
Ahmad

…

Only the id_2 record changes, the remaining file will stay the same.

like image 527
Axeem Avatar asked Jan 17 '14 07:01

Axeem


People also ask

How do I find and replace in a text file?

Open the text file in Notepad. Click Edit on the menu bar, then select Replace in the Edit menu. Once in the Search and Replace window, enter the text you want to find and the text you want to use as a replacement. See our using search and replace and advanced options section for further information and help.

How do you find and replace a word in a string in C?

The fastest way would be to allocate a new string that is strlen (s) - strlen (word) + strlen (rpwrd) + 1 . Then use the strstr function to find the word to be replaced and copy up to that point into a new string, append the new word, then copy the rest of the original sentence into a new string.


3 Answers

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

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

#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';
    }
}
like image 200
JorenHeit Avatar answered Sep 27 '22 20:09

JorenHeit


I would do what @stefaanv said:

#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.

#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;
    }
  }
} 
like image 42
Avi Tevet Avatar answered Sep 27 '22 21:09

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

Usage:

./a.out old_word    new_word    filename
like image 31
Sumeet Avatar answered Sep 27 '22 20:09

Sumeet