I am trying to erase a string from a text file. To do this, I want to read the file into a vector, then I want to search for the position of this string, so I can use vector::erase to remove it. After the string has been erased from the vector, I can write the vector into a new file.
So far, I have made all of that, but finding the position of the string. I've found all sorts of solutions using < algorithm > 's std::find, but those answers were trying to check if this string exists, not its position.
Here is an example of how the text file is set up. With a string, followed by an integer, followed by .txt without spaces. Each string is on a newline.
file123.txt
Bob56.txt'
Foo8854.txt
In this case, the vector would be "file123.txt", "bob56.txt", "Foo8854.txt".
This is the code I have made already:
std::vector<std::string> FileInVector;
std::string str;
int StringPosition;
std::fstream FileNames;
FileNames.open("FileName Permanent Storage.txt");
while (std::getline(FileNames, str)) {
if(str.size() > 0) {
FileInVector.push_back(str); // Reads file, and this puts values into the vector
}
}
//This is where it would find the position of the string: "bob56.txt" as an example
FileInVector.erase(StringPosition); // Removes the string from the vector
remove("FileName Permanent Storage.txt"); // Deletes old file
std::ofstream outFile("FileName Permanent Storage.txt"); // Creates new file
for (const auto &e : FileInVector) outFile << e << "\n"; // Writes vector without string into the new file
CodePudding user response:
std::find
returns an iterator to the found element and std::vector::erase
accepts an iterator too. std::distance
can be used to compute the index if needed.
Small example:
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
void print(const auto& vec){
for(const auto& e:vec){
std::cout<<e<<' ';
}
std::cout<<'\n';
}
int main(){
std::vector<std::string> vec{"a","b","c","d"};
auto it = std::find(vec.begin(),vec.end(),"c");
if(it!=vec.end())//If found
{
std::cout<<"Index "<<std::distance(vec.begin(),it)<<'\n';
vec.erase(it,it 1);
print(vec);
}
}
Output:
Index 2
a b d
That said, there is simple O(1)
memory ( in terms of loaded lines) solution: read the lines and immediately write back only those that do not match the string.
CodePudding user response:
Below is the working example. There is no need to store the string into a vector
or search for the position of the string inside the vector because we can directly check if the read line is equal to the string to be searched for, as shown.
main.cpp
#include <iostream>
#include <fstream>
int main()
{
std::string line, stringtobeSearched = "Foo8854.txt";
std::ifstream inFile("input.txt");
std::ofstream outFile("output.txt");
if(inFile)
{
while(getline(inFile, line, '\n'))
{
std::cout<<line<<std::endl;
//if the line read is not same as string searched for then write it into the output.txt file
if(line != stringtobeSearched)
{
outFile << line << "\n";
}
//if the line read is same as string searched for then don't write it into the output.txt file
else
{
std::cout<<"string found "<<std::endl;//just printing it on screen
}
}
}
else
{
std::cout<<"file could not be read"<<std::endl;
}
inFile.close();
outFile.close();
return 0;
}
input.txt
file123.txt
Bob56.txt'
Foo8854.txt
file113.txt
Bob56.txt'
Foo8854.txt
file223.txt
Bob96.txt'
Foo8814.txt
output.txt
file123.txt
Bob56.txt'
file113.txt
Bob56.txt'
file223.txt
Bob96.txt'
Foo8814.txt
CodePudding user response:
#include <filesystem>
#include <iostream>
#include <fstream>
#include <map>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <vector>
#include <execution>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <string>
#include <atomic>
int main(int argc, char *argv[])
{
std::vector<std::string> b{"uyv","uky","u6t"};
std::vector<std::string> cb{"uyv"};
auto heil = std::search(b.begin(), b.end(), cb.begin(), cb.end());
b.erase(heil);
for (auto c : b)
std::cout << c << std::endl;
}