Есть некоторое предложение на неизвестном языке. Посчитать количество слов в нем. Буквами алфавита в неизвестном языке являются буквы латинского алфавита и арабские цифры. Гарантируется, что других символов, кроме пробелов и знаков препинания в предложении нет.
Тестирование
№ |
Входные данные |
Выходные данные |
1 |
Hello, world! |
2 |
2 |
War is Peace. Freedom is Slavery. Ignorance is Strength. |
9 |
3 |
— «4», «8», <15>; (16), {23}, [42]!? |
6 |
4 |
A flock of sparrows – some of them juveniles – alighted and sang. |
11 |
5 |
A mean Earth solar day is approximately 24 hours, whereas a mean Martian ‘sol’ is 24 hours, 39 minutes, and 35.244 seconds. |
22 |
6 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. |
19 |
Код
Реализация с помощью посимвольного считывания
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
#include <iostream> using namespace std; // Проверяет, принадлежит ли символ алфавиту bool AllowedSign(char x) { return ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z'))?1:0; } int main() { char x; int count = 0; // Счетчик слов в предложении bool wordBegin = true; // Будет ли следующий считанный символ, принадлежащий алфавиту, началом нового слова while(EOF != (x = getchar())) { if(AllowedSign(x) && wordBegin) { // Если текущий символ принадлежит алфавиту и ожидается новое слово count++; wordBegin = false; // Указываем, что последующие находимые символы алфавита не будут началом слова } else if(x == ' ') // Если текущий символ - пробел wordBegin = true; // Указываем для следующей итерации, что текущее слово "закончилось" и ожидается новое } cout << count; return 0; } |
Реализация с помощью строк c-string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#include <iostream> #include <cstring> using namespace std; // Проверяет, принадлежит ли символ алфавиту bool AllowedSign(char x) { return ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z'))?1:0; } int main() { const int size = 500; int count = 0; // Счетчик слов в предложении char word[size]; while(cin >> word) { bool isWord = false; // По умолчанию считаем, что считанная последовательность символов словом не является for(int i = 0; i < strlen(word) && !isWord; i++) // Проверяем символы массива, пока не дойдем до его конца или не убедимся, что считанная последовательность ялвяется словом if(AllowedSign(word[i])) { // Если текущий символ принадлежит алфавиту count++; isWord = true; // Указываем, что последовательность является словом } } cout << count; return 0; } |
Решение
Так как предложение задается на неизвестном языке, максимально обобщим определение слова. Будем считать его последовательностью символов, которая удовлетворяет следующим двум условиям:
- Слева и справа она ограничена пробелами, началом предложения или концом предложения. При этом знаки препинания, стоящие непосредственно после слова или перед ним, также будут считаться его частью, однако на подсчет количества слов это никак не повлияет.
- Последовательность содержит хотя бы один символ, входящий в алфавит. Такое ограничение отсеет знаки препинания, отбивающиеся с двух сторон пробелами (такие как тире), но при этом позволит учитывать слова, содержащие в себе неалфавитные символы, к примеру, дефис или апостроф.
Теперь перейдем к практическому решению задачи.
Реализация с помощью посимвольного считывания
Поскольку в условии задачи не оговариваются максимальные длины слов или предложений, предпочтительней будет использовать именно этот способ.
Для решения задачи этим методом воспользуемся функцией
bool AllowedSign(char x), возвращающей значение
true, если переданный ей символ принадлежит алфавиту неизвестного языка, и объявим логическую переменную
wordBegin, определяющую, будет ли следующий считанный символ алфавита началом нового слова, и присвоим ей до начала выполнения цикла посимвольного считывания значение
true. Сам цикл будет выполняться до тех пор, пока не будет прочитан весь входной поток:
|
bool wordBegin = true; while(EOF != (x = getchar())) |
При этом на каждой его итерации будут возможны, в зависимости от текущего символа и значения переменной
wordBegin, следующие два варианта действий. Если считанный символ принадлежит алфавиту и при этом ожидается новое слово (
wordBegin = true), инкрементируем счетчик слов
count и присваиваем
wordBegin значение
false. С этого момента и до тех пор, пока не будет достигнут конец слова, все последующие считываемые символы алфавита не будут влиять на счетчик:
|
if(AllowedSign(x) && wordBegin) { count++; wordBegin = false; } |
Если же считанный символ — пробел, присваиваем
wordBegin значение
true. Достигнут конец текущего слова, и теперь следующий алфавитный символ, если он встретится в потоке, приведет к инкрементированию счетчика слов, так как будет принадлежать уже другому слову:
|
else if(x == ' ') wordBegin = true; |
Как видно, неалфавитные символы (знаки препинания) игнорируются и на подсчет слов никак не влияют. Наконец, после того, как будет прочитан весь входной поток, выводится значение счетчика слов
count, что и есть ответом на поставленный вопрос задачи:
Реализация с помощью строк c-string
Как и в предыдущем варианте решения, воспользуемся функцией
AllowedSign, определяющей принадлежность символа алфавиту, а также объявим переменную
bool isWord, отвечающую за то, является ли проверяемая последовательность символов словом неизвестного языка. Тогда суть метода будет заключаться в считывании из входного потока последовательностей символов и проверке того, являются ли они словами. В основе метода лежит цикл, считывающий из входного потока «потенциальные слова» до тех пор, пока это возможно:
После считывания последовательности символов присваиваем переменной
isWord значение
false, изначально считая, что эта последовательность словом не является:
Затем поочередно проверяем символы последовательности до тех пор, пока
isWord сохраняет значение
false, или пока не дойдем до конца этой последовательности. Если в процессе проверки окажется, что очередной проверяемый символ принадлежит алфавиту, инкрементируем счетчик слов
count и указываем, что последовательность является словом, переходя таким образом к проверке следующего «потенциального слова» в предложении, если таковые имеются:
|
for(int i = 0; i < strlen(word) && !isWord; i++) if(AllowedSign(word[i])) { count++; isWord = true; } |
Наконец, как и в первом случае, выводим количество найденных слов:
Ссылки
Условие задачи на E-Olymp;
Коды программ на Ideone.com: посимвольное считывание, строки c-string;
Подтверждение решения на E-Olymp.
Для отправки комментария необходимо войти на сайт.