Kaza Temat założony przez niniejszego użytkownika |
Zadanie 28 - Przemieszczające się podmieniane znaki. » 2017-07-13 20:01:59 Witam wszystkich. Odpalając świeżo napisany program zauważyłem dziwną właściwość "nowych" tekstów. Ale od początku. #include <iostream> #include <string>
size_t pozycjaznaku( std::string wjakimtekscie, std::string znak ) { size_t pozycja = wjakimtekscie.find( znak ); if( pozycja == std::string::npos ) { return false; } return pozycja; }
void zamienznak( std::string & tekst, std::string znak, std::string naco, int ileznakowusunac ) { do { tekst.erase( pozycjaznaku( tekst, znak ), ileznakowusunac ); tekst.insert( pozycjaznaku( tekst, znak ), naco ); } while( pozycjaznaku( tekst, znak ) != false ); }
int main() { std::string tekst = "<b> to jest </b> testowy napis <b>:)"; std::cout << "Tekst przed zmiana:\n"; std::cout << tekst; std::string znak1 = " "; std::string znak2 = " "; std::string znak3 = "<"; std::string znak4 = "["; std::string znak5 = ">"; std::string znak6 = "]"; zamienznak( tekst, znak1, znak2, 2 ); zamienznak( tekst, znak3, znak4, 1 ); zamienznak( tekst, znak5, znak6, 1 ); std::cout << "\n\nTekst po zmianie:\n"; std::cout << tekst; return 0; }
Program zmienia niemal każdy znak tak jak tego oczekiwałem, jednak pierwszy zmieniony znak z każdego rodzaju pojawia się na początku tekstu. Myślałem, że może pokręciłem coś z wartościami pozycji, jednak problem występuje niezależnie od tego jak długi jest tekst, na jakich pozycjach występują znaki do zmiany, oraz jakiego rodzaju są to znaki. Czytałem cały kod mnóstwo razy, analizując każdą linijkę z osobna, ale nie mam pojęcia co może powodować przeskakiwanie znaków na początek tekstu. Czy ktoś bardziej rozgarnięty mógłby wyjaśnić mi powód tej "literowej migracji"? |
|
carlosmay |
» 2017-07-13 22:16:12 W funkcji pozycjaznaku kosmetyka: Zamiast zwracać wartość logiczną false , gdy funkcja ma zadeklarowany zwracany typ na std::size_t (jest bardzo nieintuicyjnie i może wprowadzać w błąd), zwracaj wartość jaką zwraca metoda find , gdy nic nie znajdzie. size_t pozycjaznaku( std::string wjakimtekscie, std::string znak ) { size_t pozycja = wjakimtekscie.find( znak ); if( pozycja == std::string::npos ) { return std::string::npos; } return pozycja; } W zasadzie ta funkcja mogłaby zniknąć z kodu :). Bo robi dokładnie return wjakimtekscie.find( znak ); W funkcji zamienznak jest błąd logiczny: do { tekst.erase( pozycjaznaku( tekst, znak ), ileznakowusunac ); tekst.insert( pozycjaznaku( tekst, znak ), naco ); } while( pozycjaznaku( tekst, znak ) != false );
Zapamiętuj zwracaną pozycję z funkcji pozycjaznaku i na tej wartości operuj. std::size_t pos = pozycjaznaku( tekst, znak ); i w metodach erase oraz insert używaj właśnie zmiennej pos . Kod jest zamotany i musiałem użyć debuggera (jak najszybciej poznaj) aby rozkminić, co się dzieje w kodzie. |
|
Kaza Temat założony przez niniejszego użytkownika |
Działa tak jak powinno. » 2017-07-14 14:56:28 #include <iostream> #include <string>
void zamienznak( std::string & tekst, std::string znak, std::string naco, int ileznakowusunac ) { std::size_t pozycja; do { pozycja = tekst.find( znak ); if( pozycja == std::string::npos ) return; else { tekst.erase( pozycja, ileznakowusunac ); tekst.insert( pozycja, naco ); } } while( pozycja != std::string::npos ); }
int main() { std::string tekst = "<b> to jest </b> testowy napis <b>:)"; std::cout << "Tekst przed zmiana:\n"; std::cout << tekst; std::string znak1 = " "; std::string znak2 = " "; std::string znak3 = "<"; std::string znak4 = "["; std::string znak5 = ">"; std::string znak6 = "]"; zamienznak( tekst, znak1, znak2, 2 ); zamienznak( tekst, znak3, znak4, 1 ); zamienznak( tekst, znak5, znak6, 1 ); std::cout << "\n\nTekst po zmianie:\n"; std::cout << tekst; return 0; }
Jak kolega poradził, zrezygnowałem z funkcji size_t pozycjaznaku( std::string wjakimtekscie, std::string znak ) . Wielkie dzięki za pomoc. Praca z debuggerem nie pojawiła się jeszcze w kursie, dlatego nawet nie wiedziałbym jak z niego korzystać:P Została jeszcze jedna rzecz, która mnie intryguje w tym kodzie. Otóż w obecnej formie, kiedy w kodzie występują linijki if( pozycja == std::string::npos ) return; wszystko działa jak należy. Jednak kiedy ich zabraknie program zamyka się po błędzie. Czy funkcja while( pozycja != std::string::npos ); nie powinna być samowystarczalna w tej postaci, to jest kończyć funkcję do , kiedy nowe znaki nie zostaną znalezione? |
|
carlosmay |
» 2017-07-14 15:53:40 Praca z debuggerem nie pojawiła się jeszcze w kursie, dlatego nawet nie wiedziałbym jak z niego korzystać:P |
... i się nie pojawi :P. Jest (chyba) tylko wzmianka, że coś takiego istnieje. Pytasz googla jak korzystać z debuggera w IDE, z którego korzystasz lub zaglądasz do dokumentacji tego IDE. Ewentualnie dla programów kompilowanych z cmd szukasz informacji w dokumentacji kompilatora. Czy funkcja while( pozycja != std::string::npos ); nie powinna być samowystarczalna w tej postaci |
Nie. Zastanów się, jaką wartość ma zmienna pozycja i gdzie nadajesz jej wartość. Po wyrzuceniu: if( pozycja == std::string::npos ) return;
zastaje do { pozycja = tekst.find( znak ); tekst.erase( pozycja, ileznakowusunac ); tekst.insert( pozycja, naco ); } while( pozycja != std::string::npos );
|
|
« 1 » |