I want to remove the vowels from a std::string
with this code:
# include <string>
#include <vector>
bool IsVowel(char c) {
return ((c == 'a') ||
(c == 'A') ||
(c == 'e') ||
(c == 'E') ||
(c == 'i') ||
(c == 'I') ||
(c == 'o') ||
(c == 'O') ||
(c == 'u') ||
(c == 'U'));
}
std::string RemoveVowel(const std::string& str) {
const size_t s = str.length();
std::vector<char> inProgress(s);
int index = 0;
for (char c : str) {
if (!IsVowel(c)) {
inProgress[index] = c;
index ;
}
}
std::string sy(inProgress.begin(), inProgress.end());
return sy;
}
But with this input:
"aaaaaa"
I get this output:
"\0\0\0\0\0\0"
But I want to get this:
""
The problem is with std::string sy(inProgress.begin(), inProgress.end());
. I don't know how to convert the std::vector
to std::string
without any \0
.
How can I fix this problem?
CodePudding user response:
As you can see, inProgress
always contains str.length()
many elements. index
tells you the actual number of vowels in there. std::string
has constructors that let you use that information to determine how much of inProgress
to use in the initialization of sy
.
So, you could do:
std::string sy(inProgress.begin(), inProgress.begin() index);
return sy;
This would construct sy
using only the initial segment of inProgress
that actually contains vowels.
CodePudding user response:
The answer by Nathan Pierson explains how to do what you want.
But there are easier ways:
C 20 or newer:
std::string RemoveVowel(std::string str)
{
std::erase_if(str, IsVowel);
return str;
}
C 17:
std::string RemoveVowel(std::string_view str)
{
std::string ret;
ret.reserve(str); // Optional.
std::copy_if(str.begin(), str.end(), std::back_inserter(ret), std::not_fn(IsVowel));
return ret;
}
C 14 and earlier:
std::string RemoveVowel(const std::string &str)
{
std::string ret;
ret.reserve(str); // Optional.
std::copy_if(str.begin(), str.end(), std::back_inserter(ret), [](char ch){return !IsVowel(ch);});
return ret;
}
Even if you don't want to keep the custom loop, you should replace std::vector
with a std::string
to avoid the extra copy at the return.
CodePudding user response:
You could not pass in an initial size for your vector and use push_back
:
std::string RemoveVowel(const std::string& str) {
std::vector<char> in_progress;
in_progress.reserve(str.size());
for (const char& c : str) {
if (!IsVowel(c)) {
in_progress.push_back(c);
}
}
std::string sy(in_progress.begin(), in_progress.end());
return sy;
}
Or alternatively use a stringstream
instead:
std::string RemoveVowel(const std::string& str) {
std::stringstream ss;
for (const char& c : str) {
if (!IsVowel(c)) {
ss << c;
}
}
return ss.str();
}
CodePudding user response:
Instead, use std::vector::push_back(value) to insert new valid characters into your vector, rather than setting null values.
for (char c : str) {
if (!IsVowel(c)) {
inProgress.push_back(c);
}
}
std::string sy(inProgress.begin(), inProgress.end());
return sy;
Alternatively, can't you simply just append to an output string?
std::string sy = "";
for (char c : str) {
if (!IsVowel(c)) {
sy = c;
}
}
return sy;