【问题标题】:Remove vowels from string C++从字符串 C++ 中删除元音
【发布时间】:2018-11-23 12:35:55
【问题描述】:

所以我是 C++ 的新手,并试图创建一个可以从字符串中删除元音的函数,但我失败了,这是我目前的代码:

#include <string>
using namespace std;
string remove(string st) {
    for(int i = 0; st[i] != '\0'; i++) 
        st[i] = st[i] == 'a' || st[i] == 'e' || st[i] == 'i' || st[i] == 'o' || st[i] ==
        'u' || st[i] == 'A' || st[i] == 'E' || st[i] == 'I' || st[i] == 'O' || st[i] ==
        'U' ? '' : st[i];
    }
return st;

这似乎引发了错误?知道我做错了什么

我得到的错误是:

main.cpp:10:16: error: expected expression 'U' ? '' : Z[i];

并在另一个解释器上运行:

   .code.tio.cpp:7:14: error: incompatible operand types ('const char *' and '__gnu_cxx::__alloc_traits<std::allocator<char>, char>::value_type' (aka 'char'))
            'U' ? "" : Z[i];
                ^ ~~   ~~~~

【问题讨论】:

  • 它“抛出”了什么错误?
  • '' 不是有效的字符值。也许您想使用空格字符或其他东西,但它不会从字符串中“删除”该字符,只需替换它的值。
  • 看来std::remove_if 可能是完成这项工作的更好工具。
  • edit您的问题,并用您所观察到的准确描述替换“似乎引发错误”。
  • 请确保错误来自您显示的代码,错误为"",但代码为''

标签: c++ regex string str-replace


【解决方案1】:

根据谓词(条件)从顺序容器中删除元素的规范方法是使用std::remove_if。不像它的名字所暗示的那样,这个标准算法并没有完全删除元素,它将它们移动到容器的后面,这样它们就很容易被擦除,而其他元素则保持不变并保持相同的顺序。它返回一个迭代器,该迭代器指示包含“已删除”元素的容器部分的开始。由于标准算法无法更改它们操作的容器的大小,因此必须使用容器的适当删除方法删除这些元素。对于std::string,就是std::string::erase

std::remove_if 接受一对定义要检查的元素范围的迭代器,以及一个用于确定要删除哪些元素的谓词。谓词为true 的元素将被删除。

#include <algorithm>
#include <iostream>
#include <string>

// Returns true if p_char is a vowel
bool is_vowel(const char p_char)
{

    constexpr char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
    return std::find(std::begin(vowels), std::end(vowels), p_char) != std::end(vowels);
}

std::string remove_vowel(std::string st) 
{
    // Moves all the characters for which `is_vowel` is true to the back
    //  and returns an iterator to the first such character
    auto to_erase = std::remove_if(st.begin(), st.end(), is_vowel);

    // Actually remove the unwanted characters from the string
    st.erase(to_erase, st.end());
    return st;
}

int main()
{
    std::cout << remove_vowel("Hello, World!");
}

【讨论】:

  • 神圣的。好的。我印象深刻。
  • 任何 StackOverflow C++ 帖子中的强制性 STL 重响应 :)
  • 请注意,我已将函数重命名为 remove_vowel,因为 removeremove 冲突,但我不知道它是如何包含在内的。
  • @MuhammadSalman -- 另外,请注意该函数的命名与描述的完全相同。换句话说,任何 STL 知识渊博的人都可以看一眼代码,就知道它做了什么以及它可以工作,而无需调试或单步调试代码。另一方面,手动编码的循环必须 1) 弄清楚正在做什么,2) 是否正确。
  • 我更喜欢这段代码......而且我发现 remove_if(在 cppreference.com 中)的描述不可读。你在这里的描述很棒。谢谢。
【解决方案2】:

'' 不是有效字符,您不能将“空”字符(C++ 中不存在此类内容)放入字符串中以删除内容...

您可以做的是移动非元音,即。 e.辅音在前面,跳过元音,然后删除末尾的多余字符:

auto pos = st.begin();
for(auto c : st)
{
    if(isConsonant(c))
        *pos++ = c;
}
st.erase(pos, st.end());

编辑:正如弗朗索瓦(正确)所说:没有必要重新发明轮子(前提是您不被禁止使用标准库):

st.erase(std::remove_if(st.begin(), st.end(), [](char c) { return isConsonant(c); }), st.end());

请注意std::remove_if(以及std::remove)“删除”只是将元素移动到前面并返回一个迭代器到新的数据末尾 - 但并没有真正删除“后面”的元素新的结局。所以有必要明确地erase他们,如上图所示。

【讨论】:

  • 啊,我明白了。所以我不能只放一个空字符串。我的坏习惯是 JS,python。谢谢,我会看看这是什么
  • 我假设 isConstant 函数不是 C++ 的一部分?
  • @FrançoisAndrieux:你能用std::remove_if写一个答案吗?我的 C++ 真的很糟糕吗?否则一个链接可以解释?
  • @MuhammadSalman 对,否则它将驻留在命名空间 std 中(并且可能都是小写字母)。只是使用自定义函数名称来缩短代码,改用您在原始问题中的测试...
  • @MuhammadSalman:见示例代码here
猜你喜欢
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多