There are of course always many possible solutions, I will explain and show you one of them.
For the sake of some security to prevent data loss, we will NOT immediately work (modifiy) on the original source file. Instead, we will first open a temporary file, then read the source file, replace the searched word and then output the new data to the temporary file.
After all search and replace operations are finished, the original file will be deleted and the temporary file will be renamed to the original one.
For the search and replace functionality, I used in this example the std::regex_replace
function. This is very flexible, because you can use regurlar expressions as search and replace strings. But this may be also a little bit difficult for beginners. Anyway, it will of course also replace normal strings as given by the user.
Please note: The proposed implementation does search and replace words, as requested by the OP. Deleting whole lines is not possible at the moment (an empty line will remain).
So, now the program flow.
- Get a filename from the OS for the temporary file
- Open a new scope, so that all open fstreams will be closed by the destructor automatically
- Open the source file and check, if it could be opened. If not, issue error message
- Open the temporary file and check, if it could be opened. If not, issue error message
- Read the complete source file line by line
- Search and replace string in this one line
- Store result in temporary file
- Delete the original source file
- Rename the temporay file to the original
Additionally I added some error handling and status info.
Please see
#include <string>
#include <regex>
#include <vector>
#include <iostream>
#include <fstream>
#include <cstdio>
bool searchAndReplaceWordInFile(const std::string& filename, const std::string& searchString, const std::string& replaceString) {
// Get a temporary filename
#pragma warning(suppress : 4996)
const std::string tempFileName = std::tmpnam(nullptr);
// Result of file operations
bool result{ true };
// Open a new scope for the fstreams. The destructor will be called and the files will be closed
// after the fstreams will fall out of scope
{
// Open the source file name
std::ifstream sourceFile(filename);
// Check if it could be opened
if (sourceFile) {
// Open the temp file
std::ofstream tempFile(tempFileName);
// And check, if it could be opened
if (tempFile) {
// We will read the text file line by line
std::string textLine{};
// Read all lines of text file
while (std::getline(sourceFile, textLine)) {
// Serach, Replace, using regex and output in temp file
tempFile << std::regex_replace(textLine, std::regex(searchString), replaceString) << "\n";
}
}
else {
std::cerr << "*** Error Could not open temp file: " << tempFileName << "\n";
result = false;
}
}
else {
std::cerr << "*** Error Could not open source file: " << filename << "\n";
result = false;
}
}
if (result) {
// Remove original file and rename temp file to original file
std::remove(filename.c_str());
if (std::rename(tempFileName.c_str(), filename.c_str())) result = false;
}
return result;
}
int main() {
if (searchAndReplaceWordInFile("r:\\something.bat", "/Uninstall", ""))
std::cout << "Success, Done. \n";
return 0;
}