Reputation: 47
I am attempting to remove all double spaces from my string so that only single spaces remain:
while (doublespace != -1) {
kstring.replace(doublespace, 1, " ") ;
doublespace = kstring.find_first_of(" ") ; }
it finds the first double space, triggering the while statement. It then takes the first space, adds 1 to it and sets the two spaces to one space. Then it checks again.
The problem is that the loop never ends - for example if I put "hello " doubleSpace would never be set to -1.
Upvotes: 2
Views: 4512
Reputation: 5566
This alternative uses const time operations of back(), pop_back(), push_back(), empty(), and size(),
std::string str = " hello - h e l l o ";
std::string newStr = str; // diag only
std::string Miss; Miss.reserve(str.size());
while ( str.size() > 1 ) // note: str.back() undefined when str.empty()
{
// fetch copy and remove last element
char aKar = str.back(); str.pop_back();
if (! ((' ' == aKar) && // space
( ' ' == str.back()))) // space
{
Miss.push_back(aKar); // not double-space
}
}
assert(1 == str.size()); // optional
while (! Miss.empty() ) // restore str to original order
{
str.push_back (Miss.back()); // copy last element
Miss.pop_back(); // remove last element
}
assert(Miss.empty()); // optional
std::cout << "\n " << __FUNCTION__
<< "\n in: " << newStr
<< "\n out: " << str << std::endl;
Upvotes: 0
Reputation: 48635
I see two errors in your code. The first is that find_first_of()
only searches for one of the characters you supply so, in your case, it will only be looking for single spaces. Secondly you only replace one space, not two.
This should fix both those problems:
std::string& reduce_double_spaces(std::string& s)
{
std::string::size_type pos = s.find(" ");
while (pos != std::string::npos) {
// replace BOTH spaces with one space
s.replace(pos, 2, " ");
// start searching again, where you left off
// rather than going back to the beginning
pos = s.find(" ", pos);
}
return s;
}
NOTE: By beginning the subsequent searches from the place you found your last space, this version should be much more efficient. The longer the string the bigger the savings.
Upvotes: 3
Reputation: 6240
Here is an alternative take that returns copy with only single spaces in it:
#include <iostream>
#include <string>
int main()
{
std::string str = " hello - h e l l o ";
std::string newstr;
size_t beg = 0;
size_t len = str.length();
while (beg < len)
{
size_t end = str.find_first_of(' ', beg) + 1;
newstr += str.substr(beg, end - beg);
beg = str.find_first_not_of(' ', end);
}
std::cout << newstr << std::endl;
return 0;
}
Result:
hello - h e l l o
As suggested by @hnefatl this approach could also be more efficient (see comment below)
Upvotes: 3
Reputation: 6037
std::string::find_first_of
only searches until it finds one of the characters in the input string, so as you pass it " "
, it'll effectively only search for " "
- see the documentation here:
Searches the string for the first character that matches any of the characters specified in its arguments.
You should use std::string::find
instead, which searches for the first instance of the entire substring:
Notice that unlike member find_first_of, whenever more than one character is being searched for, it is not enough that just one of these characters match, but the entire sequence must match.
You're also replacing only the first space with a space (sString.replace(doubleSpace, 1, " "
), which means your output will still contain double spaces. Just use std::string::erase
instead, to erase just the first space.
This means your code snippet should look more like:
std::size_t doubleSpace = sString.find(" ");
while (doubleSpace != std::string::npos)
{
sString.erase(doubleSpace, 1);
doubleSpace = sString.find(" ");
}
Upvotes: 6