Uso delle classi C++

di il
7 risposte

Uso delle classi C++

Premesso di aver risolto da solo il problema del precedente thread, ora mi trovo in questa situazione: ho fatto due realizzazioni diverse di lista concatenata, una senza usare le classi che funziona correttamente (anche la funzione di inserimento), ma nel momento in cui aggiungo la classe Lista, l'unica funzione che non funge è quella di inserimento: di seguito riporto codice e chiarimento sull'errore che non riesco a capire

nella prima, tutto ok
#include <iostream>

using namespace std;

/* REALIZZAZIONE SENZA CLASSI */

typedef int Tinfo;

struct nodo{
    Tinfo valore;
    struct nodo *next;
};

typedef struct nodo Nodo;
typedef Nodo *Lista;

Lista creaLista();
Nodo* inserisciElemento(Lista, Tinfo);
void stampaLista(Lista);
Tinfo leggi(Lista);
Nodo* succLista(Lista);

int main()
{
    Lista lista;
    Tinfo info;
    lista = creaLista();
    int n;
    cout << "Quanti elementi vuoi inserire? ";
    cin >> n;
    for(int i=0; i<n; i++){
        cout << "Valore n." << i << ": ";
        cin >> info;
        lista = inserisciElemento(lista, info);
    }
    stampaLista(lista);
    cout << "Inserisci un elemento da aggiungere: ";
    cin >> info;
    lista = inserisciElemento(lista, info);
    stampaLista(lista);
    cout << endl;
    return 0;
}

Lista creaLista(){
    return NULL;
}

Tinfo leggi(Lista lista){
    Tinfo valore;
    bool trovato = false;
    cout << "Inserisci un valore: ";
    cin >> valore;
    Nodo *corrente, *precedente;
    precedente = NULL;
    corrente = lista;
    while(corrente != NULL && !trovato){
        precedente = corrente;
        corrente = corrente->next;
        if(valore == corrente->valore){
            trovato = true;
        }
    }
    if(trovato){
        return valore;
    }else{
        cout << "Non trovato" << endl;
    }
}

Nodo* inserisciElemento(Lista lista, Tinfo info){
    Nodo *precedente, *corrente, *nuovo_nodo;
    corrente = lista; // corrente punta al primo nodo della lista
    precedente = NULL; // precedente punta a NULL perché il primo elemento non ha un predecessore
    while(corrente != NULL && info > corrente->valore){ // scorri finché l'elemento da inserire non è maggiore di quello presente nel nodo corrente
        precedente = corrente;
        corrente = corrente->next;
    }
    nuovo_nodo = new Nodo;
    nuovo_nodo->valore = info;
    if(precedente == NULL){
        nuovo_nodo->next = lista;
        lista = nuovo_nodo;
        return lista;
    }else{
        precedente->next = nuovo_nodo;
        nuovo_nodo->next = corrente;
        return lista;
    }
}

void stampaLista(Lista lista){
    Nodo *corrente;
    corrente = lista;
    while(corrente != NULL){
        cout << "Valore: " << corrente->valore << endl;
        corrente = corrente->next;
    }
}
nella seconda, mi da un errore strano sulla funzione di inserimento: dice che non mi riconosce il tipo "Nodo", nonostante l'abbia definito, mi dà errori come "invalide use of incomplete type 'Nodo":
#include <iostream>

using namespace std;

/* REALIZZAZIONE CON CLASSI */

typedef int tipoelem;
typedef struct nodo Nodo;
typedef Nodo *lista;

class Lista{

public:

    lista creaLista();
    bool listaVuota(lista) const;
    Nodo* insLista(lista, tipoelem);

private:

    struct nodo{
        tipoelem valore;
        struct nodo *next;
    };

};

int main()
{
    Lista L;
    lista l = L.creaLista();
    int n;
    cout << "Quanti valori vuoi inserire? ";
    cin >> n;
    tipoelem e;
    for(int i=0; i<n; i++){
        cout << "Inserisci un valore: ";
        cin >> e;
        l = L.insLista(l, e);
    }
    return 0;
}

lista Lista::creaLista(){
    return NULL;
}

bool Lista::listaVuota(lista l) const{
    return (l == NULL);
}

Nodo* Lista::insLista(lista lista, tipoelem e){
    Nodo *precedente, *corrente, *nuovo_nodo;
    corrente = lista;
    precedente = NULL;
    while(corrente != NULL && e > corrente->valore){
        precedente = corrente;
        corrente = corrente->next;
    }
    nuovo_nodo = new Nodo;
    nuovo_nodo->valore = e;
    if(precedente == NULL){
        nuovo_nodo->next = lista;
        lista = nuovo_nodo;
        return lista;
    }else{
        precedente->next = nuovo_nodo;
        nuovo_nodo->next = corrente;
        return lista;
    }
}

