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

R. 45 - zadanie domowe - pytanie do ppkt b

Ostatnio zmodyfikowano 2019-09-17 20:14
Autor Wiadomość
rottingham
Temat założony przez niniejszego użytkownika
» 2019-07-05 18:14:13
Hmm... A czy to rozwiązanie jest poprawne? Można mieć dwie niezależne listy, wystarczy dla drugiej listy utworzyć drugi wskaźnik przechowujący adres ostatniego elementu i przekazać go do funkcji. Dobrze myślę?

C/C++
#include <iostream>

using namespace std;

struct Lista
{
    Lista * ogon;
    int liczba;
};

// Wypisz wszystkie elementy listy
void wypisz( Lista * lista )
{
    // Przechodzenie po liœcie *rekurencyjnie*
    if( lista )
    {
        cout << lista->liczba << ", ";
        wypisz( lista->ogon );
    }
}

// Dodaj element na koniec listy
Lista * dodajKoniec( Lista *& lista, int liczba, Lista * ostatni )
{
    // Tworzymy nowy element listy
    Lista * nowy = new Lista;
    nowy->liczba = liczba;
    nowy->ogon = nullptr;
   
    // Dopisujemy na koniec
    if( lista )
    {
        ostatni->ogon = nowy;
        return nowy;
    }
    else
         lista = nowy;
   
    return lista;
}


// Usuwa listê
void zniszcz( Lista *& lista )
{
    while( lista )
    {
        Lista * tmp = lista;
        lista = lista->ogon;
        delete tmp;
    }
   
    lista = nullptr;
}


int main()
{
    Lista * lista = nullptr, * ostatni;
    int liczba;
    while( cin >> liczba && liczba )
         ostatni = dodajKoniec( lista, liczba, ostatni );
   
    wypisz( lista );
   
    zniszcz( lista );
}
P-174895
pekfos
» 2019-07-05 18:24:57
Powiedzmy że działa. A gdyby teraz do zadania dodać
C/C++
int main()
{
    int liczba;
    Lista * lista = nullptr;
    std::cout << "Podaj liczby, 0 lub blad konczy:\n";
   
    // Nie modyfikuj reszty funkcji main() od tego punktu
    while( std::cin >> liczba && liczba )
         dodajKoniec( lista, liczba );
   
    std::cout << "Koniec, oto liczby:\n";
    wypisz( lista );
    zniszcz( lista );
}
?
Albo lepiej, dodać do przykładu
C/C++
struct Wezel {...}; // Zamiast 'Lista'
typedef Wezel * Lista; // pewnie trzeba by gdzieś omówić typedef

void utworz( Lista & lista )
{
    lista = nullptr;
}

//..

int main()
{
    int liczba;
    Lista lista;
    utworz( lista )
    std::cout << "Podaj liczby, 0 lub blad konczy:\n";
   
    while( std::cin >> liczba && liczba )
         dodajKoniec( lista, liczba );
   
    std::cout << "Koniec, oto liczby:\n";
    wypisz( lista );
    zniszcz( lista );
}
i zakaz modyfikowania funkcji main(). Tylko czy to nie byłaby już za duża podpowiedź..? :/
P-174896
rottingham
Temat założony przez niniejszego użytkownika
» 2019-07-14 22:11:13
Czy
typedef Wezel * Lista;
 ma jakąś funkcjonalność wykraczającą poza zapewnienie większej przejrzystości?
P-174923
pekfos
» 2019-07-14 23:05:56
Jest też kwestia łatwiejszego utrzymania kodu. W kodzie jest używany typ Lista, więc gdybyś chciał zmienić co się kryje pod tym typem, to możesz to zrobić w definicji aliasu, a nie we wszystkich użyciach w kodzie.
P-174924
rottingham
Temat założony przez niniejszego użytkownika
» 2019-07-17 15:31:46
Powiem tak. Napisałem kod, który spełnia swoją funkcjonalność. Wiem, że to nie jest ten kod, na który Ty chciałeś mnie naprowadzić drugim przykładem.
Pojawiły mnie się trzy wątpliwości:
1. Czy ten kod jest dobry?
2. Czy dużo mi brakuje do rozwiązania, na które chciałeś mnie naprowadzić drugą podpowiedzią?
3. Czy funkcja
zniszcz()
, którą tutaj napisałem jest dobrze napisana? (różni się od tej w przykładzie - jest krótsza, ale mam wrażenie, że w pełni spełnia swoją - nomen omen - funkcję).

