-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.cpp
190 lines (151 loc) · 7.37 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <iostream>
#include <string>
#include <cstddef>
#include <windows.h>
using namespace std;
// Переход на кириллицу:
void cyrillic() {
// Эти строки нужны для правильного отображения кириллицы:
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
// Также надо изменить шрифт в консоли на Lucida Console.
// Для замены шрифта кликаете правой кнопкой на надписи «Командная строка» окна консоли.
// В открывшемся меню выбираете «Свойства».
// В появившемся окне выбираете вкладку «Шрифт» и там выбираете «Lucida Console».
}
// Функция для определения, является ли символ буквой.
// Возвращает true, если является и false в ином случае.
bool isletter(char ch) {
return isalpha(ch)
|| (ch >= 'а' && ch <= 'я') || (ch >= 'А' && ch <= 'Я');
}
// Функция для поиска слов в строке.
// Возвращает true, если слово найдено и false в ином случае.
// Вход:
// str - строка в которой надо искать слова.
// start - индекс с которого надо начинать поиск.
// finish - индекс дальше которого искать не нужно.
// Выход:
// word_start_idx - индекс первой буквы слова.
// word_end_idx - индекс последней буквы слова.
bool find_word(string const& str, size_t start, size_t finish, size_t& word_start_idx, size_t& word_end_idx) {
size_t len = str.length();
bool word_start = false;
bool word_end = true;
for (size_t i = start; i <= finish && i >= 0 && i < len; ++i) {
char ch = str.at(i);
// Захват первой буквы слова:
if (word_end && isletter(ch)) {
word_start_idx = i;
word_start = true;
word_end = false;
}
// Захват последней буквы слова:
if (word_start) {
if (isspace(ch) || ispunct(ch) || iscntrl(ch)) {
word_end_idx = i - 1;
word_end = true;
} else if (isletter(ch) && i == len - 1) {
word_end_idx = i;
word_end = true;
}
}
// Если есть первая и последняя буквы слова, то возвращаем результат:
if (word_start && word_end) {
word_start = false;
return true;
}
}
return false;
}
// Функция переводит символ в нижний регистр:
char to_lower_letter(char ch) {
if (ch >= 'а' && ch <= 'я') {
return ch;
} else if (ch >= 'А' && ch <= 'Я') {
return 'а' + (ch - 'А');
} else {
return tolower(ch);
}
}
// Функция для проверки равенства строк, независимо от их регистра.
bool iequals(const string& a, const string& b) {
unsigned int sz = a.size();
if (b.size() != sz)
return false;
for (unsigned int i = 0; i < sz; ++i)
if (to_lower_letter(a[i]) != to_lower_letter(b[i]))
return false;
return true;
}
// Функция для подсчёта количества раз, которое слово встречается в строке.
size_t count_word(string const& str, size_t start, size_t finish, string const& word) {
size_t cnt = 0; // количество раз, которое слово встречается в строке.
size_t word_start_idx; // индекс первой буквы слова.
size_t word_end_idx; // индекс последней буквы слова.
// Обход в цикле всех слов:
while (find_word(str, start, finish, word_start_idx, word_end_idx)) {
// Извлечение слова из строки:
string next_word = str.substr(word_start_idx, word_end_idx - word_start_idx + 1);
// Сравнение очередного слова с заданным словом:
if (iequals(word, next_word)) {
++cnt;
}
start = word_end_idx + 1; // передвижение вперёд левой границы поиска слов.
}
return cnt;
}
// Функция для удаления одинаковых слов.
string delete_same_words(string const& str) {
string result; // переменная в которой будет конечный результат.
size_t len = str.length(); // длина строки.
size_t start = 0; // индекс с которого надо начинать поиск слов.
size_t finish = len - 1; // индекс дальше которого искать слова не нужно.
size_t word_start_idx; // индекс первой буквы слова.
size_t word_end_idx; // индекс последней буквы слова.
string word; // слово.
size_t cnt; // количество раз, которое слово встречается в строке.
bool skip_word = false; // флаг пропуска слова.
size_t i = 0;
// Обход в цикле всех слов:
while (find_word(str, start, finish, word_start_idx, word_end_idx)) {
if (skip_word) {
i = word_start_idx;
}
// Вывод символов перед найденным словом:
while (i < word_start_idx) {
result += str.at(i++);
}
// Извлечение слова из строки:
word = str.substr(word_start_idx, word_end_idx - word_start_idx + 1);
// Подсчёт количества встреч слова в строке:
cnt = count_word(str, 0, len - 1, word);
if (cnt == 1) { // если слово встречается только 1 раз, то:
result.append(word); // добавляем его в результирующую строку.
skip_word = false; // опускаем флаг пропуска слова.
} else {
skip_word = true; // поднимае флаг пропуска слова.
}
start = word_end_idx + 1; // передвижение вперёд левой границы поиска слов.
i = start;
}
// Вывод всего, что осталось за последним словом:
while (i < len) {
result += str.at(i++);
}
return result;
}
// Главная функция:
int main(int argc, char** argv) {
cyrillic(); // переход на кириллицу.
// Заголовок программы:
cout << "// Удаление из предложения слов, которые встретились в нём более 1 раза.\n\n";
// Ввод входной строки:
string str = "";
cout << "Пожалуйста, введите предложение:\n>";
getline(cin, str);
cout << "Вы ввели строку: \"" << str << "\"\n\n"; // проверка ввода.
cout << "Результат:\n" << delete_same_words(str) << endl << endl;
system("pause"); // пауза перед выходом из программы.
return 0;
}