Problemy z licznikiem petli for.

0

Pisze sobie taki mały programik kompresujący ciąg znaków metodą LZ78. Niestety kolejnych prównaniach w petli for licznik o nazwie index przy pozytywnym wyniku ifa wypluwa 0 a w ostatnim przypadku 0, zupełnie nie wiem dlaczego. Co robię nie tak?

#include <iostream>

using namespace std;

int main()
{
    int wy1, n, i=0, index;
    string slowo[8]={"d","d","d","d","d","d","d","d"};
    string S, x1, x2, we, wy2;
    S = "abbbcaabbcbbcaaac"; //lancuch do wczytania
    n = S.length();
    while (i < n)
    {

        for( index = 0; index<=7; index++)
        {
            x1 = S[i];
            x2 = slowo[index];
            cout << "Taki jest index bez porownan: " << index << endl;
            if( x1 == x2 )
            {
                cout << "Taki jest index w pozytywnym porownaniu: " << index << endl;
                wy1 = index;
                wy2 = S[i++];
                we = S[i]+wy2;
                i++;
            }
            else
            {
                //cout << "Taki jest index w negatywnym porownaniu: " << index << endl;
                we = S[i];
                wy1 = 0;
                wy2 = S[i];
            };
            slowo[index] = we;
        }
        cout << "Wejscie: " << we << " Wyjscie: " << wy1 << wy2 << " Indeks: " << i << " Slowo: " << we << endl;
        i++;
    }
    return 0;
0

Napisz dokładniej o co ci chodzi, bo u siebie to skompilowałem i nic nadzwyczajnego nie znalazłem.
user image

0
  1. brakuje
#include <string>

Niestety kolejnych prównaniach w petli for licznik o nazwie index przy pozytywnym wyniku ifa wypluwa 0 a w ostatnim przypadku 0
Nie rozumiem. Popraw pytanie.

0

Oj kurde coś wcześniej mi dziwnie wywalało ale się może pomyliłem bo indeks w poza ifem był inny a w ifie już inny, ale teraz widzę jest tak samo więc okey :) Nie wiem tylko czego teraz nie wyświetla mi wejścia i wyjścia gdy w ifie warunek jest spełniony.

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int wy1, n, i=0, index;
    string slowo[8]={"d","d","d","d","d","d","d","d"};
    string S, x1, x2, we, wy2;
    S = "abbbcaabbcbbcaaac"; //lancuch do wczytania
    n = S.length();
    while (i < n)
    {

        for( index = 0; index<=7; index++)
        {
            x1 = S[i];
            x2 = slowo[index];
            if( x1 == x2 )
            {
                wy1 = index;
                wy2 = S[i++];
                we = S[i]+wy2;
                i++;
            }
            else
            {
                we = S[i];
                wy1 = 0;
                wy2 = S[i];
            };
            slowo[index] = we;
        }
        cout << "Wejscie: " << we << " Wyjscie: " << wy1 << wy2 << " Indeks: " << i << " Slowo: " << we << endl;
        i++;
    }
    return 0;
}

0

Nie wiem tylko czego teraz nie wyświetla mi wejścia i wyjścia gdy w ifie warunek jest spełniony.

:-S

okej, wynik mamy taki:

Wejscie: a Wyjscie: 0a Indeks: 0 Slowo: a
Wejscie: b Wyjscie: 0b Indeks: 1 Slowo: b
Wejscie: c Wyjscie: 0c Indeks: 4 Slowo: c
Wejscie: a Wyjscie: 0a Indeks: 5 Slowo: a
Wejscie: b Wyjscie: 0b Indeks: 8 Slowo: b
Wejscie: c Wyjscie: 0c Indeks: 9 Slowo: c
Wejscie: b Wyjscie: 0b Indeks: 10 Slowo: b
Wejscie: a Wyjscie: 0a Indeks: 13 Slowo: a
Wejscie: c Wyjscie: 0c Indeks: 16 Slowo: c

a jaki być powinien?

0

