#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. Спасибо вам за помощь, Армин, прочитав две статьи, которые вы дали в своем ответе, я теперь лучше понимаю. Я могу прочитать и понять ваши решения, и это поможет мне в выполнении остальной части задания. Спасибо.