2014-01-24 4 views
1

У меня есть это своеобразное требование, когда мне нужно удалить все пробелы перед конкретным символом, который является трубой '|'. Я написал тестовый код для него, который на самом деле печать правильный вывод, но дополнительно подарив мне файл ядра :(Удалите все пробелы перед символом в строке

Мой код ниже:

int main() 
{ 

    string line="1 2 |3 4| hbvhwf  wjff wenf|hjbcwbfw  ejwef efwk dfkwe|jsv      |"; 
    cout <<line<<endl; 
    string::iterator ite =(line.begin()); 

    int counter=0; 
    int index=0; 
    int start=0; 
    while(ite != (line.end())) 
    { 
     if(*ite == '|' && counter > 0) 
     { 
      line.erase(start,counter); 
      counter=0; 
      cout<<line<<endl; 
     } 
     if(ite!=line.end()) 
     { 
      if(isalnum(*ite)) 
      { 
       counter=0; 
      } 
      if(*ite==' ') 
      { 
       if(!counter) 
       { 
        start=index; 
       } 
       counter++; 
      } 
      ite++; 
      index++;   
     } 
    } 

    cout<<line<<endl; 
} 

Я просто схожу с ума в поисках корня . причиной дамп Может кто-нибудь, пожалуйста, помогите ожидается выход:

1 2|3 4| hbvhwf  wjff wenf|hjbcwbfw  ejwef efwk dfkwe|jsv| 
+1

После того, как вы называете стереть на линии вам нужно сбросить итератор. – dwxw

+0

Это должно быть сделано автоматически, я думаю. Я не хочу этого делать. Насколько я понимаю. – user1939168

+0

@ user1939168 ['std :: string :: erase'] (http://en.cppreference.com/w/cpp/string/basic_string/erase) возвращает итератор. Вы должны назначить его 'ite' в своем коде. – rubenvb

ответ

1

Как говорит ответ Кшиштофа, причиной дампа ядра является erase() недействительными итераторы. Чтобы решить эту проблему, вам необходимо правильно исправить итератор, используйте range version из erase(), ваш получит итератор, ссылающийся на символ, который теперь занимает позицию первого стираемого символа, и назначает его ite. Измените первый оператор if на приведенный ниже код, он должен работать нормально.

if(*ite == '|' && counter > 0) 
    { 
     ite = line.erase(ite - counter, ite); 

     counter=0; 
     cout<<line<<endl; 
    } 
+0

Спасибо. Это именно то, что я искал. – user1939168

1

erase() Вызов на строку аннулирует все итераторы в строку, в том числе ite.

В частности, когда line.erase(start,counter); исполняет, ite признан недействительным - больше не будет гарантировано ссылаться на действительное положение в строке. Если он не равен line.end(), он может быть разыменован в состоянии isalnum(*ite). Поскольку ite недействителен в этой точке, он может ссылаться на уже освобожденную память (например, если строка была перераспределена после стирания). Поэтому эта строка вызывает segfault.

Вот более простая версия вашего кода, в которой нет проблемы.

std::string line = ...; 
unsigned space_run = 0; 

for (unsigned i = 0; i < line.size(); ++i) { 
    if (line[i] == ' ') { 
     ++space_run; 
    } else if (line[i] == '|') { 
     line.erase(i - space_run, space_run); 
     i -= space_run; 
     space_run = 0; 
    } else { 
     space_run = 0; 
    } 
} 
+0

Это не работает. – Vijay

+0

В нем была глупая ошибка, теперь она должна работать. –

+0

Но что случилось с моим кодом? где ошибка? – user1939168

0
#include <iostream> 
#include <string> 
#include <iterator> 
#include <algorithm> 
using namespace std; 

int main() 
{ 
    string line="1 2 |3 4| hbvhwf  wjff wenf|hjbcwbfw  ejwef efwk dfkwe|jsv      |"; 
    cout <<line<<endl; 

    string res; 
    size_t length = line.size(); 
    bool flag = false; 
    for (int i = length - 1; i >= 0 ; --i) 
    { 
     if (line[i] == '|') 
     { 
      res.push_back(line[i]); 
      flag = true; 
     } 
     else if (flag && line[i] == ' ') 
     { 

     } 
     else 
     { 
      res.push_back(line[i]); 
      flag = false; 
     } 
    } 

    copy(res.rbegin(), res.rend(), ostream_iterator<char>(cout, "")); 
    cout<<endl; 
} 

выводе является:

1 2 |3 4| hbvhwf  wjff wenf|hjbcwbfw  ejwef efwk dfkwe|jsv      | 
1 2|3 4| hbvhwf  wjff wenf|hjbcwbfw  ejwef efwk dfkwe|jsv| 
Смежные вопросы