Np gdy dopiszę w środku if wyświetlanie:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int wy1, n, i=0, index;
    string slowo[8]={"d","d","d","d","d","d","d","d"};
    string S, x1, x2, we, wy2;
    S = "abbbcaabbcbbcaaac"; //lancuch do wczytania
    n = S.length();
    while (i < n)
    {

        for( index = 0; index<=7; index++)
        {
            x1 = S[i];
            x2 = slowo[index];
            if( x1 == x2 )
            {
                wy1 = index;
                wy2 = S[i++];
                we = S[i]+wy2;
                cout << "Wejscie tutaj jest rowne: " << we << " a wyjscie " << wy1 << wy2 << endl;
                i++;
            }
            else
            {
                we = S[i];
                wy1 = 0;
                wy2 = S[i];
            };
            slowo[index] = we;
        }
        cout << "Wejscie: " << we << " Wyjscie: " << wy1 << wy2 << endl;
        i++;
    }
    return 0;
}

to pokazuja już się wyniki:

Wejscie: a Wyjscie: 0a
Wejscie: b Wyjscie: 0b
Wejscie tutaj jest rowne: bb a wyjscie 0b
Wejscie: c Wyjscie: 0c
Wejscie: a Wyjscie: 0a
Wejscie tutaj jest rowne: ba a wyjscie 0a
Wejscie: b Wyjscie: 0b
Wejscie: c Wyjscie: 0c
Wejscie: b Wyjscie: 0b
Wejscie tutaj jest rowne: cb a wyjscie 0b
Wejscie: a Wyjscie: 0a
Wejscie tutaj jest rowne: aa a wyjscie 1a
Wejscie: c Wyjscie: 0c

Dlaczego tak normalnie się nie wyświetlają?

0

Może nie jesteś tego świadom, ale właśnie zadałeś pytanie które sugeruje że nie interesuje Cię jak program działa,
chcesz tylko żeby ktoś Ci to wytłumaczył bo musisz zanotować na zaliczenie...

Podstawa w programowaniu to umiejętność czytania czyjegoś kodu, w tym wypadku pytasz o zupełne podstawy.

Uruchom debuggera, prześledź program i wróć jeśli znajdziesz coś ciekawego w tych dwóch pętelkach.

http://www.ehow.com/how_6123851_use-visual-c__-debugger.html

0

Ja się dopiero uczę ale to chyba każdy kiedyś zaczynał ;) Nie chodzi mi o zaliczenie lecz o nauczenie się, są gotowce przecież, mógłbym ściągnąć z neta, lekko pozmieniać i już ale nie o to tu chodzi. Wg mojego rozumowania to jest tak, że program wchodzi do while potem do for, w nim robi porównanie i odpowiednio modyfikuje dane a potem wychodzi z for, wyświetla co ma wyświetlić, zwiększa licznik i i potem znowu od początku for i tak w koło Macieju aż się while skończy :) Nawet przyszło mi do głowy debuggowanie lecz jakoś nie mogę się w tym połapać. Nie mam Windowsa więc nie skorzystam z Twojego poradnika. Programuję w Qt Creatorze na Linuksie.

2

Eee... dodałeś wyświetlanie, i zaczęło się wyświetlać, a gdy tego nie było to nie wyświetlało…

No booo... to tak jakoś już jest, że jak czegoś nie ma to tak jakby tego nie było...

:-\

0
Pawel Jaworski napisał(a):

Ja się dopiero uczę ale to chyba każdy kiedyś zaczynał ;) Nie chodzi mi o zaliczenie lecz o nauczenie się, są gotowce przecież, mógłbym ściągnąć z neta, lekko pozmieniać i już ale nie o to tu chodzi. Wg mojego rozumowania to jest tak, że program wchodzi do while potem do for, w nim robi porównanie i odpowiednio modyfikuje dane a potem wychodzi z for, wyświetla co ma wyświetlić, zwiększa licznik i i potem znowu od początku for i tak w koło Macieju aż się while skończy :) Nawet przyszło mi do głowy debuggowanie lecz jakoś nie mogę się w tym połapać. Nie mam Windowsa więc nie skorzystam z Twojego poradnika. Programuję w Qt Creatorze na Linuksie.

Na Linuksie to nie może być dużo trudniejsze.
http://doc.qt.digia.com/qtcreator-snapshot/creator-debugging.html

Bez debuggera daleko nie zajedziesz, więc naucz się go obsługiwać.
Gdybyś jednak z jakichś przyczyn nie mógł go zainstalować, to nawet wtedy możesz debugować-przez-wyświetlanie.
Czyli zapisywać w odpowiednim miejscu stan zmiennych na ekran lub do pliku.

