Reputation: 2415
Suppose my string is "g500() g600() g200()\n g1()" I want to output "g1() g2() g3()\n g4()" instead.
I have tried using regex to do it like so, but this gives each occurence the same value.
#include<iostream>
#include<regex>
#include<string>
void renameGates(std::string& qt_prims, int& gate_id){
std::string s("g.*?\\(");
std::regex re(s);
qt_prims=std::regex_replace(qt_prims,re,std::string("g"+std::to_string(gate_id)+ "("));
++gate_id;
std::cout<<qt_prims;
//should print "g1() g2() g3()\n g4()" but prints "g0() g0() g0()\n g0()"
}
int main(){
std::string str="g500() g600() g200()\n g1()";
int x=0;
renameGates(str,x);
}
But all the values of g get the same value. I have tried reading the c++ documentation on std::regex_replace, but the function signatures are really cryptic. I don't know which version I need.
Upvotes: 0
Views: 1182
Reputation: 626929
You may implement a callback to regex_replace
like this:
#include <iostream>
#include <cstdlib>
#include <string>
#include <regex>
using namespace std;
int gate_id = 0;
template<class BidirIt, class Traits, class CharT, class UnaryFunction>
std::basic_string<CharT> regex_replace(BidirIt first, BidirIt last,
const std::basic_regex<CharT,Traits>& re, UnaryFunction f)
{
std::basic_string<CharT> s;
typename std::match_results<BidirIt>::difference_type
positionOfLastMatch = 0;
auto endOfLastMatch = first;
auto callback = [&](const std::match_results<BidirIt>& match)
{
auto positionOfThisMatch = match.position(0);
auto diff = positionOfThisMatch - positionOfLastMatch;
auto startOfThisMatch = endOfLastMatch;
std::advance(startOfThisMatch, diff);
s.append(endOfLastMatch, startOfThisMatch);
s.append(f(match));
auto lengthOfMatch = match.length(0);
positionOfLastMatch = positionOfThisMatch + lengthOfMatch;
endOfLastMatch = startOfThisMatch;
std::advance(endOfLastMatch, lengthOfMatch);
};
std::sregex_iterator begin(first, last, re), end;
std::for_each(begin, end, callback);
s.append(endOfLastMatch, last);
return s;
}
template<class Traits, class CharT, class UnaryFunction>
std::string regex_replace(const std::string& s,
const std::basic_regex<CharT,Traits>& re, UnaryFunction f)
{
return regex_replace(s.cbegin(), s.cend(), re, f);
}
std::string my_callback(const std::smatch& m) {
gate_id++;
stringstream s;
s << "g" << gate_id << "()";
return s.str();
}
int main() {
gate_id = 0;
std::string s = "g500() g600() g200()\n g1()";
std::cout << regex_replace(s, regex("g\\S*\\(\\)"), my_callback) << std::endl;
return 0;
}
See the C++ demo
The pattern is
g
- a g
char\S*
- 0+ non-whitespace chars\(\)
- a ()
substring.The replacement is built dynamically inside my_callback
method.
For each subsequent replacement, you need to reset the gate_id
.
Upvotes: 1
Reputation: 15267
It will not work as you planned. The regex will replace everything. Or you could use backreferences ($1, $2, $3 and so on), if the number of patterns in the string are known.
You will also have the difficulty with counting. The replace string will be created once and the counter will always have the same value.
So we need to use a different approach using std::regex_search.
. We search for our pattern, then take the prefix and add the new g().
Then we continue the operation in a loop with the suffix.
And that's it.
See the following example:
#include<iostream>
#include<regex>
#include<string>
void renameGates(std::string& qt_prims, int& gate_id){
// Define a std::regex to search for g then some digits and brackezs
std::regex re("g\\d+\\(\\)");
// Here we will receive the submatches
std::smatch sm{};
// Make a local copy
std::string tmp{qt_prims};
// Reset resulting value
qt_prims.clear();
// Search all g-numbers
while (std::regex_search(tmp, sm, re)) {
// Build resulting string
qt_prims = qt_prims + std::string(sm.prefix()) + "g" + std::to_string(gate_id++) + "()";
// Continue to search with the rest of the string
tmp = sm.suffix();
}
// If there is still a suffix, add it
qt_prims += sm.suffix();
// Debug output
std::cout << qt_prims << "\n";
}
int main(){
std::string str="g500() g600() g200()\n g1()";
int x=0;
renameGates(str,x);
}
Upvotes: 1