Search code examples
c++c++11file-manipulation

How to manipulate text file in C++


I have a txt file with the following data (inputFile.txt):

Start
 FX 
 FX
 FX
 FX
End

What I am trying to achieve is to have the FX replaced by TL and BQ so that I have both repeated equally 4 times as the number of FX. See below (expected result - outputFile.txt):

Start
 TL 
 TL 
 TL
 TL 
 BQ
 BQ
 BQ
 BQ
End

However with my current implementation I have the following (current result):

Start
 TL
 BQ
 TL 
 BQ 
 TL
 BQ
 TL
 BQ
End

Below is my current code:

void replaceInFile(string inputFile, string outFile)
{
    string toBeReplaced = "FX";

    string toReplaceWith1 = "TL";
    string toReplaceWith2 = "BQ";

    ifstream inputStream(inputFile);
    ofstream outputStream(outFile);

    if (!inputStream.is_open() || !outputStream.is_open())
    {
        cerr << "Either open input or output file failed!";
    }

    string line;
    string duplicateLine;

    size_t len = toBeReplaced.length();
    while (getline(inputStream, line))
    {
        duplicateLine = line;

        for (size_t pos = line.find(toBeReplaced); pos != string::npos; pos = line.find(toBeReplaced, pos))
        {
            if (pos)
            {
                line.replace(pos, toBeReplaced.length(), toReplaceWith1);
                duplicateLine.replace(pos, toBeReplaced.length(), toReplaceWith2);

                // This line creates the duplicate
                outputStream << duplicateLine << endl;
            }
        }
        outputStream << line << endl;
    }

    inputStream.close();
    outputStream.close();
}

How can I modify the above code to get the expected result/outputFile.txt?


Solution

  • Here is how I edited your code so it works as I think you want:

    string line;
    string duplicateLine;
    std::vector<string> toBeReplacedLines1;
    std::vector<string> toBeReplacedLines2;
    
    size_t len = toBeReplaced.length();
    while (getline(inputStream, line))
    {
        if (line == "Start" || line == "End")
            continue;
        duplicateLine = line;
        for (size_t pos = line.find(toBeReplaced); pos != string::npos; pos = line.find(toBeReplaced, pos))
        {
            if (pos)
            {
                line.replace(pos, toBeReplaced.length(), toReplaceWith1);
                duplicateLine.replace(pos, toBeReplaced.length(), toReplaceWith2);
            }
        }
        toBeReplacedLines1.push_back(line);
        toBeReplacedLines2.push_back(duplicateLine);
    }
    outputStream << "Start\n";
    for (int i = 0; i < toBeReplacedLines1.size(); i++)
    {
        outputStream << toBeReplacedLines1[i] << endl;
    
    }
    for (int i = 0; i < toBeReplacedLines2.size(); i++)
    {
        outputStream << toBeReplacedLines2[i] << endl;
    }
    outputStream << "End";
    inputStream.close();
    outputStream.close();
    

    Of course, I introduced vector usage, so don't forget to include.