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

Объединение двух контейнеров - C++

Восстановить пароль Регистрация
 
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
21.10.2013, 17:04     Объединение двух контейнеров #1
функция программы, которая производит логическое объединение двух контейнеров. дело в том, что переменная check инициализируется абы как - если вдруг первая переменная контейнера А встречается в В, то там есть нормальная переменная. Если нет, то проверка
C++
1
if (check != b.end ())
ступорит программу, а не выдаёт false, как должна то делать. Если это важно, то в функцию передаю два вектора, которые являются подмножествами другого (один с нечетными элементами, другой с кратными 5-ти).
Кликните здесь для просмотра всего текста
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
void unite (vector <int> & a, vector <int> & b, set <int> & r)
{
    vector <int>::iterator temp = a.begin ();
    vector <int>::iterator check;
    while (temp != a.end ())
    {
        check = find (b.begin (), b.end (), *temp);
        if (check != b.end ())
        {
            r.insert (*temp);
        }
        ++temp;
    }
    temp = b.begin ();
    while (temp != b.end ())
    {
        check = find (a.begin (), a.end (), *temp);
        if (check != a.end ())
        {
            r.insert (*temp);
        }
    }
    ++temp;
}
Миниатюры
Объединение двух контейнеров  
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
21.10.2013, 17:23     Объединение двух контейнеров #2
А покажи использование, а? Ибо у меня все работает. тут кстати ты опечатался:

Цитата Сообщение от tramp_1-3 Посмотреть сообщение
while (temp != b.end ())
* * {
* * * * check = find (a.begin (), a.end (), *temp);
* * * * if (check != a.end ())
* * * * {
* * * * * * r.insert (*temp);
* * * * }
* * }
* * ++temp;
++temp не там стоит, где должно. Да, и куча пробелов в самых неподходящий места, этим не злоупотребляй(set <int> & => set<int>&, b.begin () => b.begin())). А так вполне себе приятно читать)
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
21.10.2013, 17:31  [ТС]     Объединение двух контейнеров #3
Цитата Сообщение от monolit Посмотреть сообщение
++temp не там стоит, где должно. Да, и куча пробелов в самых неподходящий места, этим не злоупотребляй(set <int> & => set<int>&, b.begin () => b.begin())). А так вполне себе приятно читать)
а вообще, перед этим написал, что vector <int> итератор не приращиваемый! что за итератор надо для него выбрать тогда из файла iterator? Спасибо, а о каких пробелах идёт речь? О тех, что перед операторами или внутри скобок? Если первые, то это Dev-C++ сам ставит вместо табуляции. А внутри скобок постарался сделать код читабельнее.
Полный код:
Кликните здесь для просмотра всего текста
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
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
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
#include <iterator>
#include <set>
 
using namespace std;
const int SIZE = 10;
bool isOdd (int i);
bool isEven (int i);
bool isMultipleTo5 (int i);
void fill (vector <int> &, vector <int> &, bool (*check) (int));
void unite (vector <int> &, vector <int> &, set <int> &);
 
int main ()
{
    srand (time (0));
    vector <int> seq (SIZE);
    for (int i = 0; i < SIZE; i++)
    {
        seq [i] = rand () % 50 + 50;
    }
    cout << "Source array:\n";
    ostream_iterator <int, char> out (cout, " ");
    copy (seq.begin (), seq.end (), out);
    vector <int> multipleTo5;
    vector <int> odd;
    bool (*check) (int i);
    check = isOdd;
    fill (seq, odd, check);
    check = isMultipleTo5;
    fill (seq, multipleTo5, check);
    cout << "\nOdd array:\n"; 
    copy (odd.begin (), odd.end (), out);
    cout << "\nMultipe to 5 array:\n"; 
    copy (multipleTo5.begin (), multipleTo5.end (), out);
    set <int> result;
    unite (odd, multipleTo5, result);
    cout << "\n";
    cout << "Union of them:\n";
    copy (result.begin (), result.end (), out);
    cin.ignore (1);
    cin.get ();
    return 0;
}
bool isOdd (int i)
{
    return (i % 2);
}
bool isEven (int i)
{
    return !(i % 2);
}
bool isMultipleTo5 (int i)
{
    return !(i % 5);
}
void fill (vector <int> & source, vector <int> & dest, bool (*check) (int i))
{
    vector <int>::iterator search = find_if (source.begin (), source.end (), check);
    while (search != source.end ())
    {
        dest.push_back (*search);
        search++;
        search = find_if (search, source.end (), check);
    }
}
void unite (vector <int> & a, vector <int> & b, set <int> & r)
{
    vector <int>::iterator temp = a.begin ();
    vector <int>::iterator check;
    while (temp != a.end ())
    {
        check = find (b.begin (), b.end (), *temp);
        if (check != b.end ())
        {
            r.insert (*temp);
        }
        ++temp;
    }
    temp = b.begin ();
    while (temp != b.end ())
    {
        check = find (a.begin (), a.end (), *temp);
        if (check != a.end ())
        {
            r.insert (*check);
        }
    }
    ++temp;
}
Миниатюры
Объединение двух контейнеров  
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
21.10.2013, 17:38  [ТС]     Объединение двух контейнеров #4
++temp; перенес внутрь блока if.вот кстати ошибочка
Миниатюры
Объединение двух контейнеров  
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,409
21.10.2013, 17:44     Объединение двух контейнеров #5
Каково полное задание?
Мне кажется тут нужен стандартный алгоритм set_symmetric_difference

