【问题标题】:Recursive function that counts vowels计算元音的递归函数
【发布时间】:2021-09-08 03:45:26
【问题描述】:

我有一个作业要求我“编写一个递归函数 vowels(s,low,high),它返回输入字符串 s[] 中元音的数量。”我们也受到限制通过“不要使用 C++ 字符串类型。使用 cin.get() 一次将字符读入一个数组。”我想我解决了手头的任务,但它没有编译,所以我我不确定。如果有人可以帮助我并展示如何解决我的错误以及我对解决方案所犯的任何错误,那就太好了。

这是我的错误信息。

***main.cpp:24:37: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
     vowelCount = vowels(s, low, high);**

这是我的代码:

#include <iostream>
#include <cstring>
using namespace std;

int vowels(char, int, int);

int main()
{
    char s[500];
    int high,
        vowelCount,
        low = 0;

    cout << "Enter a string of characters: ";
        cin.get(s, 500);

    high = strlen(s);
    vowelCount = vowels(s, low, high);

    cout << "The string contains " << vowelCount << " vowels." << endl;

    return 0;
}

int vowels(char s[], int low, int high)
{
    if (s[low] == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U') {
        return 1 + vowels(s, low + 1, high - 1);
    } else {
        return vowels(s, low + 1, high - 1);
    }
}

