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

Modyfikowanie tekstu i sprawdzanie jego długości - jak użyć wielokrotnie metody find

Ostatnio zmodyfikowano 2017-06-20 13:33
Autor Wiadomość
Tinker
Temat założony przez niniejszego użytkownika
Modyfikowanie tekstu i sprawdzanie jego długości - jak użyć wielokrotnie metody find
» 2017-06-14 21:29:36
Witam wszystkich.
Aktualnie przerabiam rozdział 28 kursu. Próbowałem rozwiązać zadanie domowe w trochę inny sposób niż policzenie pozycji każdego znaku i "obrobienie ich" metodami stringa, ale napotkałem pewien problem. Długo szukałem przyczyny, dla której kod przestaje się wywoływać i ustaliłem, że każdy blok kodu, jeżeli umieszczony na samym początku funkcji, wywołuje się w konsoli, ale program "zatrzymuje się" przy następnym bloku. Nie do końca rozumiem zapis
size_t b = sTekst.find( "<b>" );
 na początku każdego bloku kodu, ale zauważyłem, że nie może być on powtarzany w taki sposób jak to zrobiłem, jednocześnie, gdy usuwałem tę linie z bloków, otrzymywałem błąd, np "spacja was not declared in this scope". Podpowie ktoś jak to poprawnie napisać? Myślałem o rozbiciu tego na 3 oddzielne funkcje, ale trochę bym się oddalił od narzuconego sposobu rozwiązania.  Wrzucam kod poniżej:

C/C++
#include <iostream>
#include <string>

using namespace std;

string konwertuj( string & sTekst )
{
    string sWynik;
   
   
   
    { //blok zamieniający <b> na [b]
        size_t b = sTekst.find( "<b>" );
        do
        {
            size_t b = sTekst.find( "<b>" );
            if( b != string::npos )
            {
                sTekst.erase( b, 3 );
                cout << sTekst << endl;
                sTekst.insert( b, "[b]" );
                cout << sTekst << endl;
            }
           
        } while( b != string::npos );
       
    }
   
    { //blok zamieniający </b> na [/b]
        size_t bSlash = sTekst.find( "</b>" );
        do
        {
            size_t bSlash = sTekst.find( "</b>" );
            if( bSlash != string::npos )
            {
                sTekst.erase( bSlash + 4, 4 );
                sTekst.insert( bSlash, "[/b]" );
               
                cout << sTekst << endl;
            }
           
        } while( bSlash != string::npos );
       
    }
   
    { //blok usuwający wielokrotnie powtarzającą się spację
        size_t spacje = sTekst.find( "  " );
        do
        {
            size_t spacje = sTekst.find( "  " );
            if( spacje != string::npos )
            {
                sTekst.erase( spacje, 2 );
                cout << sTekst << endl;
            }
        } while( spacje != string::npos );
       
    }
    sWynik = sTekst;
   
    return sWynik;
}
int main()
{
    string tekst = "<b>to jest </b> testowy       napis     <b>:)";
   
    cout << konwertuj( tekst ) << endl;
    cout << tekst << endl;
    return 0;
}


P-162559
pekfos
» 2017-06-14 22:03:37
C/C++
size_t b = sTekst.find( "<b>" ); // Zmienna b_1
do
{
    size_t b = sTekst.find( "<b>" ); // Zmienna b_2 (zasłania b_1)
   
    //
    // (operacje na b_2)
    //
   
} // Koniec zasięgu b_2
while( b != string::npos ); // b_1

P-162560
Tinker
Temat założony przez niniejszego użytkownika
» 2017-06-14 22:27:10
Czyli cały kod do przeróbki? Bo nie widzę żadnego prostego wyjścia.
Napisałem to z użyciem pętli for. Nie do końca mnie to satysfakcjonuje, bo przy tej pętli trzeba było policzyć ile razy dana operacja miała być wykonana. Przy pierwszym rozwiązaniu wszystko było "zautomatyzowane", no prawie... :)
P-162562
pekfos
» 2017-06-15 02:21:08
Napisałem to z użyciem pętli for. Nie do końca mnie to satysfakcjonuje, bo przy tej pętli trzeba było policzyć ile razy dana operacja miała być wykonana.
Open your mind
C/C++
for( size_t off = 0;( off = str.find( "a", off ) ) != std::string::npos; ++off )

