C ++清除列表<string> </string>中的元音

时间:2014-03-13 22:23:25

标签: c++ string list c++11

我有一个大学作业来编写一个函数,在一个字符串列表中,所有检测到的元音都必须被删除,之后,列表需要从最大到最小的字符串排序。

我尝试的内容类似于int的列表来定义迭代器,取消引用它并与带有if的字符进行比较,并对所有元音执行此操作,那是行不通的。

我需要在下面的代码中更改什么?我首先尝试写main()来测试它是否可以编译。提前谢谢。

int main()
{
    string x;
    list<string> vowel;

    while (cin >> x)
        vowel.push_back(x);

    list<string>::iterator k;

    for(auto k=vowel.begin(); k!=vowel.end(); k++)
        if(*k == 'A' || *k =='a' || ...) // for every letter that is a vowel
            vowel.erase(*k);

    vowel.sort();

    return 0;
}

2 个答案:

答案 0 :(得分:2)

要检查字符是否为元音,您可以在所有元音的std::findstd::vector

static inline bool isVowel( char ch)
{
        static const std::string vowels("aeiouEAIOU");
        return vowels.end() != std::find(vowels.begin(), vowels.end(), ch);
}

用法:

std::assert( isVowel( 'a') == true);

示例:

int main()
{
    std::string x;
    std::vector< std::string> vowel;
    vowel.push_back( "a");
    vowel.push_back( "b");
    vowel.push_back( "c");
    vowel.push_back( "d");
    vowel.push_back( "e");
    vowel.push_back( "f");

    std::vector< std::string>::iterator k;

    for( k = vowel.begin(); k != vowel.end();)
      if( isVowel( *((*k).c_str())))
          k = vowel.erase(k);
      else
          ++k;

    return 0;
}

使用std :: remove_if和functor

这通常比使用功能更快。应用程序运算符可以很容易地内联。

struct isVowel_{
    std::string& vowels;
    isVowel_( std::string& s) : vowels( s) {}
    bool operator()( std::string c) const {
        return vowels.end() != std::find(vowels.begin(), 
                                                  vowels.end(), *(c.c_str()));
    }
};

int main()  {
  std::vector<std::string> vowel;
  vowel.push_back("a");
  vowel.push_back("b");
  vowel.push_back("c");
  vowel.push_back("d");
  vowel.push_back("e");
  vowel.push_back("f");

  std::vector<std::string>::iterator k;
  std::string vowels("aeiouEAIOU");

  k = std::remove_if( vowel.begin(), vowel.end(), isVowel_( vowels));

  vowel.erase( k, vowel.end());  // erases the unspecified values and reduces
                                 // the physical size of the container to match
                                 // its new logical size
  return 0;
}

答案 1 :(得分:1)

您的代码遇到了一些问题,您可能需要解决这些问题:

1。命名

名称vowel不是输入字符串列表的好名称。像

这样的东西
std::list<std::string> inputStringList

会更好。

2。迭代器声明

您要将变量k声明两次。来到这里:

list<string>::iterator k;

再来一次:

for(auto k=vowel.begin(); k!=vowel.end(); k++)

您应该只声​​明变量一次。摆脱第一个宣言。

3。字符串比较

在这段代码中:

for(auto k=vowel.begin(); k!=vowel.end(); k++)
    if(*k == 'A' || *k =='a' || ...) // for every letter that is a vowel
        vowel.erase(*k);

您将k的值(std::string)与“A”({1}}进行比较。不要这样做。您应该将字符串与字符串或字符与字符进行比较,但不要混合使用。要么将char的声明更改为vowel,要么将if语句更改为比较字符串

std::list<char>

4。未定义的行为

当您从列表中删除每个字符串时,您正在使用undefined behaviour

if (*k == "A" || ...)
    //    ^-^--- Note use of double-quotes for a string literal.

从列表中删除字符串后,迭代器变为无效,但您会在vowel.erase(*k); 循环(for)的下一次迭代中再次使用它。你可能侥幸逃脱,但我不希望这样。

请记住,即使DID正常工作(也没有),你最终会跳过你没有检查过的字符,因为删除后的字符串之后的字符串都会向上移动一个。< / p>

最好使用k++循环来迭代和擦除。像这样:

while

为什么这样有效here