Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Rozdział 28] Czy da się to napisać prościej?

Ostatnio zmodyfikowano 2015-11-15 20:01
Autor Wiadomość
Deivid
Temat założony przez niniejszego użytkownika
[Rozdział 28] Czy da się to napisać prościej?
» 2015-11-14 23:38:40
Witajcie, właśnie rozwiązałem zadanie domowe. Mam kilka pytań:
1. Czy o takie rozwiązanie chodziło? (patrz kod programu)
2. Czy może nie trzeba było sprawdzać pozycji frazy tylko wpisać na sztywno obliczając ją sobie (niby byłoby łatwiej)
3. Dlaczego coś takiego działa:
C/C++
do
{
    sTekst.erase( znalezione_spacje_x2, dlugosc_spacji_x2 );
    znalezione_spacje_x2 = sTekst.find( spacja_x2 );
} while( znalezione_spacje_x2 != string::npos );

zgodnie z rozdziałem 27 brakuje tutaj:
C/C++
do
{
    sTekst.erase( znalezione_spacje_x2, dlugosc_spacji_x2 );
    znalezione_spacje_x2 = sTekst.find( spacja_x2, znalezione_spacje_x2 + spacja_x2.size() );
} while( znalezione_spacje_x2 != string::npos );

Ktoś pomoże zrozumieć?
Edit. // Na chłopski rozum pojmuję to tak. Że w tym programie po prostu nie muszę korzystać z dodatków funkcji .find, przydają się one tylko gdy muszę te dane wypisać na ekran, a gdy potrzebuję je wewnątrz programu to .find zadziała w zwykłej pętli.

Kod programu:
C/C++
/*
Napisz program, który z podanego łańcucha znaków usunie powtarzające się spacje
występujące obok siebie i zastąpi wszystkie znaczniki <b> oraz </b> znacznikami
[b] oraz [/b]. Tekst, który powstanie w wyniku przeprowadzenia wspomnianych
operacji wypisz na ekran. Przykładowy fragment aplikacji, który możesz wykorzystać:

Oczekiwane wyjście programu:
[b]to jest [/b] testowy napis [b]:)
*/
#include <iostream>
#include <string>
using namespace std;


std::string konwertuj( std::string & sTekst )
{
    std::string sWynik;
   
    // USUWAMY PODWOJNE SPACJE
    string spacja_x2 = "  "; //deklaracja zmiennej ktorej bedziemy szukac
    size_t dlugosc_spacji_x2 = spacja_x2.size(); //sprawdzenie ile znakow zawiera zmienna
    size_t znalezione_spacje_x2 = sTekst.find( spacja_x2 ); //zmienna znajduje sie na pozycji ...
    do
    {
        sTekst.erase( znalezione_spacje_x2, dlugosc_spacji_x2 );
        znalezione_spacje_x2 = sTekst.find( spacja_x2 );
    } while( znalezione_spacje_x2 != string::npos );
   
    // ZAMIANA <b> na [b]
    string znak_nierownosci_b = "<b>";
    string znak_kwadratu_b = "[b]";
    size_t dlugosc_znaku_nierownosci_b = znak_nierownosci_b.size();
    size_t znalezione_znaki_nierownosci_b = sTekst.find( znak_nierownosci_b );
    do
    {
        sTekst.erase( znalezione_znaki_nierownosci_b, dlugosc_znaku_nierownosci_b );
        sTekst.insert( znalezione_znaki_nierownosci_b, znak_kwadratu_b );
        znalezione_znaki_nierownosci_b = sTekst.find( znak_nierownosci_b );
       
    } while( znalezione_znaki_nierownosci_b != string::npos );
   
    // ZAMIANA </b> na [/b]
    string znak_nierownosci2_b = "</b>";
    string znak_kwadratu2_b = "[/b]";
    size_t dlugosc_znaku_nierownosci2_b = znak_nierownosci2_b.size();
    size_t znalezione_znaki_nierownosci2_b = sTekst.find( znak_nierownosci2_b );
    do
    {
        sTekst.erase( znalezione_znaki_nierownosci2_b, dlugosc_znaku_nierownosci2_b );
        sTekst.insert( znalezione_znaki_nierownosci2_b, znak_kwadratu2_b );
        znalezione_znaki_nierownosci2_b = sTekst.find( znak_nierownosci2_b );
       
    } while( znalezione_znaki_nierownosci2_b != string::npos );
   
   
   
    sWynik = sTekst;
    return sWynik;
}
int main()
{
    std::string tekst = "<b>to jest </b> testowy       napis     <b>:)";
    std::cout << konwertuj( tekst ) << std::endl;
   
   
    return 0;
}
P-140141
pekfos
» 2015-11-15 00:03:40
Czy o takie rozwiązanie chodziło?
Jeśli działa dla dowolnego tekstu, to tak.

