Reputation:
string removeNonAlphas(string original)
{
for(int i = 0; i < original.size(); ++i){
if(!(original[i] > 64 && original[i] < 91) &&
!(original[i] > 96 && original[i] < 124)){
original[i] = original[i] - original[i];
}
}
return original;
}
//test1.cpp
string test = "abc abc";
cout << removeNonAlphas(test) << endl; // output = "abcabc"
assert(removeNonAlphas(test) == "abcabc"); // assertion failed
//Why does assertion fail above? removeNonAlphas result("abcabc") is same as //rhs "abcabc"
Upvotes: 0
Views: 686
Reputation: 302643
You're not actually erasing any characters from your string. You're just assigning them the value 0. It just looks like it works - which is just the worst. The '\0'
is just a non-printable character, which is why it looks like it prints the same. The ==
will actually check every character, even the non-printable ones, so it'll catch what you can't see.
Thankfully, the string
class makes it easy to erase
characters by providing just such a member function:
original.erase(i, 1); // erase a single character starting at i
Now that alone isn't enough. You erase a character, and now i
is "pointing" to the next element - but you won't check it. If we had "abc12abc"
, after erasing the 1
, we'd skip the 2
. So we need to change how we iterate:
for (std::string::iterator it = original.begin();
it != original.end();
/* nothing */)
{
// here's a better way to do checking
if (!(*it >= 'A' && *it <= 'Z') &&
!(*it >= 'a' && *it <= 'z'))
{
// erase(iterator ) will return the next iterator
it = original.erase(it);
}
else
{
++it;
}
}
That'll work. It's also very verbose. And error-prone. Which is why we have the erase-remove idiom:
original.erase(
std::remove_if(original.begin(),
original.end(),
[](char c) { return !std::isalpha(c); }),
original.end()
);
return original;
Upvotes: 1
Reputation: 9609
original[i] = original[i] - original[i];
What this makes is that it repaces the character with '\0'
but does not remove it. Because of that the output is not "abcabc"
but "abc\0abc"
. '\0'
is non-printable so you won't see it in the output but it is present when you compare it with ==
.
Instead of replacing charactes in a string, create a new string while iterating the old one:
string removeNonAlphas(string const& original)
{
std::string result;
for(char c : original)
if((c > 64 && c < 91) ||
(c > 96 && c < 124))
result.push_back(c);
return result;
}
Note: prefer using std::isalpha
instead of hard-coded values.
Upvotes: 3
Reputation: 283614
Both values are NOT the same, but the difference is a non-printing character, so you can't see any difference with cout
and your naked eye.
Try a proper tool, like a debugger, and you will see the extra \0
character present in the function result.
Upvotes: 1