【问题标题】:Counting vowels c++计数元音c ++
【发布时间】:2020-03-24 08:51:21
【问题描述】:

当用户输入 10 个字母时,程序应该知道其中有多少是元音。我写了这段代码:

while (count<10)
    {
        cin >> n;
        count++;
        if (n == 'A' || n == 'a' && n == 'E' || n == 'e' && n == 'I' || n == 'i' && n == 'O' || n == 'o' && n == 'U' || n == 'u')
            {
                total++;
            }
    }

cout <<  total << endl;

即使用户输入了元音,这也会产生 0 的输出。有什么问题吗?

【问题讨论】:

  • ||替换&amp;&amp;
  • 将所有&amp;&amp; 替换为||。还有n的类型是什么?提供minimal reproducible example
  • 您的代码检查一个字符是否同时是所有五个元音
  • 请按字面意思阅读:没有字符可以是AaEe 和...输出0 显然是任何输入的正确答案. ;-)
  • @n314159 抱歉,我有这样的想法,如果我把 || (或)在那里,它只会检查第一个条件,并将 A/a 添加到总数中,而不检查其余条件。

标签: c++


【解决方案1】:

让我们从稍微减少条件开始,只看ae

if (n == 'A' || n == 'a' && n == 'E' || n == 'e')

然后为了简单起见只考虑小写字母(但保留了问题)

if (n == 'a' && n == 'e')

如果你大声读出来,它会说“如果n'a' 并且n 是'e'”。 “AND”(来自&amp;&amp; 运算符)意味着两个 条件都必须为真。你在这里创造了一个不可能的条件,如果n'a',那么它不是'e',所以你得到if (true &amp;&amp; false) - 这是错误的。如果n'e',那么它就不是'a',所以你得到if (false &amp;&amp; true)

如果至少有一个相等比较为真,只需将所有&amp;&amp;(和)运算符替换为||(或)运算符即可使条件为真。

if (n == 'A' || n == 'a' || n == 'E' || n == 'e' 
    || n == 'I' || n == 'i' || n == 'O' || n == 'o' 
    || n == 'U' || n == 'u')

有一些方法可以简化条件。

一种是加一个#include &lt;cctype&gt;,用std::tolowern转为小写,那么只需要和小写字符进行比较即可。

n = std::tolower(n);
if (n == 'a' || n == 'e' || n == 'i' || n == 'o' || n == 'u')

另一种重复性较低的方法是创建一个包含所有元音的std::string,然后在顶部创建see if it contains n#include &lt;string&gt;

std::string vowels = "aeiouAEIOU";
while (/*...*/) {
   // ...
   if (vowels.find(n) != std::string::npos) {
     ++total;
   }
}

正如n314159 所指出的,如果您使用的是C++ 17 或更高版本,则可以改用std::string_view,这样更便宜。 #include &lt;string_view&gt;

static constexpr std::string_view vowels = "aeiouAEIOU";   
while (/*...*/) {
   // ...
   if (vowels.find(n) != std::string_view::npos) {
     ++total;
   }
}

【讨论】:

  • 我忽略了&amp;&amp; 的优先级高于||。然而,即使考虑到这一点,它并没有变得更好...... ;-)
  • 在 C++17 上,我建议将 std::string 替换为 constexpr std::string_view,因为它可能更便宜,并且编译器应该能够对其进行更多优化。
  • @scypx 请不要忘记标记answer
  • 嗯,如果 std::tolower 然后 find 在较小的字符串上比 find 长字符串上更快,那将会很有趣。我的意思是,std::lower(如果它不安全)应该可以通过一个减法来实现。并不是说它以任何方式相关^^
  • @urbanSoft 如果其他人会阅读您的代码,我鼓励您在您的意思是“等于”时使用==。你会使用像这样不必要的位操作来制造很多敌人。显然,如果您所做的只是单独的项目,那么一切都不重要。
【解决方案2】:

我建议使用带有直通的switch 语句,这样更具可读性但也可能更有效(可以通过跳转表实现)。

int count = 10;
while (count--) {
    switch(std::tolower(n)) {
        case 'a': case 'e': 
        case 'i': case 'o': 
        case 'u': total ++; break;
        default:;
    }
}

【讨论】:

  • 你应该添加[[ fallthrough ]] 否则会被编译器警告惹恼。
  • @n314159 这不会对 g++ 或 clang++ 发出警告(即使使用 -Weverything 标志)。我猜他们看到了空的 case 正文,他们认为它已经足够明确了。
  • @n314159 嗯,你说得对,它有时会发出警告。仅适用于非空 'u' 情况,所以修复它:)
猜你喜欢
  • 2013-08-09
  • 1970-01-01
  • 2012-02-29
  • 2015-05-16
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多