Dlaczego coś takiego działa:
C/C++
do
{
    sTekst.erase( znalezione_spacje_x2, dlugosc_spacji_x2 );
    znalezione_spacje_x2 = sTekst.find( spacja_x2 );
} while( znalezione_spacje_x2 != string::npos );

zgodnie z rozdziałem 27 brakuje tutaj:
C/C++
do
{
    sTekst.erase( znalezione_spacje_x2, dlugosc_spacji_x2 );
    znalezione_spacje_x2 = sTekst.find( spacja_x2, znalezione_spacje_x2 + spacja_x2.size() );
} while( znalezione_spacje_x2 != string::npos );

W rozdziale 27 w tej pętli nie było usuwania. Jak chcesz znaleźć wszystkie wystąpienia danej frazy, zaczynasz następne wyszukiwanie od końca poprzedniej znalezionej frazy, by nie znajdywać jej na nowo w nieskończoność. Tu fraza jest usuwana, więc nie znajdziesz tego samego wystąpienia 2 razy.
P-140144
Deivid
Temat założony przez niniejszego użytkownika
» 2015-11-15 00:07:50
Tak, działa. Jednak kiedyś w rozdziale losowania bez powtórzeń źle zrozumiałem polecenie i wykonałem złe losowanie (do dziś pamiętam mój błąd, tak więc wolę się upewnić i tutaj). Chce się uczyć poprawnie pisać kod, dlatego też pytam czy da się to napisać prościej / mniejszą ilością kodu.
Co do tego mojego drugiego pytania dlaczego to działa, mniej więcej rozumiem. Ale jeszcze nie do końca, heh. Jeśli patrzę na rozdziały przy pisaniu programu to jakoś ogarnę, może jeśli kiedyś znajdę pracę w tej branży to wyćwiczę pracę z tekstem :)

Edit. Chociaż jak przeczytałem kilka razy Twoją wypowiedź zaczyna mi się robić coraz jaśniej w tej pustej głowie o co chodzi. Dzięki :)
czasami się przydaje, jednak ten przypadek nie zostanie omówiony ponieważ praktycznego zastosowania w swoich programach nie znajdziesz z wiedzą, którą posiadasz na chwilę obecną. Przejdźmy teraz do przykładu:
 - Niestety autor kursu nie przewidział, że jednak dokładne wyjaśnienie się przyda, bo przy następnej lekcji już się wykorzystało tą wiedzę.
P-140145
j23
» 2015-11-15 10:15:18
A propos szukania spacji:
znalezione_spacje_x2 = sTekst.find( spacja_x2 );
tak zrób, będzie bardziej optymalnie:
znalezione_spacje_x2 = sTekst.find( spacja_x2, znalezione_spacje_x2 );
Nie będziesz przeszukiwał tekstu od początku, tylko od miejsca znalezienia spacji.

Tu wersja najoptymalniejsza:
C/C++
auto i1 = sTekst.begin();
auto i2 = i1;
auto i3 = sTekst.end();


while( i1 != i3 )
{
    * i2 = * i1++;
    if( * i2 == ' ' )
         while( i1 != i3 && * i1 == ' ' ) ++i1;
   
    ++i2;
}

sTekst.erase( i2, i1 );
Tylko jedno erase z końca sTekst (co nie jest bez znaczenia) dla wszystkich spacji.
P-140146
Deivid
Temat założony przez niniejszego użytkownika
» 2015-11-15 20:01:48
Dzięki za kolejną wskazówkę jak prawidłowo wykorzystać funkcję .find(). Jednak następnego fragmentu Twojego postu nie rozumiem, nie przerobiłem jeszcze wskaźników, gdy już się ich nauczę z pewnością wrócę tutaj aby przeanalizować Twój kod.
P-140189
« 1 »
  Strona 1 z 1