0

Podszedłem do problemu od nowa, napisałem coś takiego:

#include <iostream>

using namespace std;
string S = "abbbcaabbcbbcaaac";
int n = S.length();
string M;
int i, j, m, p, k, x;
bool wws;

int main()
{
    cout << "Kompresuje dane metoda LZ78" << endl;
    string Z[n];
    Z[0] = S[0];
    cout << "Wyjscie: (0, " << Z[0] << ")" << endl;
    for(i=1; i<=n; i++)
    {
        cout << "Wartosc i to: " << i << endl;
        for(p=n; p>=i; p--)
        {
            cout << " Wartosc p to: " << p << endl;
            wws=false;
            M = S.substr(i,p);
            for(k=1; k<=n; k++)//przeszukiwanie slownika
            {
                cout << "  Wartosc k to: " << k << endl;
                cout << "  Wartosc M to: " << M << endl;
                //cout << "  Wartosc Z[k] to: " << Z[k] << endl; // jezeli odkomentuje ta linijke program się zawiesza
                if(M == Z[k])
                {
                    cout << "Wyjscie: (" << k << ", " << S[p];
                    for(j=1; j<=n; j++)
                    {
                        if(Z[j].length()==0)
                        {
                            Z[j]=M;
                            cout << "Do slownika dodano indeks: " << j << " slowo: " << Z[j] << endl;
                            j=n;
                        }
                    }
                    m=M.length();
                    i=i+m-1;    //indeks zwiekszony o dlugosc wczytanego wyrazu, bez jednego znaku, ktory zostal dodany w petli for
                    wws=true;   //slowo wystepuje w slowniku
                }
            }
            if(wws=false)
            {
                cout << "Wyjscie: (0, " << S[p] << ")" << endl;
                if(Z[j].length() == 0)
                {
                    Z[j] = S[i];
                    cout << "Do slownika dodano indeks: " << j << " slowo: " << Z[j] << endl;
                    j=n;
                }
            }

            cout << endl << "Podaj x: "; //to jest dla zatrzymania
            cin >> x;

        }

    }
    return 0;
}

Z tym, że program się wykonuje bez końca. Chciałem przeanalizować działanie więc dałem cin dla zatrzymania oraz wyświetlałem sobie wszystkie zmienne. Niestety jak chciałem wyświetlić Z[k] program mi się od razu zawiesza, wie ktoś dlaczego?

0

Ale niestety dalej nie rozumiem dlaczego przy niespełnieniu warunków pętli wyniki są wyświetlane na końcu a przy spełnieniu już nie. Mi się wydaje, że powinny się wyświetlać w obu przypadkach, przecież cout jest poza całą pętlą for.

0

@pawel Jaworski moja szklana kula jest dziś mętna, ale chyba zaczynam rozumieć w czym problem. Otóż to co wyświetlasz jako "wejście" i "wyjście" to jest zupełnie co innego niż to co porównujesz ifem. W efekcie nijak to nie jest spójne z tym czego być oczekiwał.

2
    while (i < n)
    {
        for( index = 0; index<=7; index++)
        {
                // CIACH
        }

        cout << "Wejscie: " << we << " Wyjscie: " << wy1 << wy2 << " Indeks: " << i << " Slowo: " << we << endl;

        i++;
    }

Skoro wyświetlanie jest ZA pętlą, to jasne jest, że będzie PO wykonaniu się całej pętli.

0

Ale skoro pętla się wykonała (obojętnie czy if został spełniony czy nie) to zmienne we, wy1, wy2 zostały nadpisane, czy nie? Skoro tak to dlaczego raz wyświetli a raz nie?

0

Wewnątrz pętli for inkrementujesz licznik pętli while (robisz i++). Dlatego pojawia się mniej niż n wyników.

0

Podszedłem do problemu od nowa, napisałem coś takiego:

#include <iostream>

using namespace std;
string S = "abbbcaabbcbbcaaac";
int n = S.length();
string M;
int i, j, m, p, k, x;
bool wws;

