• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zamiana miejscami znaków specjalnych w std::string

Object Storage Arubacloud
0 głosów
499 wizyt
pytanie zadane 7 lipca 2020 w C i C++ przez kupson3697 Użytkownik (610 p.)

Witam wszystkich,

Mam problem z jednym zadaniem, treść poniżej:

Napisz funkcje function, która przyjmuje niemodyfikujacy iterator poczatkowy i koncowy wycinka lancucha tekstowego oraz modyfikujacy iterator poczatkowy innego wycinka.
Funkcja przepisuje zawartosc pierwszego wycinka do drugiego zamieniajac kazda sekwencje \r\n na \n i odwrotnie.
Funkcja zwraca modyfikujacy iterator nastepnego znaku za ostatnim wpisanym.
Funkcja powinna byæ przystosowana do uzycia w przykladowym programie ponizej. Funkcja korzysta tylko z pliku naglówkowego string.
Przykladowy program
int main() {
    std::string in = "peppermint 1001\rbubbles\nballoon\r\ngum", out(100, '*');
    auto e = function(in.cbegin(), in.cend(), out.begin());
    int n = e - out.begin();
    std::string s = out.substr(0, n);
    bool b = (s == "peppermint 1001\rbubbles\r\nballoon\ngum");
    std::cout << std::boolalpha << b << std::endl; }
Wykonanie
true

Męczę to zadanie już dłuższy czas i nie mogę sobie poradzić. Wydaje mi się, że wszystko powinno działać, a jednocześnie mam wrażenie, że o czymś zapomniałem. 

Mój kod:

std::string::iterator function(std::string::const_iterator b, std::string::const_iterator e, std::string::iterator f ){

    auto y = b + 1;

    for(auto i = b; i<e; i++){

            if((int)*i == 13 && (int)*y == 10){
                *f == '\n';
            } else if((int)*b == 10) {
                *f = '\r';
                *(f+1) = '\n';
            } else {
                *f = *i;
            }

            f++;
            y++;
    }


    return f;
}

int main() {
    std::string in = "peppermint 1001\rbubbles\r\nballoon\ngum", out(100, '*');



    auto e = function(in.cbegin(), in.cend(), out.begin());
    int n = e - out.begin();
    std::string s = out.substr(0, n);
    std::cout<< s << "\n\n";
    bool b = (s == "peppermint 1001\rbubbles\r\nballoon\ngum");
    std::cout << std::boolalpha << b << std::endl;

}

 

Warto dodać, że mogę operować tylko na funkcji tzn. main nie może zostać zmienony oraz używam jedynej biblioteki tj. string oraz iostream. 

Czy jakieś wprawne oko dostrzega błąd w powyższym kodzie? Będe bardzo wdzięczny za pomoc ;-) 

1 odpowiedź

+1 głos
odpowiedź 7 lipca 2020 przez Falitac Użytkownik (860 p.)
wybrane 7 lipca 2020 przez kupson3697
 
Najlepsza
#include<iostream>
#include<string>

std::string::iterator function(std::string::const_iterator b, std::string::const_iterator e, std::string::iterator f ){
    
    for(auto i = b; i!=e; i++, f++){
        if(*i == '\r' && *(i+1) == '\n'){
            *f = '\n';
            i++;
        } else if(*i == '\n') {
            *f = '\r';
            *++f = '\n';
        } else {
            *f = *i;
        }
    }
 
    return f;
}
 
int main() {
    std::string in = "peppermint 1001\rbubbles\r\nballoon\ngum", out(100, '*');
 
    auto e = function(in.cbegin(), in.cend(), out.begin());
    int n = e - out.begin();
    std::string s = out.substr(0, n);
    
    std::cout<< s << "\n\n";
    
    bool b = (s == "peppermint 1001\rbubbles\nballoon\r\ngum");
    std::cout << std::boolalpha << b << std::endl;
 
}

Znacząco zmodyfikowałem twoje dzieło. Nie uwzględniałeś w zamianach przesunięć iteratorów(i++,f++) przez co funkcja źle przepisywała wartości. Porównujesz w pierwszym ifie p=='\n' zamiast przypisać. W drugim zaś w warunku odnosisz się do b, co jest bzdurą, bo jest to pierwsza wartość tego stringa. No i w każdym z warunków konwertujesz chara na inta, sprawdzasz zapewne z tabeli ascii, co jest wg mnie katorgą skoro możesz użyć także znaków '\r' '\n'. Wywaliłbym też ten iterator y. Tu masz ideone z wynikiem: https://ideone.com/TOMWXi

komentarz 7 lipca 2020 przez kupson3697 Użytkownik (610 p.)

Bardzo dziękuję!wink

komentarz 7 lipca 2020 przez kupson3697 Użytkownik (610 p.)
edycja 7 lipca 2020 przez kupson3697

@Falitac, Wiesz może jaka jest różnica pomiędzy zapisem *(f+1) oraz *++f? Ten pierwszy sposób to postinkrementacja, dobrze to rozumiem? Pytam bo jeśli zamienie jedno na drugie to jest błąd, myślałem że jedno i drugie zwraca iterator przesuniety o jeden.

2
komentarz 7 lipca 2020 przez Falitac Użytkownik (860 p.)

++f to preinkrementacja
f++ to postinkrementacja
Oba zwiększają wartość o jeden, z tą różnicą że gdy w wyrażeniu użyjesz preinkrementacji to będzie to już wartość zwiększona, a w postinkrementacji będzie to wartość jeszcze przed zwiększeniem. Przykład:
 

int a=5;

cout << a++ << endl; //wyświetli 5

a=5
cout << ++a << endl; //wyświetli 6

*(f+1) jest odniesieniem do kolejnej wartości, nie zmienia jednak iteratora f więc *(f+1) != *++f(nie jest to żadna inkrementacja, bo takowa wiąże się ze zmianą wartości). Nie rozumiem do końca błędu, w podesłanym przeze mnie ideonie działało, więc jakbyś mógł sprecyzować to byłbym wdzięczny.

2
komentarz 7 lipca 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

*(f+1) to:

std::string::iterator temp = f + 1;
*temp;
// zauważ, że f nie zmieniło stanu

zaś *++f to:

++f; // zmienia stan f (preinkrementacja)
*f;

Polecam stosować te rozwleklejsze formy, dzięki czemu kod łatwiej się czyta.

Pytałeś jeszcze o postinkrementację. Kontynuując powyższy przykład postinkrementacja miałaby postać *f++ i oznacza ona:

*f;
++f; // preinkrementacja

 

komentarz 7 lipca 2020 przez kupson3697 Użytkownik (610 p.)

@Falitac,  Aa no tak, dobra racjawink  No właśnie Twój kod działa ale zauważyłem, że często robię ten błąd, że stosuje zamiennie przy iteratorach te dwie formy i później spędzam dużo czasu na szukaniu błędu. 

komentarz 7 lipca 2020 przez kupson3697 Użytkownik (610 p.)

@Piotr Batko, Ogromne dzięki za wytłumaczenie! Kilka postów, a zaoszczędziło mi to dużo szukania w necie wink 

Podobne pytania

0 głosów
1 odpowiedź 156 wizyt
pytanie zadane 2 września 2017 w C i C++ przez wgnsy123 Początkujący (410 p.)
0 głosów
1 odpowiedź 286 wizyt
pytanie zadane 18 stycznia 2023 w C i C++ przez pixel1335 Nowicjusz (170 p.)

92,576 zapytań

141,426 odpowiedzi

319,650 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...