Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
1

Expression: vector iterator not decrementable

27.02.2017, 11:44. Просмотров 1017. Ответов 21

Требуется в двух файлах удалить повторяющие строки (до первого вхождения)

Примеры:
Name_N
Кликните здесь для просмотра всего текста
<TEXT>
<Tag>TXT_KEY_STAGING_ROOM_CIVS_TAG</Tag>

<English>Nations:</English>
<French>Íàöèè:</French>

<German>Nationen:</German>
<Italian>Nazioni:</Italian>
<Spanish>Naciones:</Spanish>
</TEXT>

"_"+Name_N
Кликните здесь для просмотра всего текста
<TEXT>
<Tag>TXT_KEY_STAGING_ROOM_CIVS_TAG</Tag>
<Russian>Íàöèè:</Russian>
<English>Nations:</English>

<French>Nations :</French>
<German>Nationen:</German>
<Italian>Nazioni:</Italian>
<Spanish>Naciones:</Spanish>
</TEXT>


Создал функцию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void DupKiller(string Name_N)
{       
        string text;
        vector<string> f1;
        ifstream feng(Name_N);
        while(getline(feng,text)) f1.push_back(text);
        feng.close();
 
        vector<string> f2;
        ifstream frus("_"+Name_N);
        while(getline(frus,text)) f2.push_back(text);
        frus.close();
 
        for (vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            for (vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
                if(*iter1 == *iter2)
                {
                    cout << *iter1 << " " << *iter2;
                    f1.erase(iter1--);
                    f2.erase(iter2--);
                    break;
                }               
}
Вывалилась ошибка на строчке
C++
1
f1.erase(iter1--);
0
Миниатюры
Expression: vector iterator not decrementable  
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.02.2017, 11:44
Ответы с готовыми решениями:

vector iterator not decrementable
Здраствуйте! Хочу вывести вектор задом-наперед, все нормально, но после того...

Ошибка: iterator not decrementable
компилятор ошибок не выдает, а когда программа начинает работать она...

Ошибка "list iterator not decrementable" при удалении элемента из списка
При удалении элемента из списка (list) - ошибка list iterator not decrementable...

vector<T> template vector<T>::iterator
Здраствуйте! При написании вектора столкнулся с проблемой такого рода: вот...

Struct / Vector / Expression: vector subscript out of range
Добрый вечер. Имеется структура: struct Contact { public: string...

21
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 12:02  [ТС] 2
Отладка кода (клавиша F10)
0
Миниатюры
Expression: vector iterator not decrementable   Expression: vector iterator not decrementable   Expression: vector iterator not decrementable  

Expression: vector iterator not decrementable   Expression: vector iterator not decrementable  
zss
Модератор
Эксперт С++
7186 / 6681 / 4230
Регистрация: 18.12.2011
Сообщений: 17,631
Завершенные тесты: 1
27.02.2017, 12:08 3
Лучший ответ Сообщение было отмечено eXPonent как решение

Решение

не надо итератор декрементировать
C++
1
2
3
                
f1.erase(iter1);
f2.erase(iter2);
Хотя, в принципе
Функция erase делает недействительными все итераторы, указывающие на все
позиции после точки удаления, но итераторы, указывающие на позиции, предшествующие точке
удаления, остаются корректными.
Но когда декремент делается на первом элементе, то операция невыполнима.
Можно, конечно,
C++
1
2
3
4
5
                
if(iter1!=f1.begin())
    f1.erase(iter1--);
if(iter2!=f2.begin())
    f2.erase(iter2--);
Но тогда не будет удаляться первая строка
1
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 12:22  [ТС] 4
Теперь ошибка в этой строчке кода:
C++
1
for (vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
0
Миниатюры
Expression: vector iterator not decrementable  
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 12:25 5
ИМХО, легче создать ещё один вектор и сливать туда всё, у чего нет дубликатов, так даже быстрее будет, я думаю.
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 13:00  [ТС] 6
Цитата Сообщение от zss Посмотреть сообщение
Можно, конечно,
C++
1
2
3
4
if(iter1!=f1.begin())
 f1.erase(iter1--);
if(iter2!=f2.begin())
 f2.erase(iter2--);
Но тогда не будет удаляться первая строка
Дописал функцию:
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
void DupKiller(string Name_N)
{       
        string text;
        vector<string> f1;
        ifstream fin(Name_N);
        while(getline(fin,text)) f1.push_back(text);
        fin.close();
 
        vector<string> f2;
        fin.open("_"+Name_N);
        while(getline(fin,text)) f2.push_back(text);
        fin.close();
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            if((*iter1).find("      <German>")||(*iter1).find("     <Spanish>")||(*iter1).find("        <Italian>"))
                f1.erase(iter1);
        for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
            if((*iter2).find("      <German>")||(*iter2).find("     <Spanish>")||(*iter2).find("        <Italian>"))
                f1.erase(iter2);
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
                if(*iter1 == *iter2)
                {
                    if(iter1 != f1.begin()) f1.erase(iter1--);
                    if(iter2 != f2.begin()) f2.erase(iter2--);
                    break;
                }  
 
        ofstream fout(Name_N);
        for (vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++) fout << *iter1 << endl;
        fout.close();
 
        fout.open("_"+Name_N);
        for (vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++) fout << *iter2 << endl;
        fout.close();
}
вопрос?
а как при удалении дубля начинать чтение не с начала вектора, а с момента последнего выхода?
что бы ускорить выполнение функции

и кстати с помощью for_each можно ускорить выполнение функции?

Добавлено через 4 минуты
Цитата Сообщение от GbaLog- Посмотреть сообщение
ИМХО, легче создать ещё один вектор и сливать туда всё, у чего нет дубликатов, так даже быстрее будет, я думаю.
так ведь нужно сохранить два вектора, получается придется создавать ещё два вектора
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 13:08  [ТС] 7
Немного подкорректировал код:
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
void DupKiller(string Name_N)
{       
        string text;
        vector<string> f1;
        ifstream fin(Name_N);
        while(getline(fin,text)) f1.push_back(text);
        fin.close();
 
        vector<string> f2;
        fin.open("_"+Name_N);
        while(getline(fin,text)) f2.push_back(text);
        fin.close();
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            if(((*iter1).find("     <German>") != string::npos)||((*iter1).find("       <Spanish>") != string::npos)||((*iter1).find("      <Italian>") != string::npos))
                f1.erase(iter1);
        for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
            if(((*iter2).find("     <German>") != string::npos)||((*iter2).find("       <Spanish>") != string::npos)||((*iter2).find("      <Italian>") != string::npos))
                f1.erase(iter2);
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
                if(*iter1 == *iter2)
                {
                    if(iter1 != f1.begin()) f1.erase(iter1--);
                    if(iter2 != f2.begin()) f2.erase(iter2--);
                    break;
                }  
 
        ofstream fout(Name_N);
        for (vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++) fout << *iter1 << endl;
        fout.close();
 
        fout.open("_"+Name_N);
        for (vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++) fout << *iter2 << endl;
        fout.close();
}
но все равно выпадает ошибка:
0
Миниатюры
Expression: vector iterator not decrementable  
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 13:10 8
Цитата Сообщение от eXPonent Посмотреть сообщение
так ведь нужно сохранить два вектора, получается придется создавать ещё два вектора
Тогда так:
http://rextester.com/LGPA44586
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//g++  5.4.0
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
 
int main()
{
    std::cout << "Hello, world!\n";
 
    typedef std::vector<std::string> VecString; 
    
    VecString first{ "first", "second", "third" };
    VecString secnd{ "third", "fourth" };
    
    first.erase(std::remove_if(first.begin(), first.end(), [&] (const std::string & n) { return std::find(secnd.begin(), secnd.end(), n) != secnd.end(); }), first.end()); 
    secnd.erase(std::remove_if(secnd.begin(), secnd.end(), [&] (const std::string & n) { return std::find(first.begin(), first.end(), n) != first.end(); }), secnd.end());
    
    std::copy(first.begin(), first.end(), std::ostream_iterator<std::string>(std::cout, " "));
    std::cout << '\n';
    std::copy(secnd.begin(), secnd.end(), std::ostream_iterator<std::string>(std::cout, " "));
}
Если порядок не важен, то есть ещё std::set_difference.
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 13:14  [ТС] 9
Ошибка где то в коде:
Цитата Сообщение от eXPonent Посмотреть сообщение
C++
1
2
3
4
5
6
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            if(((*iter1).find("     <German>") != string::npos)||((*iter1).find("       <Spanish>") != string::npos)||((*iter1).find("      <Italian>") != string::npos))
                f1.erase(iter1);
        for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
            if(((*iter2).find("     <German>") != string::npos)||((*iter2).find("       <Spanish>") != string::npos)||((*iter2).find("      <Italian>") != string::npos))
                f1.erase(iter2);
0
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 13:17 10
Цитата Сообщение от eXPonent Посмотреть сообщение
Ошибка где то в коде
Ещё раз, erase делает невалидными ВСЕ итераторы, которые на этот же вектор указывают. После первого erase iter1/iter2 становится уже невалидным, а вы его всё равно используете...
Лекарство(начиная с с++11):
C++
1
2
3
4
5
6
for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
    if(((*iter1).find("     <German>") != string::npos)||((*iter1).find("       <Spanish>") != string::npos)||((*iter1).find("      <Italian>") != string::npos))
        iter1 = f1.erase(iter1);
for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
    if(((*iter2).find("     <German>") != string::npos)||((*iter2).find("       <Spanish>") != string::npos)||((*iter2).find("      <Italian>") != string::npos))
        iter2 = f1.erase(iter2);
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 13:41  [ТС] 11
а чем ваш код отличается от моего?
и кстати без использования этого куска кода функция работает
0
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 13:52 12
Цитата Сообщение от eXPonent Посмотреть сообщение
а чем ваш код отличается от моего?
https://www.diffchecker.com/SSYAuTOr
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 14:02  [ТС] 13
Получается тут тоже нужно делать присваивание?
C++
1
2
3
4
5
6
if(*iter1 == *iter2)
{
    if(iter1 != f1.begin()) f1.erase(iter1--);
    if(iter2 != f2.begin()) f2.erase(iter2--);
    break;
}
или нет?
0
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 14:05 14
Цитата Сообщение от eXPonent Посмотреть сообщение
Получается тут тоже нужно делать присваивание?
Да, и проверка с декрементированием тут не нужны.
А вообще, я вам показал, как надо: Expression: vector iterator not decrementable
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 14:09  [ТС] 15
Так ?
C++
1
2
3
4
5
6
if(*iter1 == *iter2)
{
    iter1 = f1.erase(iter1--);
    iter2 = f2.erase(iter2--);
    break;
}
0
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 14:14 16
Цитата Сообщение от GbaLog- Посмотреть сообщение
декрементированием тут не нужны.
...
Цитата Сообщение от eXPonent Посмотреть сообщение
C++
1
iter1--
Цитата Сообщение от eXPonent Посмотреть сообщение
C++
1
iter2--
0
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 14:53  [ТС] 17
Опечатка, так?
C++
1
2
3
4
5
6
if(*iter1 == *iter2)
{
    iter1 = f1.erase(iter1);
    iter2 = f2.erase(iter2);
    break;
}
Добавлено через 34 минуты
В итоге получили:
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
void DupKiller(string Name_N)
{       
        string text;
        vector<string> f1;
        ifstream fin(Name_N);
        while(getline(fin,text)) f1.push_back(text);
        fin.close();
 
        vector<string> f2;
        fin.open("_"+Name_N);
        while(getline(fin,text)) f2.push_back(text);
        fin.close();
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            if(((*iter1).find("     <German>") != string::npos)||((*iter1).find("       <Spanish>") != string::npos)||((*iter1).find("      <Italian>") != string::npos))
                iter1 = f1.erase(iter1);
        for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
            if(((*iter2).find("     <German>") != string::npos)||((*iter2).find("       <Spanish>") != string::npos)||((*iter2).find("      <Italian>") != string::npos))
                iter2 = f2.erase(iter2);
 
        for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
                if(*iter1 == *iter2)
                {
                    iter1 = f1.erase(iter1);
                    iter2 = f2.erase(iter2);
                    break;
                } 
 
        ofstream fout(Name_N);
        for (vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++) fout << *iter1 << endl;
        fout.close();
 
        fout.open("_"+Name_N);
        for (vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++) fout << *iter2 << endl;
        fout.close();
}
но получилось два файла:
(и даже невооруженным взглядом видно, что программа сработала неверно (точнее не полностью удалила дубли)
Строчка:
Кликните здесь для просмотра всего текста
<English>Players may lead any Nation with any Leader.</English>

и другие совпадают
0
Вложения
Тип файла: 7z Colonization.7z (29.7 Кб, 1 просмотров)
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 15:29  [ТС] 18
Вернув обратно эти строчки кода, код заработал более коректно
C++
1
2
3
4
5
6
7
8
for(vector<string>::iterator iter1 = f1.begin(); iter1 != f1.end(); iter1++)
            for(vector<string>::iterator iter2 = f2.begin(); iter2 != f2.end(); iter2++)
                if(*iter1 == *iter2)
                {
                    if(iter1 != f1.begin()) f1.erase(iter1--);
                    if(iter2 != f2.begin()) f2.erase(iter2--);
                    break;
                }
Но остались фразы типа
Кликните здесь для просмотра всего текста
<Italian>I turni sono limitati da un conto alla rovescia basato sulla dimensione della colonia più grossa</Italian>
0
Вложения
Тип файла: 7z Colonization.7z (17.2 Кб, 1 просмотров)
GbaLog-
Любитель чаепитий
3166 / 1472 / 465
Регистрация: 24.08.2014
Сообщений: 5,204
Записей в блоге: 1
Завершенные тесты: 2
27.02.2017, 16:05 19
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
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
 
int main()
{
    std::ifstream f1("CIV4GameText_Colonization.xml");
    std::ifstream f2("_CIV4GameText_Colonization.xml");
    
    std::vector<std::string> v1;
    std::vector<std::string> v2;
    
    for (std::string tmp; std::getline(f1, tmp); )
        v1.push_back(tmp);
    
    for (std::string tmp; std::getline(f2, tmp); )
        v2.push_back(tmp);
    
    f1.close();
    f2.close();
    
    std::vector<std::string> res1(v1);
    std::vector<std::string> res2(v2);
    
    res1.erase(std::remove_if(res1.begin(), res1.end(), [&] (const std::string & n) { return std::find(v2.begin(), v2.end(), n) != v2.end(); }), res1.end());
    res2.erase(std::remove_if(res2.begin(), res2.end(), [&] (const std::string & n) { return std::find(v1.begin(), v1.end(), n) != v1.end(); }), res2.end());
    
    std::ofstream fileOut1("RESULTCIV4GameText_Colonization.xml");
    std::ofstream fileOut2("RESULT_CIV4GameText_Colonization.xml");
    
    for (const auto & it : res1)
        fileOut1 << it << '\n';
    
    for (const auto & it : res2)
        fileOut2 << it << '\n';
}
P.S. Данная программа рабочая, и дальше с вами дискуссию о том, почему у вас ваш вариант не работает я не собираюсь. Изучайте контейнеры и итераторы. Джосаттис вам в помощь.
1
eXPonent
99 / 52 / 27
Регистрация: 21.05.2012
Сообщений: 1,170
27.02.2017, 17:11  [ТС] 20
На этот код:
Цитата Сообщение от GbaLog- Посмотреть сообщение
C++
1
2
3
4
5
    for (const auto & it : res1)
        fileOut1 << it << '\n';
    
    for (const auto & it : res2)
        fileOut2 << it << '\n';
выкидывает это (студия 10):
0
Миниатюры
Expression: vector iterator not decrementable  
27.02.2017, 17:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.02.2017, 17:11

Std::vector<std::pair<std::vector<int>::iterator, std::vector<int>::iterator>
Вопрос по вектору. Допустим есть вектор, std::vector&lt;int&gt; vec; на каком -...

Ошибка Expression: map/set iterator not dereferencable
Здравствуйте! Мне нужно вывести контейнер map в обратном порядке. Делаю...

copy, iterator, vector
#include &lt;istream&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; #include...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru