[C++] Aiuto con funzioni e puntatori

Messaggioda paolotesla91 » 23/02/2018, 12:44

Salve a tutti ragazzi. E' da ieri che cerco di fare un esercizio al compilatore. L'esercizio in questione è costituito dai seguenti passaggi: 1) acquisire dallo stdin un array di interi. 2) visualizzare a video l'array inserito. 3)ordinare gli elementi dell'array in ordine crescente. 4) visualizzare a video l'array ordinato.
Il tutto dovrei farlo preferibilmente mediante l'uso di funzioni. Riscontro dei problemi col secodno punto e con i succesivi in quanto non so come far ritornare un array da una funzione e in che modo manipolarla nella funzione successiva. So che posso farlo tramite un puntatore ma non so dove sia più corretto dichiarare l puntatore e come utilizzarlo.

Posto di seguito una bozza del codice sorgente da me scritto nella speranza che qualcuno di voi mi aiuti a capire se questa prima parte è corretta ed aiutarmi a capire come affrontare i punti successivi.

Codice:
#include <iostream>
#include <stdlib.h>

//dichiarazioni
const int M=100;
int a[M];
int n;



using namespace std;


//inserimento array di interi
void input(int a[], int n){
    bool ok=true;
   int temp[M];
   do{
       ok=true;
      cout << "inserire numero di elementi: "<<endl;
       cin >> n;
      if(n<=0){
            cout << "il numero di elementi deve essere positivo"<<endl;
            ok=false;
      } else if(n>0){
         cout << "inserire elementi dell'array: "<<endl;
           for(int i=0; i<n; i++)
                cin >>temp[i];
                ok=true;
              }
      }while(!ok);
      for(int j=0; j<n; j++){
      a[j]=temp[j];
    }
     
   return;
}

//visualizzo la lista inserita
void visualizza(int a[] ){
     cout << "la lista di elementi inserita e': "<<endl;
     for(int i=0; i<n; i++)
     cout << a[i];
     cout <<endl;
     return;
     }

//MAIN
   int main(){
       
      int lista[M];
      int numero;
      
      input(lista, numero);
       visualizza(lista);
      
      
      system("pause");
      return 0;
   }



P.S. se provate a compilare il codice noterete che non mi visualizza a video l'array.
Sareste cosi gentili da aiutarmi?

Ringrazio in anticipo per l'attenzione.
[i]L'essenza della matematica è nella sua libertà.[/i] Georg Cantor (1845-1918)
Avatar utente
paolotesla91
Senior Member
Senior Member
 
Messaggio: 935 di 1894
Iscritto il: 01/03/2011, 20:16
Località: Napoli

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda paolotesla91 » 23/02/2018, 16:31

Sono riuscito a fare i primi due punti del mio esercizio. Il compilatore compila il programma e non riscontro alcun errore n fase di esecuzione tuttavia ho un problema con l'algoritmo di ordinamento. Ho scelto il BubbleSort per semplicità e perchè è quello che ho compreso meglio, quando eseguo il programma ed inserisco i numeri a caso non avviene alcun ordinamento anzi, più precisamente, a video mi compaiono tanti zeri consecutivi come se non avessi inserito alcuna lista. Credo che il problema sia sempre lo stesso: come faccio a memorizzare una variabile (nello specifico un array) in uscita da una funzione per poterla manipolare in un altra funzione?

Posto di seguito il frammento di codice che mi da il problema:

Codice:
#include <iostream>
#include <cstdlib>
#define M 100

using namespace std;

int a[M];
int riemp;
const int *Pt=a;

void Bubble(int *Pt, int riemp){
   
   int i, j;
   int temp;
   for(i=0; i<riemp; i++)
       for(j=0; j<riemp-1-i; j++)
         if(a[j]>a[j+1]){
            temp=a[j+1];
            a[j+1]=a[j];
            a[j]=temp;
        }
       
      return;
}

void visualizza(int *Pt, int riemp){
   for(int i=0; i<riemp; i++)
   cout<<*Pt;
   return;
}

