Вывести только те слова сообщения, которые встречаются в нем ровно один раз
Дано предложение, допустим "Hello, world world!", программа должна вывести "Hello". Не могу понять в чем ошибка.
#include <iostream>
#include <string>
using namespace std;
void main() {
string str, word, divider = "!?., ";
string::size_type k = 0, pos = 0;
cout << "Enter string: ";
getline(cin, str);
k = str.find_first_of(divider, pos);
while (k != string::npos) {
word = str.substr(pos, k - pos);
if (ispunct(str[k])) {
pos = k + 2;
}
else {
pos = k + 1;
}
if (str.find(word, pos) == string::npos) {
cout << word << endl;
}
}
k = str.find_first_of(divider, pos);
system("pause");
}
Ответы (2 шт):
Был использован STL. Алгоритм не самый эффективный, но понять его вам будет доступнее
lexemes содержит все лексемы, которые вы ввели из консольного ввода.
Далее просто считается сколько раз каждая лексема встречается во множестве лексем. Если она встречается не один раз, то она просто не добавляется в результат
#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
#include <vector>
#include <iterator>
int main() {
std::string str, word, separator = "!?., ";
std::string::size_type k = 0, pos = 0;
std::cout << "Enter string: ";
std::getline(std::cin, str);
std::istringstream strStream(str);
std::vector<std::string> lexemes;
std::copy(std::istream_iterator<std::string>(strStream),
std::istream_iterator<std::string>(),
std::back_inserter(lexemes));
std::sort(lexemes.begin(), lexemes.end());
std::vector<std::string> result;
for (const auto& lexem : lexemes) {
if (std::count(lexemes.begin(), lexemes.end(), lexem) == 1) {
result.emplace_back(lexem);
}
}
return 0;
}
Я думаю, для подобных задач в первую очередь нужна простая функция, выбирающая слова (с управлением возможными разделителями) в строке и предоставляющая возможность анализировать разделители как до, так и после каждого слова.
В отличии от, скажем, известной функции strtok() она не портит исходную строку и позволяет анализировать символы вокруг найденного слова.
Попробуйте
// returns word length or 0
// if the word found, put pointer to it to `*word`
size_t
get_word (const char *str, const char **word, const char *sep)
{
size_t begin = strspn(str, sep);
if (!str[begin])
return 0;
*word = (str + begin);
return strcspn(str + begin, sep);
}
Пример ее использования для печати слов в строке
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
print_word (const char *w, int l)
{
while (l--)
putchar(*w++);
}
int
main (int ac, char *av[])
{
char str[] = " a ab. ab acd? x!!! zzz";
const char *word;
int l;
for (const char *p = str; l = get_word(p, &word, " .,:;!?-"); p = word + l) {
print_word(word, l);
if (word[l] && strchr(".?!", word[l]))
puts(" (end of sentence)");
else
puts("");
}
}
Компилируем и запускаем
avp@avp-desktop:~/avp/hashcode$ g++ t-getword.c && ./a.out
a
ab (end of sentence)
ab
acd (end of sentence)
x (end of sentence)
zzz
avp@avp-desktop:~/avp/hashcode$
Надеюсь, поиск дубликатов вы сможете сделать сами.