Форум программистов, компьютерный форум CyberForum.ru

Как исправить код с istream_iterator? - C++

Восстановить пароль Регистрация
 
anubis1768
4 / 4 / 0
Регистрация: 23.02.2013
Сообщений: 151
11.01.2014, 21:16     Как исправить код с istream_iterator? #1
Как исправить этот код, чтобы ввод заканчивался при вводе слова quit? Можно ли сделать с итераторами или уже нужно в простом цикле ввод проверять?

C++
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
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
 
using namespace std;
 
typedef istream_iterator< string > is;
typedef ostream_iterator< string > os;
 
vector< string > names;
 
void record(const string &s)
{
    names.push_back(s); 
}
 
int main()
{
    for_each(is(cin), is(), record);
    sort(names.begin(), names.end());
    names.erase(unique(names.begin(), names.end()), names.end());
    copy(names.begin(), names.end(), os(cout, "\n"));
    return 0;   
}
Добавлено через 14 минут
ап..
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
11.01.2014, 21:47     Как исправить код с istream_iterator? #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <algorithm>
...
bool pred(const string &s)
{
    if (s == "quit")
        return true;
        
    names.push_back(s); 
    return false;
}
 
int main()
{
    find_if(is(cin), is(), pred);
    ...
outoftime
║XLR8║
 Аватар для outoftime
505 / 427 / 33
Регистрация: 25.07.2009
Сообщений: 2,297
11.01.2014, 22:52     Как исправить код с istream_iterator? #3
anubis1768, если надо чисто ввод делай так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
 
typedef std::istream_iterator<std::string> is;
typedef std::ostream_iterator<std::string> os;
 
int main()
{
    std::vector<std::string> names;
    std::copy(is(std::cin), is(), std::back_inserter(names));
 
    std::sort(names.begin(), names.end());
    names.erase(std::unique(names.begin(), names.end()), names.end());
    std::copy(names.begin(), names.end(), os(std::cout, "\n"));
}
Вместо функций-предикатов удобнее лямбды использовать
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
 
typedef std::istream_iterator<std::string> is;
typedef std::ostream_iterator<std::string> os;
 
int main()
{
    std::vector<std::string> names;
    std::find_if(is(std::cin), is(), [&names](const std::string &str) {
        return str == "quit" ? true : (names.push_back(str), false);
    });
    std::sort(names.begin(), names.end());
    names.erase(std::unique(names.begin(), names.end()), names.end());
    std::copy(names.begin(), names.end(), os(std::cout, "\n"));
}
Добавлено через 6 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
 
typedef std::istream_iterator<std::string> is;
typedef std::ostream_iterator<std::string> os;
 
int main()
{
    std::vector<std::string> names;
    std::find_if(is(std::cin), is(), [&names](const std::string &str) {
        return str == "quit" ? true : (names.push_back(str), false);
    });
    std::sort(names.begin(), names.end());
    names.resize(std::distance(names.begin(), std::unique(names.begin(), names.end())));
    std::copy(names.begin(), names.end(), os(std::cout, "\n"));
}
Я std::erase заменил на std::vector::resize т.к. он должен работать быстрее, тем более что тебе надо удалить ВЕСЬ хвост.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4927 / 2670 / 243
Регистрация: 29.11.2010
Сообщений: 7,429
12.01.2014, 01:45     Как исправить код с istream_iterator? #4
Можно использовать std::unique_copy
outoftime
║XLR8║
 Аватар для outoftime
505 / 427 / 33
Регистрация: 25.07.2009
Сообщений: 2,297
12.01.2014, 01:52     Как исправить код с istream_iterator? #5
MrGluck, ну, как бы, оно так и есть (:
Цитата Сообщение от outoftime Посмотреть сообщение
std::sort(names.begin(), names.end());
Добавлено через 53 секунды

Не по теме:

MrGluck, я обычно пишу "не туда" (:



Добавлено через 6 минут
Цитата Сообщение от MrGluck Посмотреть сообщение
Можно использовать std::unique_copy
Мне кажется будет тоже. std::unique меняет местами элементы множества а std::unique_copy копирует уникальные в новое, разницы никакой, если использовать на одном контейнере, иначе будут накладные расходы памяти. Единственное я не нашел пока инфы о том надо ли сортировать контейнер перед вызовом unique_copy или unique.

UPD:
судя по реализации std::unique_copy можно использовать если в качестве выходного контейнера задать входной, но это лишний параметр, так что std::unique получше будет (:
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4927 / 2670 / 243
Регистрация: 29.11.2010
Сообщений: 7,429
12.01.2014, 02:11     Как исправить код с istream_iterator? #6
Цитата Сообщение от outoftime Посмотреть сообщение
Единственное я не нашел пока инфы о том надо ли сортировать контейнер перед вызовом unique_copy или unique.
если есть необходимость в сортировке - то только через std::sort

Добавлено через 12 минут
да и вообще сама сортировка вектора для вывода уникальных элементов должна настораживать, std::set же есть.
C++
1
2
3
4
5
6
7
8
9
10
#include <algorithm>
#include <iostream>
#include <set>
 
int main()
{
    std::set<std::string> names;
    for (std::string word; std::cin >> word && word != "quit"; names.insert(word));
    std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
просто и для с++98 тоже подходит

Добавлено через 3 минуты
outoftime, я имел ввиду это:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
 
typedef std::istream_iterator<std::string> is;
typedef std::ostream_iterator<std::string> os;
 
int main()
{
    std::vector<std::string> names;
    std::find_if(is(std::cin), is(), [&names](const std::string &str) {
        return str == "quit" ? true : (names.push_back(str), false);
    });
    std::sort(names.begin(), names.end());
    std::unique_copy(names.begin(), std::unique(names.begin(), names.end()), os(std::cout, "\n"));
}
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.01.2014, 02:16     Как исправить код с istream_iterator? #7
еще можно в set сувать. все сразу будет сортированным и уникальным:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <string>
 
typedef std::istream_iterator<std::string> is;
typedef std::ostream_iterator<std::string> os;
 
int main()
{
  std::set<std::string> names;
  std::find_if(is(std::cin), is(), [&names](const std::string &str) {
      return str == "quit" ? true : (names.insert(str), false);
  });
  std::copy(names.begin(), names.end(), os(std::cout, "\n"));
  return 0;
}
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4927 / 2670 / 243
Регистрация: 29.11.2010
Сообщений: 7,429
12.01.2014, 02:18     Как исправить код с istream_iterator? #8
опечатка, это:
C++
1
std::unique_copy(names.begin(), names.end(), os(std::cout, "\n"));
либо это:
C++
1
std::copy(names.begin(), std::unique(names.begin(), names.end()), os(std::cout, "\n"));
Добавлено через 1 минуту
Цитата Сообщение от DU Посмотреть сообщение
еще можно в set сувать. все сразу будет сортированным и уникальным:
ну как бы я уже написал об этом выше
Цитата Сообщение от MrGluck Посмотреть сообщение
да и вообще сама сортировка вектора для вывода уникальных элементов должна настораживать, std::set же есть.
C++
1
2
3
4
5
6
7
8
9
#include <algorithm>
#include <iostream>
#include <set>
int main()
{
* * std::set<std::string> names;
* * for (std::string word; std::cin >> word && word != "quit"; names.insert(word));
* * std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.01.2014, 02:19     Как исправить код с istream_iterator? #9
не заметил. повторение - мать ученья
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4927 / 2670 / 243
Регистрация: 29.11.2010
Сообщений: 7,429
12.01.2014, 02:20     Как исправить код с istream_iterator? #10
кстати, тело л-функции можно упростить:
C++
1
return (str == "quit") || (names.insert(str), false);
Хотя тут есть небольшое сомнение в постоянстве поведения
gray_fox
12.01.2014, 20:00
  #11

Не по теме:

Цитата Сообщение от MrGluck Посмотреть сообщение
да и вообще сама сортировка вектора для вывода уникальных элементов должна настораживать, std::set же есть.
Почему? Сложность такая же, только кода больше писать)

MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4927 / 2670 / 243
Регистрация: 29.11.2010
Сообщений: 7,429
12.01.2014, 20:33     Как исправить код с istream_iterator? #12
Цитата Сообщение от gray_fox Посмотреть сообщение
Почему?
Цитата Сообщение от gray_fox Посмотреть сообщение
Сложность такая же, только кода больше писать)
сам себе и ответил

кстати, где-то видел тесты и сравнение std::vector + std::sort и std::set по времени работы в зависимости от количества элементов - само собой результаты разные.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.01.2014, 20:41     Как исправить код с istream_iterator?
Еще ссылки по теме:

Шаблоны функций как исправить код? C++
C++ Вроде простой код, но съедает 1,5 гб оперативы, как это исправить?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
anubis1768
4 / 4 / 0
Регистрация: 23.02.2013
Сообщений: 151
12.01.2014, 20:41  [ТС]     Как исправить код с istream_iterator? #13
MrGluck, на stackoverflow я такие тесты видел. std::set на порядок быстрее для больших последовательностей
Yandex
Объявления
12.01.2014, 20:41     Как исправить код с istream_iterator?
Ответ Создать тему
Опции темы

Текущее время: 01:31. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru