【问题标题】:How to remove consonants from a string? [closed]如何从字符串中删除辅音? [关闭]
【发布时间】:2018-06-06 07:48:27
【问题描述】:

这是我的代码:

#include <iostream>
#include <string>
#include<bits/stdc++.h>
using namespace std;

int main() 
{
    int n;
    cin >> n;

    while(n--)
    {
        string str;
        char a[] = {'a','e','i','o','u','A','E','I','O','U'};
        getline(cin, str);

        for(int i=0 ;i<str.length(); i++)
        {
            for(int j=0; j<10; j++)
            {
                if(str[i]==a[j])
                {
                    cout << str[i];
                }
            }
        }
        cout << "\n"; 
    }
    return 0;
}

测试用例是:

HmlMqPhBfaVokhR 
wdTSFuI 
IvfHOSNv 

我没有删除任何东西,但我只打印元音。但是,有些测试用例没有通过。也许这段代码不适用于多个测试用例。

【问题讨论】:

  • 一个bug是,你需要在cin&gt;&gt;n;之后ignore(),否则getline(cin, str);,什么都得不到。这不是你应该做的:#include&lt;bits/stdc++.h&gt;
  • @PriyamRajvanshi 使用测试用例而不是 cmets 编辑您的问题。
  • @JeJo 你能提供我的代码吗?
  • 现在您是要真正删除元音还是只打印没有它们的输入?

标签: c++ algorithm c++11 stdstring erase


【解决方案1】:

试试这个for proper console in

int main()
{
    int n;
    std::cin >> n;
    std::cin.ignore();   // fix
    /* remaining code */
    return 0;
}

> 查找字符串中的元音

字符串中查找元音的方法是使用std::binary_search 元音表中给定字符串的每个字符。

  1. 制作一个由所有元音组成的char排序数组(即元音数组)。
  2. 对于输入字符串的每个charstd::binary_search元音数组
  3. 如果std::binary_search返回true(意味着char是元音),打印字符串的char

以下是示例代码! (See live online)

#include <iostream>
#include <string>
#include <algorithm> // std::for_each, std::binary_search, std::sort
#include <array>     // std::array

int main()
{
    std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
    std::sort(a.begin(), a.end()); // need sorted array for std::binary_search

    const std::string str{ "HmlMqPhBfaVokhR wdTSFuI IvfHOSNv" };
    std::for_each(str.cbegin(), str.cend(), [&](const char str_char)
    {
        if (std::binary_search(a.cbegin(), a.cend(), str_char))
            std::cout << str_char << " ";
    });
    return 0;
}

输出

a o u I I O

> 删除字符串中的元音

如下使用erase-remove idiom直到)。

  1. 制作一个由所有元音组成的char排序数组(即元音数组)。
  2. 使用std::remove_if,收集指向元音字符的迭代器。可以使用 lambda 函数作为 std::remove_if 的谓词,其中std::binary_search 用于检查字符串中的char 是否存在于元音数组中。
  3. 使用std::string::erase,从字符串中删除所有收集到的字符(即元音)。

以下是示例代码! (See live online)

#include <iostream>
#include <string>
#include <algorithm> // std::sort, std::binary_search, std::remove_if
#include <array>     // std::array

int main()
{
    std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
    std::sort(a.begin(), a.end()); // need sorted array for std::binary_search

    std::string str{ "Hello World" };
    // lambda(predicate) to check the `char` in the string exist in vowels array
    const auto predicate = [&a](const char str_char) -> bool { 
        return std::binary_search(a.cbegin(), a.cend(), str_char);
    };
    // collect the vowels
    const auto vowelsToRemove = std::remove_if(str.begin(), str.end(), predicate);
    // erase the collected vowels using std::string::erase
    str.erase(vowelsToRemove, str.end());

    std::cout << str << "\n";
    return 0;
}

输出

Hll Wrld

由于,因此可以使用std::erase_if,即less error prone than the the above one(See online live using GCC 9.2)

#include <iostream>
#include <string>    // std::string, std::erase_if
#include <array>     // std::array

