Newsgroup: it.comp.lang.c
Titolo: Aiuto!!!  le liste in C

Sono un principiante con C e vorrei sapere perche' questo
esercizio non funziona. Non arriva neanche a eseguire questa
istruzione  
printf("fine lista\n");  quando inserisco il secondo elemento
Grazie a chi sapra' darmi una risposta.
Ecco il listato:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct prub
{
    char nome[20];
    char cognome[20];
    char indirizzo[20];
    int eta;
    struct prub *next;
}rubrica;
rubrica *head;
//void stampa(rubrica *rub);
void stampa();
//int inserisci(rubrica *rubaus);
int inserisci();
void scrivifile();
extern int contins; // cerca la variabile dichiarata a livello
globale in un altro
					// programma (e' meglio pero' passare il valore nei
parametri della
     				// funzione)
int contins=0;
main()
{    
    int scelta;     
    do{
        printf("Menu\n");
        printf("-1- Inserimento nuovo contatto\n");
        printf("-2- Stampa\n");
        printf("-0- Esci\n");
        scanf("%d",&scelta);
        switch(scelta)
        {
            case 1:                                             
 
                inserisci();                           
                break;
            case 2:
                stampa();
                break;
            case 0:
                break;            
            default:
                printf("Scelta errata!!!!!\n");
                fflush(stdin);
                break;
        }  
    }while(scelta!=0);  
}    
int inserisci()
{
    	char nome[20],cognome[20],indirizzo[20];
    	int eta;
    	rubrica *rubaus;   
        fflush(stdin); // x ripulire il buffer
        printf("cognome:\n");
        gets(cognome);
        printf("nome:\n");
        gets(nome);
        printf("indirizzo:\n");
        gets(indirizzo);
        int errore;
        do{
           printf("eta:\n");
           fflush(stdin);
           // scanf restituisce 0 se inserisco caratteri(non va
bene in questo caso)
           // e 1 se inserisco numeri(OK)
           //errore = scanf("%d",&(rub[contins-1].eta));
           errore = scanf("%d",&eta);           
        }while(errore==0);
        fflush(stdin);                                          
 
 
    	if (contins==0)//controllo se contins=0 per vedere se e'
prima volta
    	{
    	    printf("prima volta\n");
    	    rubaus=(rubrica*)malloc(sizeof(rubrica));  
            strcpy(rubaus->cognome,cognome); //si valorizzano i campi
            strcpy(rubaus->nome,nome);
            strcpy(rubaus->indirizzo,indirizzo);
            rubaus->eta=eta;
            head=rubaus; //head viene valorizzato solo la prima volta
        }
        else
        {                         
            rubaus=head;
       	    printf("volte successive\n");  
            while(rubaus->next!=NULL) //si visita la lista      
 
            {rubaus=rubaus->next;}            
            printf("fine lista\n");    
 
            rubaus->next=(rubrica*)malloc(sizeof(rubrica));  
            printf("dopo malloc\n");    
            rubaus=rubaus->next;
            strcpy(rubaus->cognome,cognome); //si valorizzano i campi
            strcpy(rubaus->nome,nome);
            strcpy(rubaus->indirizzo,indirizzo);
            rubaus->eta=eta;
            rubaus->next=NULL;            
        }       
        contins++;            
        return 0;                    
}    
void stampa()
{   
    rubrica *rub;
    rub=head;
    int i;
    printf("contins:%d\n",contins);
    while(rub->next!=NULL)
    {        
    	printf("%s %s %s %d\n",rub->cognome,rub->nome,rub->indirizzo,
      						   rub->eta);    
    }
   	/*printf("%s %s %s %d\n",rub->cognome,rub->nome,rub->indirizzo,
   						   rub->eta);   */
}
-- 
Inviato da Virgilio 
http://newsgroup.virgilio.it
..un servizio di news via web con in piu' l'antispam

 Grazie a chi sapra' darmi una risposta.
E un chissenefrega del tuo grazie _solo_ a chi ti sa dare una risposta non
ce lo metti?
C:\>iao Angelo
P.S. Io "forse" saprei darti la risposta, ma preferisco farmi i fatti miei
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

Grazie a tutti.
Va meglio cosi?
:)


ma e' un errore grave?
un piccolo aiutino?
Nell'altra risposta stavo scherzando.
Grazie.


 Grazie a chi sapra' darmi una risposta.
Lascia perdere A.Paolitto che evidentemente oggi era girato
storto, visto che non mi sembra tu sia stato sgarbato, ma che tu
abbia semplicemente usato una frase fatta.
Ora non ho la forza psichica di guardare tutto il programma,
ma noto comunque che quando allochi il primo record non poni
il campo next uguale a NULL (cosa che fai invece per i record
successivi). Questo potrebbe causare errori,
ciao,
v.

 Ecco il listato:
no.
perché un listato di 133 linee te lo leggono solo i missionari.
taglia il codice alle parti che ritieni essere in errore, (probabilmente
facendolo lo trovi anche da solo l'errore (divide et impera, ricordi?))..
e soprattutto, non lasciarci commenti inutili tipo prototipi di funzioni
che non usi o simili. 
Se copi e incolli il codice dal tuo editor al tuo newsreader senza curarlo
è come mancare di rispetto a chi poi dovrebbe aiutarti a risolvere un
problema, non pensi ?
Un ultima cosa che mi è saltata alla vista da un'occhiata rapida:
fflush(stdin); NON ripulisce il buffer di input come invece pensi e
commenti: ha un comportamento non definito e non va usata.
Ciao
Matic

         
E' tutto, eccoti il codice, sperando possa esserti utile almeno un pò.
Ciao,
Andrea  
#include <stdio.h>
#include <stdlib.h>
typedef struct prub
{
    char nome[20];
    char cognome[20];
    char indirizzo[20];
    int eta;
    struct prub *next;
} rubrica;
typedef struct queue_struct
{
    rubrica *head, *tail;
} *queue;
void inserisci( queue );
void stampa( queue );
void scrivifile();
queue init();
int contins=0;
main()
{
    int scelta;
    queue q;
    if (  ( q = init() ) == NULL ) return 1;   // inizializza i campi
                                               // della struttura
                                               // queue_struct
    do
    {
        printf("\nMenu\n");
        printf("-1- Inserimento nuovo contatto\n");
        printf("-2- Stampa\n");
        printf("-0- Esci\n\n");
        scanf( "%d", &scelta );
        getchar();                 // legge il return, altrimenti
                                   // viene letto dalla gets()
        switch(scelta)
        {
            case 1:
                    inserisci( q );
                    break;
            case 2:
                    stampa( q );
                    break;
            case 0:
                    break;
            default:
                    printf("Scelta errata!!!!!\n");
                    fflush(stdin);
                    break;
        }
    }
    while( scelta!=0 );
}
void inserisci( queue q )
{
     rubrica *rubaus = calloc( 1, sizeof( rubrica ) );
 
     fflush(stdin);  // x ripulire il buffer
     printf( "\ncognome:\n" );
     gets( rubaus->cognome );
     printf("nome:\n");
     gets( rubaus->nome );
     printf("indirizzo:\n");
     gets( rubaus->indirizzo );
     printf ("eta: \n");
     scanf ( "%d", &rubaus->eta );
     if ( q->head == NULL )   // prima volta
     {
          printf( "\nprima volta\n" );
          q->tail= q->head= rubaus;
     }
     else {  q->tail->next=rubaus; q->tail= rubaus; }
 
     contins++;
}
void stampa( queue q )
{
     rubrica *rub= q->head;
     printf("\ncontins:%d\n",contins);
     while ( rub!=NULL )
     {
         printf( "%s %s %s %d\n", rub->cognome, rub->nome,
                 rub->indirizzo, rub->eta );
         rub=rub->next;
     }
}
queue init()
{
      return calloc ( 1, sizeof ( struct queue_struct ) );
}

 :)
Va molto meglio. Anche chi non ti risponde legge il tuo post, un
grazie per il_*SUO*_ tempo che _*TI*_ ha REGALATO lo merita comunque.
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Nell'altra risposta stavo scherzando.
Se avessi sospettato che stessi scherzando non ti avrei risposto.
In ogni caso ti ho regalato un po' del mio tempo.
i miei commenti cominciano con
//// ->
Inutile dire che' c'e' un mucchio di roba inutile e che il programma
potrebbe essere semplificato parecchio
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>  //// -> serve per strcpy & Co.
typedef struct prub
{
    char nome[20];
    char cognome[20];
    char indirizzo[20];
    int eta;
    struct prub *next;
}rubrica;
rubrica *head;
 
 //void stampa(rubrica *rub);
void stampa();
 //int inserisci(rubrica *rubaus);
int inserisci();
void scrivifile();
//// -> Questa _*dichiarazione*_ non serve se subito dopo c'e' la
//// ->  _*definizione*_ della variabile che dichiari.
extern int contins; // cerca la variabile dichiarata a livello globale
in un altro
                     // programma (e' meglio pero' passare il valore nei
parametri della
                     // funzione)
//// -> Le globali sono inizializzate a zero automaticamente. 
int contins=0;
//// -> int main(void) o int main(int argc, char* argv[]) o equivalenti
//// -> la tua dichiarazione di main e' sbagliata.
//// -> main()
int main(void)
{    
     int scelta;     
     do{
         printf("Menu\n");
         printf("-1- Inserimento nuovo contatto\n");
         printf("-2- Stampa\n");
         printf("-0- Esci\n");
         scanf("%d",&scelta);
         switch(scelta)
         {
             case 1:                                             
 
                 inserisci();                           
                 break;
             case 2:
                 stampa();
                 break;
             case 0:
                 break;            
             default:
                 printf("Scelta errata!!!!!\n");
                 fflush(stdin);
                 break;
         }  
     }while(scelta!=0);  
 }    
int inserisci()
{
       char nome[20],cognome[20],indirizzo[20];
       int eta;
       rubrica *rubaus;   
       int errore;
//// -> un fflush() su stdin e' un undefined behaviour. Se ti
//// -> interessa la portabilita' del codice e' da evitare.
        fflush(stdin); // x ripulire il buffer
        printf("cognome:\n");
        gets(cognome);
        printf("nome:\n");
//// -> gets() e' da evitare come la peste. se si immettono piu' di
//// -> 20 caratteri si sovrascrive memoria con risultati spettacolari
//// -> che spesso si scoprono a distanza di anni.
        gets(nome);
        printf("indirizzo:\n");
        gets(indirizzo);
   //// -> Questo e' C o C++? In "C" la variabili vanno
   //// -> definite ad inizio blocco
         // int errore;
         do{
            printf("eta:\n");
            fflush(stdin);
            // scanf restituisce 0 se inserisco caratteri(non va  bene
in questo caso)
            // e 1 se inserisco numeri(OK)
            //errore = scanf("%d",&(rub[contins-1].eta));
            errore = scanf("%d",&eta);           
         }while(errore==0);
         fflush(stdin);                                          
 
 
        if (contins==0)//controllo se contins=0 per vedere se e' prima
volta
        {
            printf("prima volta\n");
 
//// -> un controllo su quanto restituito da malloc() non sarebbe
//// -> sbagliato
            rubaus= /* (rubrica*) */ malloc(sizeof(rubrica));
        //// -> o usi calloc() o inizializzi next
            rubaus->next = NULL;
         //// ->  Un include per strcpy non lo vogliamo mettere?
             strcpy(rubaus->cognome,cognome); //si valorizzano i campi
             strcpy(rubaus->nome,nome);
             strcpy(rubaus->indirizzo,indirizzo);
             rubaus->eta=eta;
             head=rubaus; //head viene valorizzato solo la prima volta
         }
         else
         {                         
             rubaus=head;
                    printf("volte successive\n");  
//// -> Questa istruzione fondamentalmente e' sbagliata. Tu allochi
//// -> rubaus con malloc(). malloc ti restituisce un blocco di
//// -> memoria non inizializzato: non puoi fare affidamento sul fatto
//// -> che next sia NULL, visto che non lo inizializzi.
         //// -> questo non visita la lista: non c'e' niente
         //// -> che cambi il valore di quanto sotto test
             // while(rubaus->next!=NULL) //si visita la lista
             while(NULL != rubaus->next)
                   rubaus = rubaus->next;
//// -> Perche' vuoi perdere il valore di rubaus appena
//// -> uscito dal blocco?
             // {rubaus=rubaus->next;}
 
             printf("fine lista\n");
             //// -> Come ti diranno qualche miliardo di volte
             //// -> il cast su malloc e' da evitare.
             rubaus->next =/* (rubrica*) */ malloc(sizeof(rubrica));  
             printf("dopo malloc\n");    
             rubaus=rubaus->next;
             strcpy(rubaus->cognome,cognome); //si valorizzano i campi
             strcpy(rubaus->nome,nome);
             strcpy(rubaus->indirizzo,indirizzo);
             rubaus->eta=eta;
             rubaus->next=NULL;
         }       
         contins++;            
         return 0;                    
 }    
//// -> stampa esplode se la prima opzione selezionate e proprio
//// -> stampa Non esiste nessun controllo per verificare se head
//// ->  punta a qualcosa di sensato o e' NULL.
void stampa()
{
    int i;
    rubrica *rub;
    rub=head;
  //// -> Questo e' C o C++? In "C" la variabili vanno
  //// -> definite ad inizio blocco e visto che non viene
  //// -> referenziata, e' meglio non metterla
    // int i;
    printf("contins:%d\n",contins);
    while(rub!=NULL)
    {        
       printf("%s %s %s %d\n",rub->cognome,rub->nome,rub->indirizzo,
                                                  rub->eta);
       rub = rub->next; //// -> lo vogliamo cambiare il valore
                        //// -> stampato?
    }
       /*printf("%s %s %s %d\n",rub->cognome,rub->nome,rub->indirizzo,
                                                   rub->eta);   */
}


 successivi). Questo potrebbe causare errori,
Fosse stato solo quello...
C:\>iao Il missionario.


OK, finalmente risolto.
Grazie ancora.


              // {rubaus=rubaus->next;}
... e questa e' una puttanata del sottoscritto.
C:\>iao Angelo


 e il suo valore sara` indefinito allo startup del programma.
A declaration of an identifier for an object that has file scope
without an initializer, and without a storage-class specifier or
with the storage-class specifier static, constitutes a tentative
definition. If a translation unit contains one or more tentative
definitions for an identifier, and the translation unit contains
no external definition for that identifier, then the behavior is
exactly as if the translation unit contains a file scope
declaration of that identifier, with the composite type as of the
end of the translation unit, with an initializer equal to 0.
ISO/IEC 9899:1999 pag. 143
Da standard, direi che una globale viene inizializzata a 0 all'avvio
del programma...
C:\>iao Angelo



Scusa, sai dirmi se e` il compilatore che sa generare codice per 
inizializzare l'area del segmento bss? oppure viene inclusa qualche 
routine di libreria?
Oppure cio` che citi dallo standard standard non esisteva nelle 
precedenti versioni?
Io ero abituato ad usare compilatori per generare codice di sistemi 
embedded e ho sempre avuto sgradite sorprese se una variabile non era 
inizializzata prima dell'uso.


 inizializzata prima dell'uso.
Non so che dirti...
C:\>iao Angelo