Добавлено через 5 минут
А на какую строку ругается? В коде под катом нет 101.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
21.10.2013, 19:53     Объединение двух контейнеров #6
101 это в stl'евском файле..

Добавлено через 9 минут
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
а вообще, перед этим написал, что vector <int> итератор не приращиваемый!
Дело в том, что, судя по показаниям дебагера массив b у тебя туда передавался пустой. temp стоял вне цикла, и таким образом в любом случае он пытался выполнить операцию ++, что в силу пустоты b невозможно. Мне вообще сдается, что просто необходимо вставить проверки ну пустоту (если просто занесение ++temp не поможет).

Цитата Сообщение от tramp_1-3 Посмотреть сообщение
а о каких пробелах идёт речь?
Я думаю, что читабельность от пробелов повышается в таких ситуациях:
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
temp = b.begin ();
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
if (check != a.end ())
В следующих же случаях это только распыляет внимание:
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
void unite (vector <int> & a, vector <int> & b, set <int> & r)
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
copy (odd.begin (), odd.end (), out);
Так ведь намного лучше:
C++
1
2
3
void unite(vector<int>& a, vector<int>& b, set<int>& r)
 
copy(odd.begin(), odd.end(), out);
Но это, конечно, сугубо мое мнение...
I.M.
 Аватар для I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
21.10.2013, 19:55     Объединение двух контейнеров #7
monolit, так проблема решилась переносом ++temp внутрь цикла или нет? и если нет, то откуда стреляет ассерт?
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
22.10.2013, 02:47  [ТС]     Объединение двух контейнеров #8
MrGluck, программа производит логическое объединение двух множеств

Добавлено через 6 минут
Цитата Сообщение от monolit Посмотреть сообщение
Дело в том, что, судя по показаниям дебагера массив b у тебя туда передавался пустой. temp стоял вне цикла, и таким образом в любом случае он пытался выполнить операцию ++, что в силу пустоты b невозможно. Мне вообще сдается, что просто необходимо вставить проверки ну пустоту (если просто занесение ++temp не поможет).
так ведь temp - итератор массива A
C++
1
vector<int>::iterator temp = a.begin();
и приращиваться он должен только если конец А еще не достигнут. Вчера я зачем-то перенёс его приращивание в блок if, хотя это ошибка, т.к. temp - текущий элемент множества, и пока
C++
1
temp != a.end()
его нужно инкрементировать. Разве нет?

Добавлено через 11 минут
Цитата Сообщение от I.M. Посмотреть сообщение
так проблема решилась переносом ++temp внутрь цикла или нет? и если нет, то откуда стреляет ассерт?
его не надо никуда переносить, посмотрите выше почему.
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
Мне вообще сдается, что просто необходимо вставить проверки ну пустоту
C++
1
while (temp != a.end())
разве этот блок с этим не справится в случае пустого массива?
программа впадает в ступор в
C++
1
if (check != b.end ())
почему - непонятно.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,409
22.10.2013, 03:00     Объединение двух контейнеров #9
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
MrGluck, программа производит логическое объединение двух множеств
а если просто в unordered_set пихнуть?
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
22.10.2013, 03:26  [ТС]     Объединение двух контейнеров #10
Цитата Сообщение от MrGluck Посмотреть сообщение
а если просто в unordered_set пихнуть?
не знаком с таким, посмотрю, но эту программу точно нужно допилить с этими компонентами, нужно понять в чём дело.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,409
22.10.2013, 03:29     Объединение двух контейнеров #11
tramp_1-3, set только без сортировки. Получается обычный контейнер, содержащий уникальные по ключу элементы.

Добавлено через 47 секунд
Требует С++11. Если хочется иметь уникальные элементы, но подходящего компилятора под рукой нет, то можно и set использовать для данных целей.
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
22.10.2013, 03:32  [ТС]     Объединение двух контейнеров #12
Цитата Сообщение от MrGluck Посмотреть сообщение
Требует С++11. Если хочется иметь уникальные элементы, но подходящего компилятора под рукой нет, то можно и set использовать для данных целей.
понятно, спасибо, но меня сейчас не это беспокоит.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,409
22.10.2013, 03:44     Объединение двух контейнеров #13
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
26
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
 