int main()
{
    std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
    std::sort(a.begin(), a.end()); // need sorted array for std::binary_search

    std::string str{ "Hello World" };
    // lambda(predicate) to check the `char` in the string exist in vowels array
    const auto predicate = [&a](const char str_char) -> bool { 
        return std::binary_search(a.cbegin(), a.cend(), str_char);
    };

    std::erase_if(str, predicate); // simply erase

    std::cout << str << "\n";
    return 0;
}

> 删除字符串中的辅音

要从给定字符串中删除辅音,在上面的predicate 中否定std::binary_search 的结果。 (See live online)

const auto predicate = [&a](const char str_char) -> bool { 
    return !std::binary_search(a.cbegin(), a.cend(), str_char);
    //     ^^ --> negate the return
};

作为旁注,

【讨论】:

  • 你怎么知道字符向量的“升序”是什么?你怎么知道对于这么短的字符列表,二分查找比线性查找要快?
  • @PeteBecker 你同意 O(log10) O(10) 吗?如果是这样,二进制搜索总是更好。但是,对于一个小数组,我们也可以进行线性查找,最终效果不会有很大的性能差异。
  • 如果输入足够小,排序开销甚至可能会消耗所有可能仍然存在的小好处......假设问题对于这种精心设计的方法来说太简单了(但我喜欢它。 ..).
  • @Aconcagua:关于std::sort(),你说的是真的。他还可以在循环之前使用排序,这样就可以避免每次排序。但是,我只是概括了这种情况,这将适用于其他不是元音的字符。此外,二分查找是我的习惯。但是,我发现 strchr 也是一个很好的方法,因为数组很小。
  • @JeJo -- 二分查找更适合大输入。渐近复杂度是关于渐近线;它不是性能的绝对衡量标准。
【解决方案2】:

除了已经回答的std::getline问题:

for(int i=0 ;i<str.length(); i++)
{
    for(int j=0; j<10; j++)
    {
        if(str[i] == a[j])
        {
            // this is the one you do NOT want to print...
            // cout<<str[i];
            // skip instead:
            goto SKIP;
        }
    }
    std::cout << str[i]; // output the one NOT skipped...
    SKIP: (void)0;
}

好的,不想开始讨论goto 的用法,有很多方法可以避免它,例如。 G。通过将内部 for 循环打包到单独的(内联)函数中。但是,您可以更轻松地使用它,因为已经存在这样的功能;使用基于范围的 for 循环,代码变得更加简单:

for(auto c : str)
{
    if(!strchr("aeiouAEIOU", c))
    {
        std::cout << c;
    }
}

strchr(来自 cstring)返回指向字符串中与引用字符相等的第一个字符的指针 - 如果未找到则返回 nullptr...

要以现代 C++ 方式真正删除字符串中的元音,请考虑以下几点:

str.erase(std::remove_if(
        str.begin(), str.end(),
        [](char c) { return strchr("aeiouAEIOU", c) != nullptr; }
    ), str.end());

【讨论】:

    【解决方案3】:

    您的代码可能应该如下所示(请参阅 cmets inline):

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
        string vowels = "aeiouAEIOU";
    
        int n;
        cin>>n; // assume this stands for line count
    
        while(n-- >= 0)
        {
            string str, result;
            getline(cin, str);
    
            for(int i=0 ;i<str.length(); i++)
            {
                if (vowels.find(str[i]) != std::string::npos)
                    result += str[i];   // add character to result if it is not consonant
            }
            cout<<result<<"\n"; // print result
        }
    
        return 0;
    }
    

    【讨论】:

    • 此代码不能解决问题。它所做的只是使代码复杂化;它产生完全相同的输出。
    • @PeteBecker OP 实际上并没有很好地解释这个问题。我发现行数比应有的少一。不知道是不是这个问题。
    猜你喜欢
    • 2015-07-11
    • 2021-03-17
    • 2020-03-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2015-08-30
    • 2012-10-02
    相关资源
    最近更新 更多