Проблема с вашим кодом заключается в том, что он пытается сделать две вещи одновременно:
- решает, находится ли символ в выбранном наборе или нет
- на основе этих решений вычислите запрошенные числа.
В целях удобства чтения часть 2 должна использовать часть 1, а не включать ее.
Это тем более, что вы, похоже, используете очень длинные строки кода. Таким образом, читатель должен использовать горизонтальный ползунок, и в этом случае невозможно одновременно увидеть конец длинной строки кода и более короткие строки кода, которые следуют. Это затрудняет поиск ошибок.
Поскольку это C ++, следовательно, объектно-ориентированное программирование, мы можем делегировать решение о том, является ли символ частью выбранных, какому-то специальному объекту, например, CharTester класс. Объект CharTester
получает во время создания строку, содержащую все «выбранные» символы. Таким образом, алгоритм, который вычисляет запрошенные числа, может быть намного короче.
Объект CharTester может делегировать всю тяжелую работу в строку Метод поиска .
Источниккод для создания этого вспомогательного объекта будет выглядеть, например, так:
static const char EnglishConsonantList[] =
"bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ";
CharTester cht(EnglishConsonantList);
Хорошая вещь с вышеуказанным стилем кодирования состоит в том, что, если какой-то официальный Грамматический комитет решит, что с этого момента Y будет согласной вместогласных, необходимые изменения в вашем исходном коде минимальны. И ваш учитель, возможно, не выше сказанного, например, « Теперь, когда вы сделали это для согласных, пожалуйста, сделайте это для гласных. » - это, чтобы заставить вас понять, насколько гибок ваш исходный код именно,
Таким образом, мы приводим следующий код, где наиболее интересной является функция goodCharCounts()
, которая возвращает объект std::vector
, содержащий запрошенные числа.
#include <vector>
#include <string>
#include <iostream>
using std::string;
using std::cout;
class CharTester {
public:
CharTester(const string& list) : goodCharList(list)
{};
bool isGoodChar(char ch) const;
private:
string goodCharList; // list of "chosen" characters
};
bool CharTester::isGoodChar(char ch) const
{
// hard work there:
bool isGood = (goodCharList.find(ch) != string::npos);
return isGood;
}
// THE ALGORITHM:
std::vector<int> goodCharCounts(const CharTester& cht, const std::string& str)
{
std::vector<int> posVec;
int counter = 0;
// loop on all characters of the input string
for (char ch : str) {
bool isGood = cht.isGoodChar(ch);
if (isGood) {
counter++;
}
else if (counter > 0) {
// end of current "chosen" group, so must register it
posVec.push_back(counter);
counter = 0;
}
}
if (counter > 0) {
// register last "chosen" group
posVec.push_back(counter);
counter = 0;
}
return posVec;
}
Мы можемпротестируйте алгоритм, добавив следующую основную программу:
// test one string and print the results:
void doUnitTest(const CharTester& cht, const string& str)
{
std::vector<int> counts = goodCharCounts(cht, str);
cout << str << " --> ";
// loop on all numbers:
for (int n : counts) {
cout << n << ' ';
}
cout << std::endl;
}
// possible lists of "chosen" characters :
//-- const wchar_t FrenchVowelList[] = L"AEIOUYÀÂÉÊÈÏÔÛÙaeiouyàâéêèïôûù";
//-- const wchar_t RussianVowelList[] = L"АЕИОЭЙЫЮЯЁУаеиоэйыюяёу";
static const char EnglishVowelList[] = "aeiouyAEIOUY";
static const char EnglishConsonantList[] =
"bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ";
int main()
{
CharTester cht(EnglishConsonantList);
doUnitTest(cht, "computers");
doUnitTest(cht, "Some computers are cheap. Aeiuo-XrZT.");
return EXIT_SUCCESS;
}
Выполнение:
computers --> 1 2 1 2
Some computers are cheap. Aeiuo-XrZT. --> 1 1 1 2 1 2 1 2 1 4
Примечание:
Выше я использовал тип char
исвязанный классический тип C ++ string
, потому что именно так вы и поступаете в своем коде. Однако для производственного кода вам, вероятно, придется использовать более общие типы wide wchar_t
и wstring
, чтобы разрешить использование символов, не относящихся к ASCII, таких как á, à, ê, ẞ. и т. д. (символы Юникода).