【问题标题】:String manipulation with vowels not working as intended元音的字符串操作未按预期工作
【发布时间】:2019-06-13 19:23:06
【问题描述】:

下面的程序旨在将字符串中的所有字符变为小写,删除所有元音,然后在每个字母之前打印一个句号。例如,输入“umbrella”将变为“.m.b.r.l.l”。但是当我输入“tour”时,'u'并没有被删除。

char ChangeToLow(char letter) {
  if(letter <= 'Z' && letter >= 'A')
    return letter - ('A' - 'a');
  return letter;
}
int main()
{
    string name;
    cin>>name;
    for (int i = 0 ; i < name.length() ; i++)
    {
        name[i] = ChangeToLow(name[i]);
        if (name[i] == 'y' || name[i] == 'a'|| name[i] == 'u'|| name[i] == 'i'|| name[i] == 'e'|| name[i] == 'o')
        {
            name.erase(i,1);
        }
    }
    for (int i = 0 ; i < name.length() ; i++)
        {
          cout<<'.'<<name[i];
        }
}

我希望输出“.t.r”,但它会打印“.t.u.r”。 提前致谢。

【问题讨论】:

  • 听起来你可能需要学习如何使用调试器来单步调试你的代码。使用好的调试器,您可以逐行执行您的程序,并查看它与您期望的偏差在哪里。如果您要进行任何编程,这是必不可少的工具。进一步阅读:How to debug small programsDebugging Guide
  • @jww:这是一种常见的 ASCII hack。
  • 删除一个字母后,后面的所有字母都会在字符串中向左移动,但您仍在递增i。例如。如果你删除 0,1 会变成 0,但你会继续移动到 1 并跳过“新”0。
  • @JonathanPotter 这似乎是最有可能的问题。 OP 应该能够通过测试任何两个或多个元音相邻的单词来确认这种行为。
  • @JonathanPotter 谢谢,成功了。

标签: c++ string c++11


【解决方案1】:

当您从字符串中删除一个字符时,剩余的内容会移动以填充空间。他们的指数会相应调整。在您的游览示例中,它看起来如下所示:

在您从游览中删除“o”后,您的循环计数器 i 增加到 2,而 name[i] 现在是“r”。避免这种行为的一种选择是在删除元音时减少 i

【讨论】:

    【解决方案2】:

    我有一些建议给你。首先,您不应该将using namespace std; 放入您的代码中。它只会增加混乱,被认为是一种不好的做法。我认为这也是一件好事,如果你考虑学习 STL,如果你的目标真的是深入学习 C++。至于错误,我认为已经发布的答案显示了您的错误假设。

    #include <iostream>
    #include <cstdlib>
    #include <locale>
    #include <set>
    #include <algorithm>
    
    int main()
    {
            std::string name;
            std::cin>>name;
    
            std::set<char> vowels={'a','u','i','e','o'};
            std::transform(name.begin(), name.end(), name.begin(), [](auto v){ return std::tolower(v, std::locale());});
    
            auto iter=std::remove_if(name.begin(), name.end(), [&vowels](auto v){ return vowels.find(v)!=vowels.end();});
            name.erase(iter,name.end());
    
            for (int i = 0 ; i < name.length() ; i++)
            {
                    std::cout<<'.'<<name[i];
            }
            return EXIT_SUCCESS;
    }
    

    【讨论】:

    • 几乎完美。我还建议进一步优化上述内容,将 for 循环和 std::copy 名称删除到 std::ostream_iterator(std::cout, " ")
    猜你喜欢
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多