std::string question

K

Kian Goh

Hello,

I would like to replace all the occurrence of "(" and ")"
in C++ std::string to "\(" and "\)".

For example:
string s = "(abc)|(toto)|(lala)"
will be become "\(abc\)|\(toto\)|\(lala\)"


Question:
Just wonder if there is a straight forward function to do so??


Currently I am using a while loop to read through the string, then
basic_string::find and basic_string::replace the occurrence of "(" and ")".

Any better solution?

Thanks,
Kian
 
J

John Harrison

Kian Goh said:
Hello,

I would like to replace all the occurrence of "(" and ")"
in C++ std::string to "\(" and "\)".

For example:
string s = "(abc)|(toto)|(lala)"
will be become "\(abc\)|\(toto\)|\(lala\)"


Question:
Just wonder if there is a straight forward function to do so??
No.



Currently I am using a while loop to read through the string, then
basic_string::find and basic_string::replace the occurrence of "(" and
")".

Any better solution?

Certainly there are bad ways and good ways to write this code but without
seeing the code you have written it is impossible to say whether there is a
better solution.

A good solution would work in three phases.

1) Go though the string seeing how many backslashes you are going to need to
insert
2) Increase the size of the string by the number of extra backslashes needed
3) Loop backwards though the string, copying characters and inserting
backslashes as necessary.

The point of this compexity is that it minimises reallocation of the string
and copying of characters.

A bad solution would work like this

1) Go forwards through the string and each time you find a "(" or ")" insert
a backslash.

john
 
J

Jason Heyes

Kian Goh said:
Hello,

I would like to replace all the occurrence of "(" and ")"
in C++ std::string to "\(" and "\)".

For example:
string s = "(abc)|(toto)|(lala)"
will be become "\(abc\)|\(toto\)|\(lala\)"


Question:
Just wonder if there is a straight forward function to do so??


Currently I am using a while loop to read through the string, then
basic_string::find and basic_string::replace the occurrence of "(" and
")".

Any better solution?

Thanks,
Kian

Here is a solution:

string add_backslash_to_brackets(char ch)
{
string s(1, ch);
if (ch == '(' || ch == ')')
s.insert(s.begin(), '\\');
return s;
}

vector<string> v;
transform(s.begin(), s.end(), back_inserter(v), add_backslash_to_brackets);
s = accumulate(v.begin(), v.end(), string());

Hope you like it.
 
S

Siemel Naran

string add_backslash_to_brackets(char ch)
{
string s(1, ch);
if (ch == '(' || ch == ')')
s.insert(s.begin(), '\\');
return s;
}

vector<string> v;
transform(s.begin(), s.end(), back_inserter(v), add_backslash_to_brackets);
s = accumulate(v.begin(), v.end(), string());

Good.

Along the same lines, the function back_inserter(v) returns an iterator,
specifically a std::back_insert_iterator<std::vector<std::string>>, whose
operator= calls v.push_back(...). You could write your own
back_insert_iterator class too, thus avoiding the need to create strings and
a vector of strings.

class special_back_insert_iterator : public
std::back_insert_iterator<std::string> {
typedef std::back_insert_iterator<std::string> inherited;
public:
special_back_insert_iterator(std::string& s) : inherited(s) { }
special_back_insert_iterator& operator=(char c) {
if (ch == '(' || ch == ')') inherited::eek:perator=('\\');
inherited::eek:perator==(c);
return *this;
}
};

inline
special_back_insert_iterator special_back_inserter(std::string&)
{
return ...;
}

string s2;
transform(s.begin(), s.end(), special_back_inserter(s2));
 
J

Jason Heyes

Siemel Naran said:
Good.

Along the same lines, the function back_inserter(v) returns an iterator,
specifically a std::back_insert_iterator<std::vector<std::string>>, whose
operator= calls v.push_back(...). You could write your own
back_insert_iterator class too, thus avoiding the need to create strings
and
a vector of strings.

class special_back_insert_iterator : public
std::back_insert_iterator<std::string> {
typedef std::back_insert_iterator<std::string> inherited;
public:
special_back_insert_iterator(std::string& s) : inherited(s) { }
special_back_insert_iterator& operator=(char c) {
if (ch == '(' || ch == ')') inherited::eek:perator=('\\');
inherited::eek:perator==(c);
return *this;
}
};

inline
special_back_insert_iterator special_back_inserter(std::string&)
{
return ...;
}

string s2;
transform(s.begin(), s.end(), special_back_inserter(s2));

Nice. It all happens in one line of STL. I wonder how these STL solutions
compare with non-STL ones in terms of code complexity. Alot better I
presume.
 
D

David Harmon

On Tue, 16 Nov 2004 21:59:27 -0500 in comp.lang.c++, "Kian Goh"
I would like to replace all the occurrence of "(" and ")"
in C++ std::string to "\(" and "\)".


#include <string>
#include <algorithm>
#include <numeric>
#include <iostream>

std::string changer(std::string was, char in)
{
if (in == '(')
return was+"\\(";
if (in == ')')
return was+"\\)";
return was+in;
};

int main()
{
std::string foo("(abc)|(toto)|(lala)");
std::string bar = std::accumulate(foo.begin(), foo.end(),
std::string(""), changer);
std::cout << bar;
}
 
S

Siemel Naran

Jason Heyes said:
Nice. It all happens in one line of STL. I wonder how these STL solutions
compare with non-STL ones in terms of code complexity. Alot better I
presume.

Except for the meaningless name 'special_back_inserter', the code above
looks simpler. However, it's not an inplace algorithm, therefore uses more
memory. John's suggestion is in in-place algorithm, though harder to
implement.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,973
Members
47,530
Latest member
jameswilliam1

Latest Threads

Top