void unite(const std::vector<int>& a, const std::vector<int>& b, std::set<int>& r)
{
    typedef std::vector<int>::const_iterator vec_cit;
 
    for (vec_cit temp = a.begin(); temp != a.end(); ++temp)
        if (std::find(b.begin(), b.end(), *temp) != b.end())
            r.insert (*temp);
 
    for (vec_cit temp = b.begin(); temp != b.end(); ++temp)
        if (std::find(a.begin(), a.end(), *temp) != a.end())
            r.insert(*temp);
}
 
int main()
{
    std::vector<int> v1 = {1, 2, 3, 4, 5}, v2 = {2, 4, 6, 8};
    std::set<int> s;
    unite(v1, v2, s);
    for (auto &x: s) // write your analog
        std::cout << x << " ";
}
То?

Добавлено через 1 минуту
Я слабо понимаю суть функции unite. Или это попытка самописного std::set_intersaction или std::set_union. Зависит от знака после функции std::find в условиях
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
22.10.2013, 09:44  [ТС]     Объединение двух контейнеров #14
Цитата Сообщение от MrGluck Посмотреть сообщение
Я слабо понимаю суть функции unite. Или это попытка самописного std::set_intersaction или std::set_union. Зависит от знака после функции std::find в условиях
Два множества необходимо объединить в одно так, чтобы в результате в нем были только те элементы, которые есть в обоих. Конъюнкция.

Добавлено через 2 минуты
MrGluck, работает как надо, осталось мне понять, где ж я просчитался.. спасибо огромное.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,409
22.10.2013, 11:46     Объединение двух контейнеров #15
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
MrGluck, работает как надо, осталось мне понять, где ж я просчитался.. спасибо огромное.
всего лишь в месте инструкции ++temp, как вам уже указывал monolit во втором сообщении. Я лишь занес все в циклы для наглядности. Я бы рекомендовал также присмотреться к некой оптимизации:
сначала вектора сортируются по возрастанию, а дальше идет проход в один цикл со сравнением двух конечных элементов векторов. Некий аналог
http://www.cplusplus.com/reference/a..._intersection/
Хотя и данный алгоритм вполне неплох.

Насчет лишних пробелов я с monolit полностью согласен
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
22.10.2013, 13:49     Объединение двух контейнеров #16
Хоть и с опозданием, и вопрос уже решен, но все же. Авось пригодится)

Цитата Сообщение от tramp_1-3 Посмотреть сообщение
программа впадает в ступор в
Код C++
1
if (check != b.end ())
почему - непонятно.
Если брать оба непустых массива, то в ступор не впадает. Специально проверил. Если пустой - ошибка с ++temp, что я и написал
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
и приращиваться он должен только если конец А еще не достигнут
Для этого и проверяют на !=****.end(). Если посмотреть в исходники stl итератора, то там никаких проверок нет, и ++ выполнится, если ты ее вызвал, есть ли у тебя что-то дальше, или нет. Если вызвал на end'е, сам виноват, получается.
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
Код C++
1
while (temp != a.end())
разве этот блок с этим не справится в случае пустого массива?
Справится (справлялось). Но... ++temp все портило...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2013, 14:59     Объединение двух контейнеров
Еще ссылки по теме:

C++ Не осуществляется объединение двух контейнеров
C++ Объединение двух массивов
C++ Объединение двух списков

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

Или воспользуйтесь поиском по форуму:
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
22.10.2013, 14:59  [ТС]     Объединение двух контейнеров #17
Цитата Сообщение от monolit Посмотреть сообщение
Если пустой - ошибка с ++temp, что я и написал
блин, ну буду аккуратней тогда с итераторами и пустыми контейнерами.
Цитата Сообщение от monolit Посмотреть сообщение
Но... ++temp все портило...
так жеш ++temp внутри цикла это, после проверки while (temp != a.end())
блин, нашёл наконец-таки ошибку! нижний ++temp перенес в скобку ближайшую и всё норм. как всегда, мелочная херня. спасибо за участие.

Добавлено через 19 минут
monolit, MrGluck, оптимизировал как мог, вот работает как надо, всем спасибо огромное. и да, пробелы тоже поправил.
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
26
27
28
29
void unite (vector<int>& a, vector<int>& b, set<int>& r)
{
    typedef std::vector<int>::const_iterator vec_iter;
    vec_iter moreSt;
    vec_iter lessSt;
    vec_iter moreEn;
    vec_iter lessEn;
    if (a.size() > b.size())
    {
        moreSt = a.begin();
        moreEn = a.end();
        lessSt = b.begin();
        lessEn = b.begin();
    }
    else
    {
        moreSt = b.begin();
        moreEn = a.end();
        lessSt = a.begin();
        lessEn = a.end();
    }
    for (vec_iter temp = moreSt; temp != moreEn; ++temp)
    {
        if (std::find (b.begin(), b.end(), *temp) != b.end())
        {
            r.insert(*temp);
        }
    }
}
Yandex
Объявления
22.10.2013, 14:59     Объединение двух контейнеров
Ответ Создать тему
Опции темы

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