Рекурсивная функция, подсчитывающая гласные

#c

Вопрос:

У меня есть задание,в котором меня просят «Написать рекурсивную функцию гласных(s,низкий, высокий), которая возвращает количество гласных во входной строке 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);
    }
}
 

Комментарии:

1. if (s[low] == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U') — Это не то, как вы сравниваете ценность с несколькими предметами. В книге C , которую вы используете, как в книге показано, как это делается? Начните с простого — как бы вы сравнили s[low] оба A и a ?

2. Вы получаете бесконечную рекурсию и неопределенное поведение.

3. Ваша vovels реализация функции не соответствует объявлению. Проверьте первый параметр.

4. Не используйте строковый тип C — Использование std::string в любом случае не имело бы значения. Ошибки, которые вы совершаете, будут происходить с использованием или без использования std::string .

5. Это не решает вопроса, но эти два вызова vowels внутри vowels функции одинаковы (и имеют одну и ту же ошибку). Когда вы увидите два одинаковых фрагмента кода, посмотрите, сможете ли вы написать его только один раз. В этом случае я бы сделал что-то вроде bool is_vowel = /* check whether s[low] is a vowel */ . Тогда возвращаемое значение просто is_vowel vowels(s, low 1, high); .

Ответ №1:

Здесь мы говорим о так называемой XY-проблеме.

Учитель хочет охватить рекурсивные функции. Подсчет гласных-это просто какой-то шум. К сожалению, данный пример является плохим, потому что он может быть реализован гораздо лучше при итеративном подходе.

Рекурсия просто добавляет ненужную сложность во времени и пространстве. Таким образом, производительность во всех случаях хуже по сравнению с простым циклом.

Если учитель хочет, чтобы вы узнали о рекурсии, вы можете сначала взглянуть на это описание или на тот более практический пример.

Прочитав это, вы поймете, что цикл можно просто преобразовать в рекурсивную функцию.

Я не уверен, почему существует параметр «низкий» и «высокий». Возможно, из-за использования 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]) amp;amp; ((0x208222 >> (s[low] amp; 0x1f)) amp; 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 и будем использовать значимые имена переменных и комментарии, то мы могли бы прийти к этому:

 #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 << "nnThe string contains " 
            << std::count_if(text.begin(), text.end(), [](const char c){ return std::isalpha(c) amp;amp; ((0x208222 >> (c amp; 0x1f)) amp; 1);})
            << " vowels.n";

    return 0;
}
 

Получайте удовольствие . . .

Комментарии:

1. Спасибо вам за помощь, Армин, прочитав две статьи, которые вы дали в своем ответе, я теперь лучше понимаю. Я могу прочитать и понять ваши решения, и это поможет мне в выполнении остальной части задания. Спасибо.