Как удалить рядом стоящие одинаковые по значению символы, но разные по регистру?

Пытаюсь создать цикл удаления из строки рядом стоящий повторяющихся по значению символов, но разных по регистру. Т.е при вводе строки AaBb он должен вывести пустую строку, а при вводе AaBB он должен вывести BB. Cмог придумать цикл на проверку подстроки, но он не работает и это неэффективно.

string S;
cin >> S;
int k=2;
int lengt= S.size();
for(int i=0; i<S.size(); i++){
label1:
if(lengt>S.size()){
    k=1;
    lengt=S.size();
}
else{
    k=2;
}
if(S.find("Aa")<52){
    S.erase(S.find("Aa"),S.find("Aa")+k);
    goto label1;
}
if(S.find("aA")<52){
    S.erase(S.find("aA"),S.find("aA")+k);
    goto label1;
    }
if(S.find("bB")<52){
    S.erase(S.find("bB"),S.find("bB")+k);
    goto label1;
    }  
if(S.find("Bb")<52){
    S.erase(S.find("Bb"),S.find("Bb")+k);
    goto label1;
}
if(S.find("Cc")<52){
    S.erase(S.find("Cc"),S.find("Cc")+k);
    goto label1;
}
 if(S.find("сС")<52){
    S.erase(S.find("сС"),S.find("сС")+k);
    goto label1;
    } 
}
if(!S.empty()){
    cout<<"Impossible"<<endl;
}
else{
     cout<<"Possible"<<endl;
}

Ответы (1 шт):

Автор решения: maestro

Для этой цели подойдёт функция std::adjacent_find. Она ищет рядом стоящие пары одинаковых элементов массива. Только в данном случае нужно будет дополнительно указать ей, что следует считать равными именно равные по значению символы, но разные по регистру. Для этого надо написать компаратор.

#include <iostream>
#include <algorithm>

int main() {
    std::string s = "Have you seen the new Ssang Yong?";
    
    //Напишем функцию компаратора.
    //Компаратор принимает два символа и возвращает истину,
    //если символы равны по значению но разные по регистру.
    auto comparator = [](char left, char right) {
        unsigned char uleft = static_cast<unsigned char>(left);
        unsigned char uright = static_cast<unsigned char>(right);
        bool isEqual = std::tolower(uleft) == std::tolower(uright);
        bool isLeftConverted = uleft == std::tolower(uleft);
        bool isRightConverted = uright == std::tolower(uright);
        return isEqual && (isLeftConverted ^ isRightConverted);
    };
    //Цикл, который ищет одинаковые элементы. В качестве параметра передана функция компаратора.
    for (auto it = std::adjacent_find(s.begin(), s.end(), comparator); 
         it != s.end(); 
         it = std::adjacent_find(it, s.end(), comparator))
    {
        //Удаляем два рядом стоящих символа
        it = s.erase(it, std::next(it, 2));
        
    }
    std::cout << s;
    return 0;
}

https://ideone.com/2QPDST

UPD. Если же необходимо обрабатывать не пары, а произвольное количество идущих подряд символов, то последнее вхождение можно найти функцией std::upper_bound. Компаратор при этом надо будет переработать.

→ Ссылка