7 Risposte

  • Re: Uso delle classi C++

    Scusa, cosa hai risolto? Non c'è il parametro "posizione" su cui tanto si è discusso ... quindi?

    E il problema che proponi è lo stesso di quello che hai proposto in

    http://www.pierotofy.it/pages/extras/forum/2/1065351-classe_lista_concatenata_c/

    Perché la struttura tra i membri privati della lista?
  • Re: Uso delle classi C++

    Relativamente al primo codice:
    - il secondo typedef è inutile, in quanto nel C++ la definizione di una struct/class comporta la definizione di un nuovo tipo;
    - il terzo typedef, tanto spesso utilizzato nei codici postati sui forum, secondo me sarebbe meglio evitarlo... comporta una semplificazione minima, ma rende il codice meno chiaro;
    - la funzione creaLista() è perfettamente inutile;
    - in C++ di solito si utilizza nullptr e non NULL;
    - nella funzione stampaLista() la variabile corrente è superflua;
    - credo inoltre che qualsiasi implementazione di una lista concatenata debba contenere una funzione per l'inserimento in testa e in coda;
    - la funzione inserisciElemento() (che forse sarebbe più corretto chiamare inserisciElemento_in_ordine) potresti anche renderla di tipo void e implementarla sfruttando le suddette due funzioni introdotte nel punto precedente;
    - la funzione leggi è sbagliata... cosa ritorna la funzione se trovato è falso? Se fossi in te renderei la funzione di tipo bool e passerei la variabile valore come argomento.

    In pratica farei qualcosa del genere:
    #include <iostream>
    
    using namespace std;
    
    typedef int T;
    
    struct nodo
    {
        T valore;
        struct nodo *next;
    };
    
    void aggiungi_in_testa(nodo **ptr, T info)
    {
        nodo *nuovo = new nodo;
        nuovo->valore = info;
        nuovo->next = *ptr;
        *ptr = nuovo;
    }
    
    void aggiungi_in_coda(nodo **ptr, T info)
    {
        nodo **temp = ptr;
        while(*temp)
        {
            temp = &(*temp)->next;
        }
        aggiungi_in_testa(temp, info);
    }
    
    void aggiungi_in_ordine(nodo **ptr, T info)
    {
        nodo **temp = ptr;
        while(*temp && (*temp)->valore < info)
        {
            temp = &(*temp)->next;
        }
        aggiungi_in_testa(temp, info);
    }
    
    bool trova(nodo *ptr, T info)
    {
        while(ptr)
        {
            if(ptr->valore == info)
            {
                return true;
            }
            ptr = ptr->next;
        }
        return false;
    }
    
    void stampa_lista(nodo *ptr)
    {
        while(ptr)
        {
            cout << ptr->valore << " ";
            ptr = ptr->next;
        }
    }
    
    int main()
    {
        nodo* lista = nullptr;
        aggiungi_in_coda(&lista, 3);
        aggiungi_in_testa(&lista, 2);
        aggiungi_in_coda(&lista, 4);
        aggiungi_in_testa(&lista, 1);
        aggiungi_in_coda(&lista, 6);
        aggiungi_in_ordine(&lista, 0);
        aggiungi_in_ordine(&lista, 5);
        aggiungi_in_ordine(&lista, 9);
        aggiungi_in_ordine(&lista, 7);
        aggiungi_in_ordine(&lista, 8);
        if(trova(lista, 6))
        {
            stampa_lista(lista);
        }
    }
    
    Se hai qualche dubbio chiedi pure.

    Per quanto riguarda il secondo codice, dopo se ho tempo gli do un'occhiata.
  • Re: Uso delle classi C++

    I problemi li ho principalmente sul secondo codice, grazie in anticipo
  • Re: Uso delle classi C++

    E comunque per quanto riguarda l'inserimento in testa e in coda ho già previsto un inserimento in ordine (cioè quando dai in input un valore da inserire, per esempio 5, lo inserisco tra il 3 e il 4)
  • Re: Uso delle classi C++

    Il 5 lo inserisce tra il 3 e il 4?
  • Re: Uso delle classi C++

    Ho sbagliato volevo dire 4 tra 3 e 5 il senso era quello
  • Re: Uso delle classi C++

    lippolis2000 ha scritto:


    I problemi li ho principalmente sul secondo codice, grazie in anticipo
    Ho capito che il secondo codice non ti compila, ma volevo farti notare che anche il primo non è il massimo. Oltre alla parte logica che è ampiamente ottimizzabile, c'è la funzione leggi() che è proprio sbagliata. Poi se ti accontenti del compitino...
    Giusto per curiosità, ma lo hai letto attentamente il mio precedente post? E il codice che ho postato?

    lippolis2000 ha scritto:


    E comunque per quanto riguarda l'inserimento in testa e in coda ho già previsto un inserimento in ordine (cioè quando dai in input un valore da inserire, per esempio 5, lo inserisco tra il 3 e il 4)
    Sinceramente non ho capito cosa mi stai contestando!?

    Passiamo quindi al secondo codice. L'errore di cui parlavi nel post iniziale è dovuto al casino che hai combinato tra i vari typedef, alla definizione della struct all'interno della classe e al mancato utilizzo dell'operatore risolutore di scopo. A questo punto la domanda sorge spontanea... perchè complicarsi la vita con cose strane, quando basterebbe scrivere del codice semplice e pulito?! Nel caso specifico intendo dire lascia stare tutti quei typedef inutili e dichiara la struct/class nodo all'esterno della classe list.
    Inoltre penso che tu non abbia le idee molto chiare riguardo alle classi, perchè tutta l'impostazione della classe list e l'utilizzo che ne fai nel main non hanno alcun senso.
Devi accedere o registrarti per scrivere nel forum
7 risposte