【问题讨论】:

  • if (s[low] == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U') -- 这不是您将值与多个项目进行比较的方式。在您正在使用的 C++ 书中,这本书是如何展示它是如何完成的?从简单开始 - 您如何比较 s[low]Aa
  • 你会得到无限递归和未定义的行为。
  • 您的vovels 函数实现与声明不匹配。检查第一个参数。
  • 不要使用 C++ 字符串类型 -- 使用std::string 无论如何都不会产生任何影响。无论是否使用std::string,您所犯的错误都会发生。
  • 这并没有解决问题,但是在vowels 函数中对vowels 的这两个调用是相同的(并且具有相同的错误)。当你看到两段相同的代码时,看看你能不能只写一次。在这种情况下,我会做类似bool is_vowel = /* check whether s[low] is a vowel */ 的事情。那么返回值就是is_vowel + vowels(s, low + 1, high);

标签: c++


【解决方案1】:

我们在这里谈论所谓的XY-Problem

老师想要介绍递归函数。元音计数只是一些噪音。不幸的是,给定的示例是一个糟糕的示例,因为使用迭代方法可以更好地实现它。

递归只是增加了不必要的时间和空间复杂度。因此,在所有情况下,与简单循环相比,性能都更差。

如果老师想让你学习递归,你不妨先看看this descriptionthat更实际的例子。

读完之后,你就会明白循环可以简单地转化为递归函数。

我不确定,为什么会有“低”和“高”参数。可能是因为使用了存储在 char 数组中的 C 字符串(C++ 中的废话)。我怀疑应该建立 2 个自我调用,并且函数应该从字符串的开头和结尾走到中间。这甚至会进一步降低性能。所以,让我们假设标准情况。


在您的比较问题旁边。你写的是错误的。 C++ 中的正确比较是:

if ((s[low] == 'a') || (s[low] == 'A') || (s[low] == 'e') || 
   (s[low] == 'E') || (s[low] == 'i') || (s[low] == 'I') || 
   (s[low] == 'o') || (s[low] == 'O') || (s[low] == 'u') || 
   (s[low] == 'U'))

当然,没有人会写这么长的语句,因为您可以简单地计算,无需任何比较,如果 ASCII 字符是元音。你可以简单地写:

if (std::isalpha(s[low]) && ((0x208222 >> (s[low] & 0x1f)) & 1))

就是这样。如果你有兴趣,我可以稍后解释这个理论,但这个例子不需要。

然后,接下来,您的递归函数是危险的错误,因为它没有结束条件。它将永远运行或直到堆栈溢出。

因此,您需要对其进行返工,可以这样完成:

#include <iostream>
#include <cstring>
using namespace std;

int vowels(char[], int, int);

int main()
{
    char s[500];
    int high,
        vowelCount,
        low = 0;

    cout << "Enter a string of characters: ";
        cin.get(s, 500);

    high = strlen(s);
    vowelCount = vowels(s, low, high);

    cout << "The string contains " << vowelCount << " vowels." << endl;

    return 0;
}

int vowels(char s[], int low, int high)
{
    int sum = 0;
    if (low != high) {
        if ((s[low] == 'a') || (s[low] == 'A') || (s[low] == 'e') || 
            (s[low] == 'E') || (s[low] == 'i') || (s[low] == 'I') || 
            (s[low] == 'o') || (s[low] == 'O') || (s[low] == 'u') || 
            (s[low] == 'U')) 
        {
            ++sum; 
        }
        sum += vowels(s,low+1,high);
    }
    return sum;
}

如果我们更深入 C++ 的方向,并使用有意义的变量名和 cmets,那么我们可以想出:

#include <iostream>
#include <cstring>

// A recursive function to count the vowels in a rang of a text
int countVowelsRecursive(char textToEvaluate[], unsigned int startPositionForEvaluation, unsigned int endPositionOfText)
{
    // Here we will store the number of vowels. We will use tail recursion 
    // So, the overall calculation will be done at the end 
    unsigned int numberOfVowelsInThisRecursion = 0u;
    
    // Now we are evaluating this character from the text
    const char currentChar = textToEvaluate[startPositionForEvaluation];
    
    // Check, for the end of recursion condition
    if (startPositionForEvaluation != endPositionOfText) {

        // Check, if it is a vowel
        if ((currentChar == 'a') || (currentChar == 'A') || (currentChar == 'e') || 
            (currentChar == 'E') || (currentChar == 'i') || (currentChar == 'I') || 
            (currentChar == 'o') || (currentChar == 'O') || (currentChar == 'u') || 
            (currentChar == 'U')) 
        {
            // Vowel found. Increase counter by one 
            ++numberOfVowelsInThisRecursion; 
        }
        // Tail recursion. Self call, starting at next position of the string
        numberOfVowelsInThisRecursion += 
            countVowelsRecursive(textToEvaluate,startPositionForEvaluation + 1, endPositionOfText);
    }
    // This will be the final result
    return numberOfVowelsInThisRecursion;
}

// We will allow a maximal input text length like this
constexpr unsigned int MaxTextLength = 500u;

// Driver code / test function
int main()
{
    // Here we will store the text from the user 
    char text[MaxTextLength]{};
    
    // Give instructions and get the text
    std::cout << "Enter a string of characters: ";
    std::cin.get(text, MaxTextLength);

    // Set text parameters for the evaluation 
    unsigned int startOfText = 0u;
    unsigned int endOfText = static_cast<unsigned int>(strlen(text));
    
    // Calculate the vowels
    unsigned int vowelCount = countVowelsRecursive(text, startOfText, endOfText);

    // Show result to user 
    std::cout << "The string contains " << vowelCount << " vowels." << std::endl;

    return 0;
}

如果我们被允许使用 C++,那么我们会这样写:

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

int main()
{
    // Give instructions and get the text
    std::cout << "\nEnter a text:\n";
    if (std::string text{}; std::getline(std::cin, text))

        // Show result to user 
        std::cout << "\n\nThe string contains " 
            << std::count_if(text.begin(), text.end(), [](const char c){ return std::isalpha(c) && ((0x208222 >> (c & 0x1f)) & 1);})
            << " vowels.\n";

    return 0;
}

玩得开心。 . .

【讨论】:

  • 感谢Armin的帮助,在阅读了您在回答中给出的两篇文章后,我现在有了更好的理解。我能够阅读并理解您的解决方案,这将有助于我完成其余的作业。谢谢。
猜你喜欢
  • 2015-03-04
  • 1970-01-01
  • 2015-07-28
  • 2022-11-25
  • 2012-10-04
  • 2013-11-26
  • 2021-05-03
  • 1970-01-01
  • 2023-02-04
相关资源
最近更新 更多