int main(){
   
   int array[M];
   int n;
   
   bool ok=true;
   do{
      ok=true;
      cout<<"inserire il numero di elementi della lista: ";
      cin>>n;
      if(n<=0){
         cout<<"il numero di elementi deve essere maggiore di zero"<<endl;
         ok=false;
      }else if(n>0){
         cout<<"inserire elementi della lista: "<<endl;
         for(int i=0; i<n; i++)
         cin>>array[i];
         ok=true;
      }
   }while(!ok);
   cout<<"la lista inserita e': "<<endl;
   for(int i=0; i<n; i++){
      cout<<array[i];
   }
   cout<<"ordino la lista"<<endl;
   Bubble(array, n);
   cout<<"la lista ordinata e': "<<endl;
   visualizza(array,n);
   
   
   system("pause");
   return 0;
}
[i]L'essenza della matematica è nella sua libertà.[/i] Georg Cantor (1845-1918)
Avatar utente
paolotesla91
Senior Member
Senior Member
 
Messaggio: 936 di 1894
Iscritto il: 01/03/2011, 20:16
Località: Napoli

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda vict85 » 23/02/2018, 22:40

Qualche correzione sulla funzione che visualizza a schermo.
Codice:
void
visualizza(int * Pt, int riemp)
{
  // Se passi un puntatore è normale testare che sia non nullo
  if (Pt == nullptr)
    {
      return;
    }

  for (int i = 0; i < riemp; i++)
    {
      // cout << *Pt; // continui ad stampare il primo elemento, e manca lo
                      // spazio tra i numeri
      cout << Pt[i] << " ";  // oppure *(Pt+i)
    }
  std::cout << std::endl;
  // return; // NON necessario
}


Per il main lo farei così
Codice:
int
main(void)
{
  // usare #define per definire costanti e' meno comune nel C++
  // suggerisco di usare constexpr
  constexpr size_t M = 100;
  int array[M] = {};
  size_t N = 0;

  for (;;)
    {
      std::cout << "Inserire il numero degli elementi della lista:\t"
                << std::endl;
      std::cin >> N;
      if (N > 0 && N <= M)
        {
          break;
        }
      std::cout << "Numero inserito non valido" << std::endl;
    }

  for (size_t i = 0; i != N; ++i)
    {
      std::cout << "Inserire A[" << i << "] = ";
      std::cin >> array[i];
    }

  visualizza(array, N);

  Bubble(array, N);

  visualizza(array, N);
}



Per quanto riguarda Bubble, non ho controllato molto, ma sono bastate poche correzioni perché il risultato sembrasse corretto
Codice:
void
Bubble(int * Pt, int riemp)
{
  if (Pt == nullptr)
    {
      return;
    }
  for (int i = 0; i < riemp; i++)
    {
      for (int j = 0; j < riemp - 1 - i; j++)
        {
          if (Pt[j] > Pt[j + 1])
            {
              temp = Pt[j + 1];
              Pt[j + 1] = Pt[j];
              Pt[j] = temp;
            }
        }
    }
}
Ho però l'impressione che non sia un BubbleSort.

Ho eliminato anche tutte le variabili globali e non serve includere cstdlib.
vict85
Moderatore
Moderatore
 
Messaggio: 9262 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda paolotesla91 » 24/02/2018, 11:24

Ciao vict grazie mille per aver risposto. Alcune scelte di programmazione come l'uso dei define ecc.. sono obbligate in quanto il mio prof preferisce che si faccia cosi. Avrei alcune domande che restano senza risposta come quelle che ho elencato nei post precedenti e in più: il controllo che il puntatore sia non nullo va fatto sempre?

Questo esercizio mi è servito solo per allenamento con array, puntatori, funzioni, passaggi di variabile. Spesso all'esame il prof ci fa manipolare stringhe per cui vorrei capire bene come giocare con esse e familiarizzare un po. quindi come faccio a memorizzare il contenuto di un dato (anche strutturato) per poterlo riutilizzare e manipolare nelle funzioni?