W drugiej podpowiedzi użyłeś funkcji
utworz()
. Nie za bardzo miałem pomysł na jej zastosowanie. A podejrzewam, że to ona odgrywa ważny element w tym drugim sposobie.

C/C++
#include <iostream>

using namespace std;

struct Lista
{
    int liczba;
    Lista * wezel;
} * ostatni = nullptr;

Lista * ogon( Lista * ostatni )
{
    return ostatni;
}

void dodajKoniec( Lista *& lista, int liczba )
{
    Lista * nowy = new Lista;
    nowy->liczba = liczba;
    nowy->wezel = nullptr;
   
    if( !lista )
    {
        lista = nowy;
        ostatni = nowy;
    }
    else
    {
        ogon( ostatni )->wezel = nowy;
        ostatni = nowy;
    }
}

void wypisz( Lista * lista )
{
    while( lista )
    {
        cout << lista->liczba << " ";
        lista = lista->wezel;
    }
}

void zniszcz( Lista *& lista )
{
    while( lista )
    {
        delete lista;
        lista = lista->wezel;
    }
   
    lista = nullptr;
}

int main()
{
    int liczba;
    Lista * lista0 = nullptr;
   
    cout << "Wprowadz liczbe... Blad lub 0 konczy wczytywanie: " << endl;
   
    while( cin >> liczba && liczba )
         dodajKoniec( lista0, liczba );
   
    wypisz( lista0 );
    zniszcz( lista0 );
}
P-174929
Monika90
» 2019-07-17 17:42:57
C/C++
struct Lista
{
    int liczba;
    Lista * wezel;
} * ostatni = nullptr;
Zmienna globalna, co gorsza ukryta w definicji klasy. Ponieważ jest to zmienna globalna, to znaczy że w programie może być tylko jedna lista na raz.

C/C++
delete lista;
lista = lista->wezel;
Użycie po zniszczeniu.
P-174930
rottingham
Temat założony przez niniejszego użytkownika
» 2019-07-31 15:34:45
gdybyś chciał zmienić co się kryje pod tym typem, to możesz to zrobić w definicji aliasu, a nie we wszystkich użyciach w kodzie.

Alias struktury Lista może mieć inne składowe niż ta struktura?
Jak to w takim razie zapisać? Próbowałem wielu sposobów, ale bezskutecznie.
P-174964
pekfos
» 2019-07-31 17:30:13
Alias struktury Lista może mieć inne składowe niż ta struktura?
I dlaczego miałoby to wciąż nazywać się "aliasem"? Oczywiście że nie może.
gdybyś chciał zmienić co się kryje pod tym typem, to możesz to zrobić w definicji aliasu, a nie we wszystkich użyciach w kodzie.
Przypuśćmy że masz w kodzie milion razy użyte float do trzymania wartości temperatury i miliard razy użyte float dla innych wartości fizycznych. Nagle stwierdzasz że akurat dla temperatury chcesz mieć long double, bo akurat jest za mała precyzja, a jak zmienisz wszystkie floaty, to nie wiem, RAM ci się skończy. Wtedy albo miałeś
C/C++
typedef float Temperatura;
i wystarczy typ zmienić w 1 miejscu, albo byś bardzo żałował że tak tego wcześniej nie zrobiłeś.

C/C++
#include <iostream>
using namespace std;

typedef int Lista;

void utworz( Lista & lista );
void dodajKoniec( Lista & lista, int liczba );
void wypisz( const Lista & lista );
void zniszcz( Lista & lista );

int main()
{
    int liczba;
    Lista lista;
    utworz( lista );
    std::cout << "Podaj liczby, 0 lub blad konczy:\n";
   
    while( std::cin >> liczba && liczba )
         dodajKoniec( lista, liczba );
   
    std::cout << "Koniec, oto liczby:\n";
    wypisz( lista );
    zniszcz( lista );
}
Ten kod skompiluje się dla dowolnego typu ukrytego pod nazwą Lista. int, float**, std::string, cokolwiek dla czego zapis Lista x; jest poprawny. Naturalnie, nie zlinkuje się, bo brakuje definicji tych funkcji.
P-174965
1 « 2 » 3 4 5 6
Poprzednia strona Strona 2 z 6 Następna strona