Я знаю, что следующее будет трудно переварить. В любом случае, я хочу показать его, потому что это «более современное решение C ++».
Итак, сначала я подумаю и разработаю алгоритм, а затем использую элементы moderen C ++ для его реализации.
Сначала к алгоритму. Если мы используем код ASCII для кодирования букв, то мы увидим следующее:
Мы увидим, что код ASCII для заглавных и строчных букв просто отличаются младшими 5 битами. Итак, если мы замаскируем код ASCII с 0x1F, то есть char c{'a'}; unsigned int x{c & 0x1F}
, мы получим значения от 1 до 26. Таким образом, мы можем вычислить 5-битное значение для каждой буквы. Если мы теперь помечаем все гласные с 1, мы можем построить двоичное число, состоящее из 32 бит (без знака int) и установить бит в каждой позиции, где гласная истинна. Затем мы получаем что-то вроде
Bit position
3322 2222 2222 1111 1111 1100 0000 0000
1098 7654 3210 9876 5432 1098 7654 3210
Position with vowels:
0000 0000 0010 0000 1000 0010 0010 0010
Это число может быть преобразовано в 0x208222. И если теперь мы хотим выяснить, является ли буква (независимо от того, является ли она заглавной или прописной буквой) гласной, тогда мы замаскируем ненужные биты из символа (C & 1F) и сместим двоичное число вправо. столько места, сколько получен буквенный код. Если тогда бит установлен в позиции LSB, то у нас есть гласный. Это ноу-хау уже десятки лет.
Ага. Это не так просто, но будет работать для букв в кодировке ASCII.
Далее мы создадим лямбду, которая будет читать строку, состоящую исключительно из букв алфавита и считающую гласные. Что не является гласным, это согласный (потому что у нас есть только буквы).
Затем мы используем современные элементы C ++ для вычисления запрошенных значений:
В результате получается некоторый элегантный код C ++ с только несколько строк.
Пожалуйста, смотрите
#include <utility>
#include <algorithm>
#include <string>
#include <iostream>
#include <fstream>
#include <cctype>
int main() {
// Lambda for counting vowels and consonants in a string consisting of letters only
auto countVowelsAndConsonants = [](std::string& s) -> std::pair<size_t, size_t> {
size_t numberOfVowels = std::count_if(s.begin(), s.end(), [](const char c) { return (0x208222 >> (c & 0x1f)) & 1; });
return { numberOfVowels, s.size() - numberOfVowels }; };
// Inform the user what to do: He should enter a valid filename
std::cout << "\nCount vowels and consonants.\n\nEnter a valid filename with the source text: ";
// Read the filename
if (std::string fileName{}; std::cin >> fileName) {
// Now open the file and check, if it could be opened
if (std::ifstream sourceFileStream(fileName); sourceFileStream) {
// Read the complete source text file into a string. But only letters
std::string completeSourceTextFile{};
std::copy_if(std::istreambuf_iterator<char>(sourceFileStream), {}, std::back_inserter(completeSourceTextFile), std::isalpha);
// Now count the corresponding vowels and consonants
const auto [numberOfVowels, numberOfConsonants] = countVowelsAndConsonants(completeSourceTextFile);
// Show result to user:
std::cout << "\n\nNumber of vowels: " << numberOfVowels << "\nNumber of consonants: " << numberOfConsonants << "\n\n";
}
else {
std::cerr << "\n*** Error. Could not open source text file '" << fileName << "'\n\n";
}
}
else {
std::cerr << "\n*** Error. Could not get file name for source text file\n\n";
}
return 0;
}
Обратите внимание:
Существует миллион возможных решений. Каждый может делать то, что он хочет.
Некоторые люди все еще находятся в режиме C -Style, а другие любят больше программировать на C ++