Chiedo scusa se sono rompiscatole ma devo cercare di capire bene queste cose.

Grazie ancora per l'aiuto.
[i]L'essenza della matematica è nella sua libertà.[/i] Georg Cantor (1845-1918)
Avatar utente
paolotesla91
Senior Member
Senior Member
 
Messaggio: 937 di 1894
Iscritto il: 01/03/2011, 20:16
Località: Napoli

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda Super Squirrel » 24/02/2018, 14:27

Per quanto riguarda l'esercizio io farei qualcosa del genere:

Codice:
#include <iostream>

using namespace std;

void riempi_array(int *v, const int &dim)
{
    for(unsigned int i = 0; i < dim; i++)
    {
        cout << "v[" << i << "] = ";
        cin >> v[i];
    }
}

void mostra_array(int *v, const int &dim)
{
    for(unsigned int i = 0; i < dim; i++)
    {
        cout << v[i] << " ";
    }
}

void scambia_valori(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

void ordina_crescente(int *v, const int &dim)
{
    bool modifica;
    for(unsigned int k = 0; k < dim - 1; k++)
    {
        modifica = false;
        for(unsigned int i = 0; i < dim - 1 - k; i++)
        {
            if(v[i] > v[i + 1])
            {
                scambia_valori(v[i], v[i + 1]);
                modifica = true;
            }
        }
        if(!modifica)
        {
            return;
        }
    }
}

int main()
{
    const unsigned int dim_max = 100;
    int v[dim_max];
    int dim;
    bool errore;
    do
    {
        errore = false;
        cout << "dim(MAX 100) = ";
        cin >> dim;
        if(dim < 0 || dim > dim_max)
        {
            errore = true;
            cout << "INSERIMENTO NON VALIDO" << endl;
        }
    }
    while(errore);
    riempi_array(v, dim);
    mostra_array(v, dim);
    ordina_crescente(v, dim);
    cout << endl;
    mostra_array(v, dim);
}


Avrei alcune domande che restano senza risposta come quelle che ho elencato nei post precedenti e in più: il controllo che il puntatore sia non nullo va fatto sempre?


E' un controllo che ci può stare come potrebbero starcene anche altri, ma al momento mi soffermerei maggiormente su altre questioni.
Per quanto riguarda le tue domande precedenti non ho capito bene quali sono i tuoi dubbi. Gli argomenti in gioco credo siano passaggio per valore e per riferimento alle funzioni, puntatori e array. Potresti essere più chiaro?
Per quanto riguarda le stringhe, utilizzate stringhe stile C (array di char) o stringhe stile C++ (oggetti della classe string)?
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 163 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda paolotesla91 » 24/02/2018, 15:46

Ciao Squirrel. L'uso che facciamo noi delle stringhe consiste nella manipolazione di array di char e il prof vuole che implementiamo funzioni che eseguano l'operazione richiesta. I miei dubbi sono sia sui passaggi di variabile che sulla dichiarazione dei puntatori. Sto rivedendo una soluzione di una prova d'esame postata dal mio prof ma non riesco a capire alcuni passaggi.
Posto di seguito il codice del programma della prova d'esame:

Questo è il segmento di codice del file head:

Codice:
#include <iostream>

using namespace std;

struct Elemento{
    char prod[20];
    int quant;
    double prezzo;
    struct Elemento *prossimo;
};
   
    typedef struct Elemento *Lista;

void inserisciLista(Lista &,char [], int,double);
void visualizzaLista(Lista);
double calcolaCosto(Lista l);


Posto il segmento di codice che non riesco a capire:
Questo il segmento di codice del file .cpp :

Codice:
#include <iostream>
#include <cstring>
#include ".\lista.h"

using namespace std;

void inserisciLista(Lista &l,char n[20],int q,double pr)
{
    Lista p=l;
    bool trovato=false;
   while (p!=NULL && !trovato){
      trovato=false;
      if (strcmp(p->prod,n)==0){
         p->quant+=q;
         p->prezzo=pr;
         trovato=true;
      }
      else
         p=p->prossimo;
      }
      
   if (!trovato){
      struct Elemento *e=new Elemento;
       strcpy(e->prod,n);
       e->quant=q;
      e->prezzo=pr;       
       e->prossimo=l;
       l=e;
   }         
    return;
}

void visualizzaLista(Lista l){
     Lista q=l;
     while (q!=NULL){
          cout<<q->prod<<" : "<<q->quant<<" unita'. Prezzo: "<<q->prezzo<<endl;
          q=q->prossimo;
     }
    return;
}

double calcolaCosto(Lista l){
     Lista q=l;
     double costo=0.0;
     while (q!=NULL){
          costo+=(q->quant*q->prezzo);
          q=q->prossimo;
     }
     cout<<endl;
    return costo;
}


Più precisamente non riesco a capire perchè passa la lista per riferimento e poi scrive "Lista p=l;" , poi nell'if annidato scrive "e->prossimo=l;
l=e;
".

Gentilmente mi aiutereste acapire?

P.S. non ho postato la traccia per non essere troppo rompiscatole.
[i]L'essenza della matematica è nella sua libertà.[/i] Georg Cantor (1845-1918)
Avatar utente
paolotesla91
Senior Member
Senior Member
 
Messaggio: 938 di 1894
Iscritto il: 01/03/2011, 20:16
Località: Napoli

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda Super Squirrel » 24/02/2018, 23:32

Dando un'occhiata al codice, noto (tralasciando la questione stringhe) un gran miscuglio tra C e C++.
Da una lettura veloce non so dirti se ci sono errori veri e propri, ma sicuramente il tutto non è impostato in modo molto chiaro (in particolare mi riferisco al fatto che non vengono separati i concetti di lista e nodo).
Comunque ho provato a svolgere l'esercizio impostandolo in un modo che ritengo più chiaro. In questa versione le funzioni sono metodi della classe lista:

Codice:
#include <iostream>
#include <cstring>

using namespace std;

struct prodotto
{
    char nome[20];
    int quantita;
    double prezzo;
    prodotto *prossimo;
};

struct lista
{
    prodotto *testa = nullptr;
    void inserisci_prodotto (const char*, const int&, const double&);
    void visualizza_lista();
    double calcola_costo_totale();
};

void lista::inserisci_prodotto(const char *n, const int &q, const double &p)
{
    prodotto *a = testa;
    prodotto *precedente;
    while(a != nullptr)
    {
        if(!strcmp(a->nome, n))
        {
            a->quantita += q;
            a->prezzo = p;
            return;
        }
        else
        {
            precedente = a;
            a = a->prossimo;
        }
    }
    prodotto *nuovo = new prodotto;
    strcpy(nuovo->nome, n);
    nuovo->quantita = q;
    nuovo->prezzo = p;
    nuovo->prossimo = nullptr;
    if(testa == nullptr)
    {
        testa = nuovo;
    }
    else
    {
        precedente->prossimo = nuovo;
    }
}

void lista::visualizza_lista()
{
    prodotto *a = testa;
    while(a != nullptr)
    {
        cout << "- " << a->nome << ": " << a->quantita << " unita'. Prezzo: " << a->prezzo << endl;
        a = a->prossimo;
    }
}

double lista::calcola_costo_totale()
{
    prodotto *a = testa;
    double costo_totale = 0;
    while(a != nullptr)
    {
        costo_totale += a->quantita * a->prezzo;
        a = a->prossimo;
    }
    return costo_totale;
}

int main()
{
    lista l;
    int scelta;
    char n[20];
    int q;
    double p;
    cout << "1: INSERIRE PRODOTTO" << endl;
    cout << "2: VISUALIZZARE LISTA" << endl;
    cout << "3: CALCOLARE COSTO TOTALE" << endl;
    cout << "4: USCIRE" << endl;
    while(true)
    {
        cout << endl << "INSERIRE AZIONE: ";
        cin >> scelta;
        if(scelta == 1)
        {
            cout << "NOME PRODOTTO: ";
            cin >> n;
            cout << "QUANTITA' PRODOTTO: ";
            cin >> q;
            cout << "PREZZO PRODOTTO: ";
            cin >> p;
            l.inserisci_prodotto(n, q, p);
        }
        else if(scelta == 2)
        {
            l.visualizza_lista();
        }
        else if(scelta == 3)
        {
            cout << l.calcola_costo_totale() << endl;
        }
        else if(scelta == 4)
        {
            break;
        }
        else
        {
            cout << "INSERIMENTO NON VALIDO" << endl;
        }
    }
}


In questa versione invece le funzioni sono esterne:

Codice:
#include <iostream>
#include <cstring>

using namespace std;

struct prodotto
{
    char nome[20];
    int quantita;
    double prezzo;
    prodotto *prossimo;
};

struct lista
{
    prodotto *testa = nullptr;
};

void inserisci_prodotto (lista&, const char*, const int&, const double&);
void visualizza_lista(lista&);
double calcola_costo_totale(lista&);

void inserisci_prodotto(lista &l, const char *n, const int &q, const double &p)
{
    prodotto *a = l.testa;
    prodotto *precedente;
    while(a != nullptr)
    {
        if(!strcmp(a->nome, n))
        {
            a->quantita += q;
            a->prezzo = p;
            return;
        }
        else
        {
            precedente = a;
            a = a->prossimo;
        }
    }
    prodotto *nuovo = new prodotto;
    strcpy(nuovo->nome, n);
    nuovo->quantita = q;
    nuovo->prezzo = p;
    nuovo->prossimo = nullptr;
    if(l.testa == nullptr)
    {
        l.testa = nuovo;
    }
    else
    {
        precedente->prossimo = nuovo;
    }
}

void visualizza_lista(lista &l)
{
    prodotto *a = l.testa;
    while(a != nullptr)
    {
        cout << "- " << a->nome << ": " << a->quantita << " unita'. Prezzo: " << a->prezzo << endl;
        a = a->prossimo;
    }
}

double calcola_costo_totale(lista &l)
{
    prodotto *a = l.testa;
    double costo_totale = 0;
    while(a != nullptr)
    {
        costo_totale += a->quantita * a->prezzo;
        a = a->prossimo;
    }
    return costo_totale;
}

int main()
{
    lista l;
    int scelta;
    char n[20];
    int q;
    double p;
    cout << "1: INSERIRE PRODOTTO" << endl;
    cout << "2: VISUALIZZARE LISTA" << endl;
    cout << "3: CALCOLARE COSTO TOTALE" << endl;
    cout << "4: USCIRE" << endl;
    while(true)
    {
        cout << endl << "INSERIRE AZIONE: ";
        cin >> scelta;
        if(scelta == 1)
        {
            cout << "NOME PRODOTTO: ";
            cin >> n;
            cout << "QUANTITA' PRODOTTO: ";
            cin >> q;
            cout << "PREZZO PRODOTTO: ";
            cin >> p;
            inserisci_prodotto(l, n, q, p);
        }
        else if(scelta == 2)
        {
            visualizza_lista(l);
        }
        else if(scelta == 3)
        {
            cout << calcola_costo_totale(l) << endl;
        }
        else if(scelta == 4)
        {
            break;
        }
        else
        {
            cout << "INSERIMENTO NON VALIDO" << endl;
        }
    }
}


Ho impostato il main in modo da poter provare le 3 funzioni. Se hai qualche dubbio chiedi pure.

I miei dubbi sono sia sui passaggi di variabile che sulla dichiarazione dei puntatori.


Sono argomenti abbastanza vasti, se hai qualche domanda più specifica chiedi pure, altrimenti puoi dare un'occhiata al seguente sito che è davvero ben fatto:
http://www.bo.cnr.it/corsi-di-informatica/corsoCstandard/Lezioni/01Indice.html#virtual
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 164 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda apatriarca » 25/02/2018, 15:30

@Super Squirrel: La soluzione adottata di identificare nodo e lista è tipica del C e lo stesso vale per molti altri aspetti dell'implementazione. Sembra un codice scritto nella seconda metà degli anni '90. Immagino sia la data in cui il professore ha smesso di informarsi sullo sviluppo del linguaggio.

Non vedo sinceramente alcun vantaggio nella creazione di una classe lista, mentre avrebbe avuto più senso separare il concetto di lista dal suo contenuto. Un prodotto non è un nodo in una lista insomma, ma qualcosa che può essere contenuta in essa. Ha senso usare una classe lista solo se nasconde in qualche modo i dettagli implementativi. Se per fare ogni cosa è comunque necessario ricorrere all'uso dei nodo interni tanto vale usare la vecchia strategia adottata nel C.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4988 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda Super Squirrel » 25/02/2018, 16:58

Non vedo sinceramente alcun vantaggio nella creazione di una classe lista, mentre avrebbe avuto più senso separare il concetto di lista dal suo contenuto. Un prodotto non è un nodo in una lista insomma, ma qualcosa che può essere contenuta in essa. Ha senso usare una classe lista solo se nasconde in qualche modo i dettagli implementativi. Se per fare ogni cosa è comunque necessario ricorrere all'uso dei nodo interni tanto vale usare la vecchia strategia adottata nel C.


Magari al posto della struct lista sarebbe bastato un typedef per rendere chiara la distinzione tra lista e nodo, ma sinceramente non capisco perchè creare una classe lista (dove racchiudere le 3 funzioni come metodi e conservare l'informazione sul nodo di testa) sia tanto sbagliato!
In che senso un prodotto non è un nodo in una lista? Ti riferisci ai nomi che ho dato alle struct o avresti proprio impostato il tutto diversamente?
Avendo studiato da autodidatta e non conoscendo il modo in cui il C viene insegnato nelle scuole non capisco di preciso cosa intendi con "vecchia strategia adottata dal C". Alla fine credo che il concetto di lista sia lo stesso per ogni linguaggio di programmazione, quindi mi chiedo in che modo si possa fare a meno di ricorrere ai nodi interni!?
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 166 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C++] Aiuto con funzioni e puntatori

Messaggioda apatriarca » 25/02/2018, 17:20

Magari al posto della struct lista sarebbe bastato un typedef per rendere chiara la distinzione tra lista e nodo, ma sinceramente non capisco perchè creare una classe lista (dove racchiudere le 3 funzioni come metodi e conservare l'informazione sul nodo di testa) sia tanto sbagliato!

In realtà il typedef c'è.. Non c'è niente di sbagliato, ma non ne vedo alcun vantaggio. E' certamente una soluzione possibile.

In che senso un prodotto non è un nodo in una lista? Ti riferisci ai nomi che ho dato alle struct o avresti proprio impostato il tutto diversamente?

Invece di avere una struttura come la seguente:
Codice:
struct prodotto
{
    char nome[20];
    int quantita;
    double prezzo;
    prodotto *prossimo;
};

avrei separato quello che rappresenta il contenuto della lista con la lista stessa. Cioè qualcosa come segue:
Codice:
struct Product {
    char name[20];
    int quantity;
    double price;
};

struct Node {
    Product product;
    Node *next;
};

Questo permette di lavorare su oggetti del tipo Product senza mischiare tale implementazione con quella della lista. Dal punto di vista di funzionalità più avanzate, l'idea sarebbe di avere la lista come un template e il prodotto sarebbe quello che è contenuto nella lista.

Alla fine credo che il concetto di lista sia lo stesso per ogni linguaggio di programmazione, quindi mi chiedo in che modo si possa fare a meno di ricorrere ai nodi interni!?

Nell'implementazione della classe è certamente impossibile. Ma se supponi che un utilizzatore della tua classe volesse ordinare i prodotti nella lista o fare altre operazioni, l'unica loro alternativa è di usare la rappresentazione interna della classe come lista concatenata. Ma è possibile fare come std::list e nascondere l'implementazione all'utente che è a questo punto obbligato ad interagire con la classe in modo "generico".
apatriarca
Moderatore
Moderatore
 
Messaggio: 4990 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite