0

So I have a file of strings that I am reading in, and I have to replace certain values in them with other values. The amount of possible replacements is variable. As in, it reads the patterns to replace with in from a file. Currently I'm storing in a vector<pair<string,string>> for the patterns to find and match. However I run into issues:

Example:

Input string: abcd.eaef%afas&333

Delimiter patterns:

. %%%

% ###

& @@@

Output I want: abcd%%%eaef###afas@@@333

Output I get: abcd#########eaef###afas@@@333

The issue being it ends up replacing the % sign or any other symbol that was already a replacement for something else, it should not be doing that.

My code is (relevant portions):

std::string& replace(std::string& s, const std::string& from, const std::string& to){
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size()) s.replace(pos, from.size(), to);
    return s;
}
string line;
vector<pair<string, string>> myset;
while(getline(delimiterfile, line)){
    istringstream is(line);
    string delim, pattern;
    if(is >> delim >> pattern){
        myset.push_back(make_pair(delim, pattern));
    } else {
        throw runtime_error("Invalid pattern pair!");
    }
}

while(getline(input, line)){
    string temp = line;
    for(auto &item : myset){
        replace(temp, item.first, item.second);
    }
    output << temp << endl;
}

Can someone please tell me what I'm messing up and how to fix it?

3
  • Attempting to use the >> operator for something like this is absolutely the wrong way to do it, and introduces completely unnecessary complications related to formatted input operators. The correct way to do this is to loop over the string, check if each character is the one that needs to be replaced, if not copy it to the destination string, else copy the replacement. That's it. End of story. A simple for loop is going to be much easier than this overengineered tangled mass of spaghetti. Commented Jun 4, 2017 at 14:15
  • The problem is that once you made a replacement, you start all over again. Therefore you first replace "." with "%%%" which you then replace with three sets of "###". When you made a replacement, don't start over from the beginning, start with the next character after the recent replacement. Commented Jun 4, 2017 at 14:15
  • @Someprogrammerdude I'm aware of that, but I just don't know how to implement it character by character like that. (Starting off from a certain character.) Commented Jun 4, 2017 at 14:17

2 Answers 2

2

In pseudo-code a simple replacement algorithm could look something like this:

string input = getline();
string output;  // The string containing the replacements
for (each char in input)
{
    if (char == '.')
        output += "%%%";
    // TODO: Other replacements
    else
        output += char;
}

If you implement the above code, once it's done the variable output will contain the string with all replacements made.

Sign up to request clarification or add additional context in comments.

4 Comments

How would I change this in order to use the pairs I read in from the file automatically? Hard coding it in is both a bad idea, and nonviable.
@Link I would suggest using a dictionary-type container instead of a vector of pairs. For example std::unordered_map. The key could be the delimiter, and the data is the replacement. Then it's basically as easy as if (char exists in map) output += map[char]
I'll look into it! Thanks!
pastebin.com/rwPyK99q I have that, but it throws some sort of error for the find function, not sure what's going wrong here?
0

I would suggest you use stringstream. This way you will be able to achieve what you are looking for very easily.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.