Здравствуйте, korzhik, Вы писали:
K>Здравствуйте, momart, Вы писали:
M>>Здравствуйте!
M>>Есть такая задача:
M>>строка [word1] bla-bla-bla [word2] tra-ta-ta [word1] be-be-be [word3] a-a-a [word2] и так далее. Надо оставить только первые вхождения слов в скобках:
M>>[word1] bla-bla-bla [word2] tra-ta-ta be-be-be [word3] a-a-a
K>вот мой вариант:
K>K>#include <iostream>
K>#include <string>
K>#include <vector>
K>template<typename Iterator>
K>class tokenizer
K>{
K>private:
K> tokenizer(const tokenizer&);
K> tokenizer& operator=(const tokenizer&);
K>public:
K> struct token
K> {
K> Iterator first;
K> Iterator last;
K> };
K>public:
K> tokenizer()
K> {
K> }
K> void set_str(Iterator first, Iterator last)
K> {
K> first_ = first;
K> last_ = last;
K> current_= first_;
K> }
K> token current_token()
K> {
K> return token_;
K> }
K> bool next();
K>private:
K> Iterator first_;
K> Iterator last_;
K> Iterator current_;
K> token token_;
K>};
K>//-----------------------------------------------------------------------
K>template<typename Iterator>
K>bool tokenizer<Iterator>::next()
K>{
K> if (current_ == last_)
K> {
K> return false;
K> }
K> while (current_ != last_ && *current_ != '[')
K> {
K> ++current_;
K> }
K> if (current_ == last_)
K> {
K> return false;
K> }
K> unsigned count = 0;
K> Iterator p = current_;
K> while (p != last_ && *p != ']')
K> {
K> ++p;
K> ++count;
K> }
K> ++count;
K> if (p == last_)
K> {
K> return false;
K> }
K> token_.first = current_;
K> token_.last = current_ + count;
K> current_ += count;
K> return true;
K>}
K>//-----------------------------------------------------------------------
K>int main()
K>{
K> std::string str("[word1] bla-bla-bla [word2] tra-ta-ta [word1] be-be-be [word3] a-a-a [word2]");
K> typedef tokenizer<std::string::iterator> tokenizer;
K> tokenizer tok;
K> tok.set_str(str.begin(), str.end());
K> std::vector<tokenizer::token> tokens;
K> while (tok.next())
K> {
K> tokenizer::token tk = tok.current_token();
K> std::vector<tokenizer::token>::iterator it = tokens.begin();
K> std::vector<tokenizer::token>::iterator last = tokens.end();
K> for (;it != last; ++it)
K> {
K> if (std::distance(it->last, it->first) == std::distance(tk.last, tk.first) &&
K> std::string(it->first, it->last) == std::string(tk.first, tk.last))
K> {
K> tok.set_str(str.erase(tk.first, tk.last), str.end());
K> }
K> }
K> tokens.push_back(tok.current_token());
K> }
K> std::cout << str << std::endl;
K>}
K>
K>кто будет критиковать код сразу сообщаю, что я писал его уставший и ,честно говоря, немного выпивший, так что особо не ругайте.
И все-таки покритикуем. Правда не код, а алгоритм. Здесь все хорошо за исключением квадратичности. Лучше вместо внутреннего цикла использовать HashSet для проверки того, что такой тоукен уже встречался. Алгоритм будет работать в N раз быстрее (где N-количество слов в []).
Можно подумать и о том, чтобы заменить удаление во внутреннем цикле на добавление к результирующей строке. В крайнем случае сейчас мы произведем N-1 удаление, при этом всего произойдет N-1 копирование ВСЕЙ оставшейса строки.