Wyrzuca bład po skompilowaniu "out of range"

0

Witam serdecznie,
Dlaczego po skompilowaniu wyrzuca mi komunikat:
terminate called after throwing an instance of std::out of range.

kod funkcji:

size_t dlugosc = tekst.size();
    for(int i=0;i<dlugosc-1;i++){
        if(tekst[i]==tekst[i+1]){
            tekst.erase(i,1);
        }
    }

pozdrawiam

0

ponieważ w ostatnim kroku pętli porównujesz z ostatnim elementem, który jest znakiem końca tablicy.

if(tekst[i]==tekst[i+1]){

Tutaj, jeśli tekst[5], to tu w ostatnim kroku, porównujesz tekst[4]z tekst[5].

2

Dlatego, że długość stringa się zmienia po usunięciu z niego znaków.

0
kq napisał(a):

Dlatego, że długość stringa się zmienia po usunięciu z niego znaków.

Oczywiście! Dziękuje za trafna uwagę. Pozdrawiam

1

https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Korzystaj z metod udostępnionych przez klasę std::string,
prawie identycznie jak dla kontenera w linku.

0
midodej napisał(a):

Witam serdecznie,
Dlaczego po skompilowaniu wyrzuca mi komunikat:
terminate called after throwing an instance of std::out of range.

kod funkcji:

size_t dlugosc = tekst.size();
    for(int i=0;i<dlugosc-1;i++){
        if(tekst[i]==tekst[i+1]){
            tekst.erase(i,1);
        }
    }

pozdrawiam

to nie przez to, zabezpieczyłem się przed tym warunkiem w pętli dlugosc-1..
Odpowiedź padła ze strony moderatora przecież długość zmiennej się zmienia. Temat do zamknięcia.

pozdrawiam

1

Rozwijając ciut wypowiedź @carlosmay (+mój komentarz), wzorując się na

template<typename Container, typename Predicate>
void erase_if(Container& c, Predicate p)
{
    using std::begin;
    using std::end;
    using std::remove_if;
 
    auto realEnd = end(c);
    auto removedIt = remove_if(begin(c), realEnd, p);
 
    c.erase(removedIt, realEnd);
}

Możesz napisać coś takiego:

auto e = remove_if(s.begin(), prev(s.end()), [](char const& c){
    return c == (&c)[1];
});
s.erase(e, s.end());

link

Wydaje mi się, że to w pełni zdefiniowane zachowanie (zakładając co najmniej 1-elementowy s), ale i tak trochę zalatuje hackiem ((&c)[1])

1

Bez "hacków":

char prev_c = 0;
auto it = std::remove_if(s.begin(), 
					s.end(), 
					[&prev_c](char c) 
					{ 
						bool res = prev_c == c; 
						prev_c = c; 
						return res; 
					});
s.erase(it, s.end());

1 użytkowników online, w tym zalogowanych: 0, gości: 1