'Convert std::vector to std::string without \0
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?
Solution 1:[1]
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.
Solution 2:[2]
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.size()); // 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.size()); // 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.
Solution 3:[3]
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();
}
Solution 4:[4]
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;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nathan Pierson |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | jloh |