int main()
{
    cout << "Kompresuje dane metoda LZ78" << endl;
    string Z[n];
    Z[0] = S[0];
    cout << "Wyjscie: (0, " << Z[0] << ")" << endl;
    for(i=1; i<=n; i++)
    {
        cout << "Wartosc i to: " << i << endl;
        for(p=n; p>=i; p--)
        {
            cout << " Wartosc p to: " << p << endl;
            wws=false;
            M = S.substr(i,p);
            for(k=1; k<=n; k++)//przeszukiwanie slownika
            {
                cout << "  Wartosc k to: " << k << endl;
                cout << "  Wartosc M to: " << M << endl;
                //cout << "  Wartosc Z[k] to: " << Z[k] << endl; // jezeli odkomentuje ta linijke program się zawiesza
                if(M == Z[k])
                {
                    cout << "Wyjscie: (" << k << ", " << S[p];
                    for(j=1; j<=n; j++)
                    {
                        if(Z[j].length()==0)
                        {
                            Z[j]=M;
                            cout << "Do slownika dodano indeks: " << j << " slowo: " << Z[j] << endl;
                            j=n;
                        }
                    }
                    m=M.length();
                    i=i+m-1;    //indeks zwiekszony o dlugosc wczytanego wyrazu, bez jednego znaku, ktory zostal dodany w petli for
                    wws=true;   //slowo wystepuje w slowniku
                }
            }
            if(wws=false)
            {
                cout << "Wyjscie: (0, " << S[p] << ")" << endl;
                if(Z[j].length() == 0)
                {
                    Z[j] = S[i];
                    cout << "Do slownika dodano indeks: " << j << " slowo: " << Z[j] << endl;
                    j=n;
                }
            }

            cout << endl << "Podaj x: "; //to jest dla zatrzymania
            cin >> x;

        }

    }
    return 0;
}

Z tym, że program się wykonuje bez końca. Chciałem przeanalizować działanie więc dałem cin dla zatrzymania oraz wyświetlałem sobie wszystkie zmienne. Niestety jak chciałem wyświetlić Z[k] program mi się od razu zawiesza, wie ktoś dlaczego?

0

Weź może rozbij to na osobne funkcje, np. szukanie w słowniku, dodanie do słownika itp.
bo tylu pętli i warunków na raz wyraźnie nie ogarniasz.

0

Też o tym myślałem ale jakoś udało się bez. Wstawiam działający kod:

#include <iostream>

using namespace std;

string R, s, S = "abbbcaabbcbbcaaac";
int m, l, j, i, k, n = S.length();
bool wws;

int main()
{
    string Z[n];
    //idziemy po kolei z ciagiem znakow
    for(i=0; i<n; i++)
    {
        wws=false;
        //porownywanie z kazdym slowem w slowniku
        for(k=0; k<n; k++)
        {
            s=S[i];
            if(s==Z[k])
            {

                //szukam najdluzszego slowa pasujacego do ktoregos wyrazu ze slownika
                for(j=n; j>i; j--)
                {
                    s=S.substr(i,j-i);
                    for(l=0; l<n; l++)
                    {
                        if(s==Z[l])
                        {
                            m=s.length();
                            s=s+S[m+i];
                            //wstawianie wyrazu do slownika na wolne miejsce
                            for(k=0; k<n; k++)
                            {
                                if(Z[k].length()==0)
                                {
                                    Z[k]=s;
                                    k=n;
                                }
                            }
                            cout << "(" << l << "," << S[j] << ")" << endl;

                            l=n;
                            j=i;
                            i=i+m;
                            wws=true;
                        }

                    }
                }
            }

        }
        if(wws==false)
        {
            //wstawianie wyrazu do slownika na wolne miejsce
            for(k=0; k<n; k++)
            {
                if(Z[k].length()==0)
                {
                    Z[k]=s;
                    k=n;
                }
            }
            cout << "(0," << s << ")" << endl;
        }
    }

    //wstawianie wyrazu do slownika na wolne miejsce
    for(k=0; k<n; k++)
    {
        if(Z[k].length()==0)
        {
            Z[k]=s;
            k=n;
        }
    }

    return 0;
}

0
Pawel Jaworski napisał(a):

Też o tym myślałem ale jakoś udało się bez.

  • jeśli piszesz to na zaliczenie to głupio byłoby z tego powodu dostać jedynkę - mimo że program działa
  • jeśli piszesz to w pracy, to jest to słaby kod
  • jeśli piszesz to dla siebie to za pół roku nie będziesz wiedział o co w tym chodzi

1 użytkowników online, w tym zalogowanych: 0, gości: 1