Quick std::string question

  • Thread starter Christopher Benson-Manica
  • Start date
C

Christopher Benson-Manica

Let's say I have a std::string, and I want to replace all the ','
characters with " or ", i.e. "A,B,C" -> "A or B or C". Is the
following the best way to do it?

int idx;
while( (idx=str.find_first_of(',')) >= 0 ) {
str.replace( idx, 1, "" );
str.insert( idx, " or " );
}

(Stroustrup wasn't too illuminating here, unfortunately.)
 
T

Thore Karlsen

Let's say I have a std::string, and I want to replace all the ','
characters with " or ", i.e. "A,B,C" -> "A or B or C". Is the
following the best way to do it?

int idx;
while( (idx=str.find_first_of(',')) >= 0 ) {
str.replace( idx, 1, "" );
str.insert( idx, " or " );
}

(Stroustrup wasn't too illuminating here, unfortunately.)

See if this will work for you:

///
/// Replace all occurences of a substring in a string with another
/// string, in-place.
///
/// @param s String to replace in. Will be modified.
/// @param sub Substring to replace.
/// @param other String to replace substring with.
///
/// @return The string after replacements.
inline std::string &
replacein(std::string &s, const std::string &sub,
const std::string &other)
{
assert(!sub.empty());
size_t b = 0;
for (;;)
{
b = s.find(sub, b);
if (b == s.npos) break;
s.replace(b, sub.size(), other);
b += other.size();
}
return s;
}
 
R

Rolf Magnus

Christopher said:
Let's say I have a std::string, and I want to replace all the ','
characters with " or ", i.e. "A,B,C" -> "A or B or C". Is the
following the best way to do it?

int idx;
while( (idx=str.find_first_of(',')) >= 0 ) {

This will start from the beginning for each ',' that was found and again
search the already searched parts. I'd replace the above two lines
with:

int idx = 0;
while( (idx=str.find_first_of(',', idx)) >= 0 ) {

You could even save a bit more by jumping over the replacement text,
too.
str.replace( idx, 1, "" );
str.insert( idx, " or " );


Why do you first replace the ',' with an empty string and then insert
the " or " instead of just replacing it directly with " or "?

str.replace(idx, 1, " or ");
 
M

Mike Wahler

Christopher Benson-Manica said:
Let's say I have a std::string, and I want to replace all the ','
characters with " or ", i.e. "A,B,C" -> "A or B or C". Is the
following the best way to do it?

int idx;
while( (idx=str.find_first_of(',')) >= 0 ) {
str.replace( idx, 1, "" );
str.insert( idx, " or " );
}

(Stroustrup wasn't too illuminating here, unfortunately.)

For more versatility, I've changed your 'character to find'
to 'string to find':


#include <iostream>
#include <string>

/* If 'from' matches 'to' or 'from' is empty, */
/* does not parse 's', returns std::string::npos */
/* */
/* Otherwise returns number of replacements done */
/* */

std::string::size_type repl(std::string& s,
const std::string& from,
const std::string& to)
{
std::string::size_type cnt(std::string::npos);

if(from != to && !from.empty())
{
std::string::size_type pos1(0);
std::string::size_type pos2(0);
const std::string::size_type from_len(from.size());
const std::string::size_type to_len(to.size());
cnt = 0;

while((pos1 = s.find(from, pos2)) != std::string::npos)
{
s.replace(pos1, from_len, to);
pos2 = pos1 + to_len;
++cnt;
}
}

return cnt;
}

int main()
{
std::string s("A,B,C");

const std::string old_seq(",");
const std::string new_seq(" or ");

std::cout << "Original string:\n"
<< '"' << s << '"'
<< "\n\n";

const std::string::size_type count(repl(s, old_seq, new_seq));
const std::string dq(count > 0, '"');
const bool parsed(count != std::string::npos);
const bool found(parsed && count > 0);

if(parsed)
{
std::cout << count
<< " occurences of sequence \"" << old_seq << "\""
<< (count ? " replaced with sequence " : " found")
<< dq << (count ? new_seq : "") << dq
<< "\n\n";
}
else
std::cout << "Nothing to change\n\n";

std::cout << (parsed && found
? std::string("New string:\n" + dq + s + dq)
: "No changes made")
<< '\n';

return 0;
}



Original string:
"A,B,C"

2 occurences of sequence "," replaced with sequence " or "

New string:
"A or B or C"



HTH,
-Mike
 
C

Cy Edmunds

Christopher Benson-Manica said:
Let's say I have a std::string, and I want to replace all the ','
characters with " or ", i.e. "A,B,C" -> "A or B or C". Is the
following the best way to do it?

int idx;
while( (idx=str.find_first_of(',')) >= 0 ) {
str.replace( idx, 1, "" );
str.insert( idx, " or " );
}

(Stroustrup wasn't too illuminating here, unfortunately.)

std::string // replace all instances of victim with replacement
mass_replace(const std::string &source, const std::string &victim, const
std::string &replacement)
{
std::string answer = source;
std::string::size_type j = 0;
while ((j = answer.find(victim, j)) != std::string::npos )
answer.replace(j, victim.length(), replacement);
return answer;
}
 
T

Thore Karlsen

std::string // replace all instances of victim with replacement
mass_replace(const std::string &source, const std::string &victim, const
std::string &replacement)
{
std::string answer = source;
std::string::size_type j = 0;
while ((j = answer.find(victim, j)) != std::string::npos )
answer.replace(j, victim.length(), replacement);
return answer;
}

This function doesn't work.

mass_replace("a", "a", "a");

Oops.
 
M

Mike Wahler

Thore Karlsen said:
On Tue, 10 Feb 2004 00:21:02 GMT, "Cy Edmunds"


This function doesn't work.

mass_replace("a", "a", "a");

Oops.

Try mine, I spent a bit of time testing it for such corner cases
(since I needed to write something like that for myself anyway).

Of course I might have missed something... :)

-Mike
 
T

Thore Karlsen

Try mine, I spent a bit of time testing it for such corner cases
(since I needed to write something like that for myself anyway).

Thanks, but I already have my own, which I posted. :)
 
C

Chris \( Val \)

Hi Mike.

| | > On Tue, 10 Feb 2004 00:21:02 GMT, "Cy Edmunds"
| >
| > >std::string // replace all instances of victim with replacement
| > >mass_replace(const std::string &source, const std::string &victim, const
| > >std::string &replacement)
| > >{
| > > std::string answer = source;
| > > std::string::size_type j = 0;
| > > while ((j = answer.find(victim, j)) != std::string::npos )
| > > answer.replace(j, victim.length(), replacement);
| > > return answer;
| > >}
| >
| > This function doesn't work.
| >
| > mass_replace("a", "a", "a");
| >
| > Oops.
|
| Try mine, I spent a bit of time testing it for such corner cases
| (since I needed to write something like that for myself anyway).
|
| Of course I might have missed something... :)

Since you're interested in such an exercise for yourself,
then I thought the following might interest you too ;-):

# include <iostream>
# include <ostream>
# include <string>

inline std::string TrimBS( const std::string& S,
const std::string& Junk = " \a\b\f\t\n\r\v," )
{
const std::string::size_type First( S.find_first_not_of( Junk ) );
const std::string::size_type Last( S.find_last_not_of( Junk ) );

return ( First == std::string::npos ) ?
std::string( "" ) : S.substr( First, Last - First + 1 );
}

inline void ReplaceTokens( std::string& S, const std::string& Token )
{
S = TrimBS( S );
std::string::size_type Idx( 0 );
std::string::size_type Pos( 0 );
std::string::size_type Start( 0 );

static const char* GoodChars( "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" );

while( ( Pos = S.find_first_not_of( GoodChars, Start ) ) != std::string::npos )
{
if( ( Idx = S.find_first_of( GoodChars, Pos ) ) != std::string::npos )
{
S.erase( Pos, Idx - Pos );
S.insert( Pos, Token );
}

Start = Pos + Token.size();
}
}

int main()
{
std::string S( " A , B, C , D,Z, " );

std::cout << S << std::endl;
ReplaceTokens( S, " or " );
std::cout << S << std::endl;

return 0;
}

-- Input --
A , B, C , D,Z,

-- Output --
A or B or C or D or Z

Cheers.
Chris Val
 
C

Christopher Benson-Manica

Rolf Magnus said:
Why do you first replace the ',' with an empty string and then insert
the " or " instead of just replacing it directly with " or "?
str.replace(idx, 1, " or ");

Probably because I'm dumb (and Stroustrup doesn't go into specifics on
the std::string functions). Thanks.
 
M

Mike Wahler

Chris ( Val ) said:
Hi Mike.

Since you're interested in such an exercise for yourself,
then I thought the following might interest you too ;-):

[snip misc string handling functions]

Thanks, Chris.

-Mike
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,177
Latest member
OrderGlucea
Top