Czyli cały kod do przeróbki?
Nie definiuj dwóch zmiennych, tylko jedną.
P-162566
Tinker
Temat założony przez niniejszego użytkownika
» 2017-06-19 18:34:22
Dzięki za fajne wytłumaczenie.
Wklejam zmodyfikowany kod:
C/C++
#include <iostream>
#include <string>

using namespace std;

string konwertuj( string & sTekst )
{
    string sWynik;
   
    for( size_t b = 0;( b = sTekst.find( "<b>", b ) ) != string::npos; b++ )
    {
        sTekst.erase( b, 3 );
        cout << sTekst << endl;
        sTekst.insert( b, "[b]" );
        cout << sTekst << endl;
    }
   
    for( size_t bSlash = 0;( bSlash = sTekst.find( "</b>", bSlash ) ) != string::npos; bSlash++ )
    {
        sTekst.erase( bSlash, 4 );
        cout << sTekst << endl;
        sTekst.insert( bSlash, "[/b]" );
       
        cout << sTekst << endl;
    }
   
    for( size_t spacje = 0;( spacje = sTekst.find( "  " ) ) != string::npos; ++spacje )
    {
        sTekst.erase( spacje, 2 );
        cout << sTekst << endl;
    }
   
    sWynik = sTekst;
   
    return sWynik;
}
int main()
{
    string tekst = "<b>to jest </b> testowy       napis     <b>:)";
   
    cout << konwertuj( tekst ) << endl;
   
    return 0;
}
Mam jeszcze kilka pytań:
- jak interpretować frazę
size_t
? jest to typ danych? jakich? nie kojarzę takiego typu, rozjaśnisz trochę? :)
- w ostatniej pętli nie użyłem offsetu w części b, bo gdy się tam znajdował, to program nie usuwał wszystkich podwójnych spacji, wiesz może dlaczego?
- no i jeszcze pytanie o inkrementacje w każdej z pętli: czy rzeczywiście zachodzi?
P-162689
jankowalski25
» 2017-06-19 20:26:48
jak interpretować frazę
size_t
?
Zgodnie z » Kurs C++ » Poziom 3Wyszukiwanie frazy w tekście lekcja » Klasa std::string - metoda find na razie możesz to w uproszczeniu traktować jako
unsigned int
, chociaż tak naprawdę zamiast
int
 zwykle jest tam coś innego, zależnie od implementacji (między innymi dlatego, że
int
 może nie zmieścić wszystkiego, jeśli na przykład w programie 64-bitowym będzie zajmował 32 bity) ale w tym momencie może lepiej się w to nie wgłębiaj. Na chwilę obecną wystarczy wiedzieć, że to jest jakiś typ danych, który przechowuje liczbę całkowitą nieujemną.
program nie usuwał wszystkich podwójnych spacji, wiesz może dlaczego?
Przeanalizuj krok po kroku co się stanie, gdy zechcesz usunąć kilka spacji pod rząd.
inkrementacje w każdej z pętli: czy rzeczywiście zachodzi?
Jak wyżej. Zajrzyj do » Kurs C++ » Poziom 2Pętla for lekcja » Składnia pętli for. Jeśli dla danego tekstu rozwiniesz prawidłowo pętlę instrukcja po instrukcji (ewentualnie w razie wątpliwości użyjesz debuggera), to zobaczysz krok po kroku co, gdzie i jak się wykonuje.
P-162699
pekfos
» 2017-06-19 20:35:34
w ostatniej pętli nie użyłem offsetu w części b, bo gdy się tam znajdował, to program nie usuwał wszystkich podwójnych spacji, wiesz może dlaczego?
Poza tym, że podany kod do tego nie służył? To był przykład do analizy, nie skopiowania. Moja pętla nie sprawdza 2 razy tego samego miejsca, a gdy ze stringa tylko usuwasz, to się nie sprawdzi. Powinieneś usunąć inkrementację, nie offset.
P-162700
Tinker
Temat założony przez niniejszego użytkownika
» 2017-06-20 13:33:51
Chcę się upewnić, że dobrze to rozumiem. Zostawiając inkrementację, powoduję że, offset w drugim kroku pętli zostanie zwiększony o 1?
C/C++
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string sTekst = "bbbb aaaaaa";
    for( size_t spacje = 0;( spacje = sTekst.find( "aaa", spacje ) ) != string::npos; spacje++ ) /*w drugim kroku size_t spacje przyjmie wartość 5+1?*/
    {
        sTekst.erase( spacje, 3 );
        cout << spacje << endl;
    }
    return 0;
}
P-162716
« 1 »
  Strona 1 z 1