Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - liste di liste - dubbio
Forum - C/C++ - liste di liste - dubbio

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
tonno16 (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2013

Segnala al moderatore
Postato alle 12:16
Venerdì, 04/01/2013
salve a tutti. Ho trovato questo forum veramente di facile utilizzo, ed ora provo a chiedere a voi un aiuto.

devo implementare un programma in C che gestisca gli studenti iscritti agli anni accademici con gli esami (lgi esami li implementerò successivamente);

QUINDI: in questa lista di liste ci sono gli anni e gli studenti:
prendiamo per esempio questa imamgine:

http://img97.imageshack.us/img97/4989/listage.jpg

ipotizziamo che i nodi in alto dove c'è M siano gli anni. e i nodi in verticale siano gli studenti di ogni anno.

nel mio codice la lista degli studenti si chiama *testa_stud.  come vedete nella foto il numero 10 punta a NULL. nel mio caso, testa_stud->next punta a NULL, come nella foto. Infatti stampando tutti gli studenti di tutti gli anni, viene stampata dolo la lista degli studenti inseriti in input dell ultimo anno. esempio. inserisco 2 studenti del 1993 e altri 3 del 1995,  in stampa_studenti(), ho solo la lista degli studenti del 1993.

DUNQUE devo far si che il nodo 10 della foto punti a 2???? cosi da avere un unica lista di studenti.
AIUTO.

Codice sorgente - presumibilmente C++

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4.  
  5. typedef struct __studente{
  6.   int matricola;
  7.   char nome[20];
  8.   char cognome[20];
  9.   int esame[6];
  10.   struct __studente* next_stud;
  11. }studente;
  12.  
  13. typedef struct __anno{
  14.   int anno;
  15.   struct __anno* next_anno;
  16.   struct __studente* testa_stud;
  17. }anno;
  18.  
  19. studente* testa_studente=NULL;
  20.  
  21. void ins_anno(anno** testa_anno){
  22.    
  23.     int aanno;
  24.     printf("inserire anno: "); scanf("%d", &aanno); // ATTENZIONE è AANNO E NON ANNO
  25.    
  26.     anno* temp;
  27.     temp=*testa_anno; // mi appoggio a temp
  28.    
  29.     while(temp!=NULL){ // CONTROLLO SE L' ANNO è GIà PRESENTE
  30.         if(temp->anno==aanno){ printf("anno già inserito"); return; }
  31.         temp=temp->next_anno;
  32.     }
  33.    
  34.     anno* nuovo;
  35.     nuovo=(anno*)malloc(sizeof(anno));
  36.     nuovo->anno=aanno;
  37.     nuovo->next_anno=*testa_anno;
  38.     *testa_anno=nuovo;
  39. }    
  40.  
  41. void stampa_anno(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
  42.    
  43.      if(testa_anno!=NULL){
  44.          printf(" %d\n", testa_anno->anno);      
  45.          stampa_anno(testa_anno->next_anno);
  46.      }
  47. }
  48.  
  49. void ins_stud(anno** testa_anno){
  50.    
  51.     int esiste=0,aanno;
  52.     printf("anno frequentato: ");  scanf("%d", &aanno); // appositamente scritto aanno
  53.    
  54.     anno* ultimo=*testa_anno;
  55.     ultimo->testa_stud=NULL;
  56.    
  57.     do{
  58.         if(aanno==ultimo->anno){  esiste=1;   break;   }
  59.         else{
  60.              ultimo=ultimo->next_anno;
  61.         }
  62.     }
  63.     while(ultimo!=NULL);
  64.    
  65.     if(esiste==0){ puts("non esiste alcun anno selezionato"); }
  66.     else{
  67.          char nome[15],cognome[15];
  68.          int matricola;
  69.          
  70.          puts("matricola: "); fflush(stdin);  scanf("%d", &matricola);
  71.          puts("nome: ");      fflush(stdin);  gets(nome);
  72.          puts("cognome: ");   fflush(stdin);  gets(cognome);
  73.          
  74.          studente* nuovo;
  75.          nuovo=(studente*)malloc(sizeof(studente));
  76.          nuovo->matricola=matricola;
  77.          strcpy(nuovo->nome,nome);
  78.          strcpy(nuovo->cognome,cognome);
  79.          
  80.          if(ultimo->testa_stud==NULL){// se non ci sono studente in quell anno
  81.              testa_studente=nuovo;
  82.              testa_studente->next_stud=NULL;
  83.              ultimo->testa_stud=testa_studente;
  84.          }
  85.          else{
  86.               nuovo->next_stud=testa_studente; // lo studente nuovo viene inserito in testa
  87.               testa_studente=nuovo;
  88.          }          
  89.              
  90.     }//else  
  91.        
  92. }  
  93.    
  94. void stampa_stud(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
  95.      
  96.      int aanno;
  97.      studente* temp_stud;
  98.      anno* temp_anno;
  99.      
  100.      temp_stud=testa_studente;
  101.      temp_anno=testa_anno;
  102.      
  103.      while(temp_anno->next_anno!=NULL){
  104.          printf("\n\n------- A N N O  %d --------- \n", temp_anno->anno);
  105.          
  106.          while(temp_stud!=NULL){
  107.              printf(" nome: %s\n cognome: %s\n matricola: %d \n", temp_stud->nome, temp_stud->cognome, temp_stud->matricola);
  108.              temp_stud=temp_stud->next_stud;
  109.          }
  110.          
  111.         temp_anno=temp_anno->next_anno;
  112.      }        
  113.      
  114.      
  115. }    
  116.  
  117.    
  118. int main(){
  119.    
  120.     int scelta=1;
  121.     anno* testa_anno=NULL;
  122.    
  123.    
  124.     while(scelta!=0){
  125.         system("cls");
  126.         printf("1 inserisci anno\n2 stampa anni\n3 inserisci studente\n4 stampa studenti");
  127.         printf("scelta: ");  scanf("%d", &scelta);
  128.    
  129.             if(scelta==1){ system("cls"); ins_anno(&testa_anno);   system("pause"); }
  130.             if(scelta==2){ system("cls"); stampa_anno(testa_anno); system("pause"); } // omettendo & non viene modficato niente
  131.             if(scelta==3){ system("cls"); ins_stud(&testa_anno);   system("pause"); }
  132.             if(scelta==4){ system("cls"); stampa_stud(testa_anno);   system("pause"); }// omettendo & non viene modficato niente
  133.     }    
  134.  
  135.  
  136. system("pause");
  137. return;
  138. }



PM Quote
Avatar
Bonny (Member)
Expert


Messaggi: 437
Iscritto: 24/04/2009

Segnala al moderatore
Postato alle 18:32
Venerdì, 04/01/2013
Visto la struttura dati che hai deciso di definire per contenere i studenti, non ha senso aggiungere un altro puntatore.
Gli anni sono contenuti in una lista (unidirezionale), ad ogni nodo (anno) c'è un puntatore ad una lista di studenti (unidirezionale) segue che per stampare tutti gli studenti:
Codice sorgente - presumibilmente Plain Text

  1. //per ogni nodo (anno) della lista
  2. while(lista_anno->next != NULL){
  3.   //prendo il ptr alla lista degli studenti
  4.   lista studenti = lista_anno->lista;
  5.   printf("ANNO : %d", lista_anno->id);
  6.   //per ogni studente
  7.   while(studenti->next != NULL){
  8.        //.. stampo le credenziali
  9.        printf("%s\n", atudente->nome, ....);
  10.        studenti = studenti->next;
  11.   }
  12.  
  13.  lista_anno = lista-anno-next;
  14. }



Per stampare gli studenti di un determinato anno:

Codice sorgente - presumibilmente C/C++

  1. lista studenti;
  2. int found = 0;
  3. int anno = 1993;
  4.  
  5. //per ogni anno della lista e fino a quando non trovo l'anno 1993...
  6. while(lista_anno->next != NULL && !found){
  7.    //se trovo l'anno 1993    
  8.    if(lista_anno->id == anno){
  9.       //prendo il ptr alla lista degli studenti
  10.       studenti = lista_anno->lista;
  11.       found = 1;
  12.  
  13.    }else{
  14.       lista_anno = lista-anno-next;
  15.    }
  16.  
  17. }
  18.  
  19. //stamp gli studenti del 1993
  20.  
  21. while(studenti->next != NULL){
  22.  
  23.        printf("%s\n", atudente->nome, ....);
  24.        studenti = studenti->next;
  25. }



Spero sia chiaro:k:

PM Quote
Avatar
Phi (Member)
Expert


Messaggi: 241
Iscritto: 30/12/2009

Segnala al moderatore
Postato alle 18:37
Venerdì, 04/01/2013
Innanzitutto attento che "cls" e "pause" sono comandi DOS. Penso siano disponibili solo per Windows.

Poi ci sono alcuni errori che non rendono perfettamente funzionante il programma.
Io ho fatto così.

1) ho eliminato la variabile testa_studente di cui mi sembra si possa fare a meno

2) in ins_stud ho :
* eliminato "ultimo->testa_stud=NULL;"
* invece dell'ultimo if-else ho scitto
nuovo->next_stud=ultimo->testa_stud;
ultimo->testa_stud=nuovo;
Tutta la funzione viene così :
Codice sorgente - presumibilmente C++

  1. void ins_stud(anno** testa_anno){
  2.     int esiste=0,aanno;
  3.     printf("anno frequentato: ");  scanf("%d", &aanno); // appositamente scritto aanno
  4.     anno* ultimo=*testa_anno;
  5.     do{
  6.         if(aanno==ultimo->anno){  esiste=1;   break;   }
  7.         else  ultimo=ultimo->next_anno;
  8.     }
  9.     while(ultimo!=NULL);
  10.     if(esiste==0){ puts("non esiste alcun anno selezionato"); }
  11.     else{
  12.          char nome[15],cognome[15];
  13.          int matricola;
  14.          puts("matricola: "); fflush(stdin);  scanf("%d", &matricola);
  15.          puts("nome: ");      fflush(stdin);  gets(nome);
  16.          puts("cognome: ");   fflush(stdin);  gets(cognome);
  17.          studente* nuovo;
  18.          nuovo=(studente*)malloc(sizeof(studente));
  19.          nuovo->matricola=matricola;
  20.          strcpy(nuovo->nome,nome);
  21.          strcpy(nuovo->cognome,cognome);
  22.          nuovo->next_stud=ultimo->testa_stud;
  23.          ultimo->testa_stud=nuovo;
  24.     }
  25. }



3) Ho modificato così stampa_stud :
* eliminato "int aanno" (era inusata, ma non era un problema)
* eliminato "temp_stud=testa_studente;" (perché ho eliminato la variabile testa_studente)
* sostituito "temp_anno->next_anno!=NULL" con "temp_anno!=NULL" (perché altrimenti ignoriamo un anno)
* posto "temp_stud=temp_anno->testa_stud;" subito dopo il while, così per ogni hanno scriviamo tutti a partire dall'ultimo inserito.
La procedure risulta così :
Codice sorgente - presumibilmente C/C++

  1. void stampa_stud(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
  2.      studente* temp_stud;
  3.      anno* temp_anno;
  4.      temp_anno=testa_anno;
  5.      while(temp_anno!=NULL){
  6.         printf("\n\n------- A N N O  %d --------- \n", temp_anno->anno);
  7.         temp_stud=temp_anno->testa_stud;
  8.         while(temp_stud!=NULL){
  9.              printf(" nome: %s\n cognome: %s\n matricola: %d \n", temp_stud->nome, tem$
  10.              temp_stud=temp_stud->next_stud;
  11.         }
  12.         temp_anno=temp_anno->next_anno;
  13.      }
  14. }



Così io l'ho testato e sembra funzionare.
Tuttavia se usassi anziché il C il C++(cambia pochissimo) potresti usare delle liste già implementate nelle librerie standard.
La libreria "list" delle STL fornisce dei template per le liste.

Edit : Attenzione: alla riga 9 della seconda funzione il carattere $ è stato sostituito al resto della riga.

Ultima modifica effettuata da Phi il 04/01/2013 alle 18:45
PM Quote
Avatar
tonno16 (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2013

Segnala al moderatore
Postato alle 16:05
Sabato, 05/01/2013
BONNI, grazie della risposta.
[QUOTE]Visto la struttura dati che hai deciso di definire per contenere i studenti, non ha senso aggiungere un altro puntatore. [/QUOTE]

che puntatore intendi????

PHI. si per la stampa ho corretto subito da solo.  nella testa non mi era entrato il concetto dell avariabile temp , ovvero temp=listaprimaria->punt_lista_secondaria. Nel mio caso temp_stud=temp_anno->testa_stud;

il programma ora corretto, funziona sicuramente, però in fase di esecuzione crasha. cioè stampa i nomi degli studenti e poi il programma crasha. idee??? ho provato a mettere nella stampa dopo tale istruzione;

temp_anno=temp_anno->next_anno;

anche temp_anno->next_anno=NULL;   perchè pensavo che il crash derivasse da un loop, ma mi sbagliavo.

IDEE???

grazie a tutti comunque per l''aiuto

PM Quote
Avatar
Bonny (Member)
Expert


Messaggi: 437
Iscritto: 24/04/2009

Segnala al moderatore
Postato alle 13:51
Domenica, 06/01/2013
Ho risposto a questa domanda, anzi ho dato la mia opinione:)

"DUNQUE devo far si che il nodo 10 della foto punti a 2???? cosi da avere un unica lista di studenti."

Comunque non devi pensare di numerare i nodi in sequenza basandoti su tutte le liste, ma per esempio:

1990  ->  1991 ->1992 ->   ......   ->  NULL
  1             1           1
  2             2           2
  .              .            .
  .              .            .
NULL        NULL      NULL

NB: liste unidirezionali.

prendi spunto dalle funzioni che ho scritto in pseudo-codice non dovresti avere alcun problema.... ragionaci su, usa il foglio di carta :) e poi vedrai che il codice si scrive da solo senza errori :k:

PM Quote
Avatar
tonno16 (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2013

Segnala al moderatore
Postato alle 15:35
Domenica, 06/01/2013
a ma infatti il compito che devo fare è tutto su foglio di carta.

comunque, espongo un altro problema, senza aprire altri topic, tanto sempre di liste di liste si parla.
la consegna dell esercizio è:

......Implementare infine una funzione che, presa come parametro la data di un appello, calcoli
quanti studenti hanno concluso l’esame in quell’appello (cioè quanti hanno superato sia lo scritto che......

Codice sorgente - presumibilmente C++

  1. STRUTTURE DATI USATE;
  2. struct Esame {
  3. int matricola;
  4. int voto;
  5. struct Esame *next;
  6. }
  7. struct Appello {
  8. int data_esame;
  9. struct Esame *scritto;
  10. struct Esame *orale;
  11. struct Appello *next;
  12. };




LO SPEZZONE DI CODICE DELLA PROF:

Codice sorgente - presumibilmente C++

  1. void conta_numero_studenti(struct Appello *elencoAppelli, int data_esame){
  2.      struct Appello *tempAppello;
  3.      struct Esame *tempScritto;
  4.      struct Esame *tempOrale;
  5.      int conta = 0;
  6.      tempAppello = elencoAppelli
  7.      
  8.      while (tempAppello != NULL)
  9.     {
  10.           if (tempAppello->data_esame == data_esame)
  11.          {
  12.              tempScritto = tempAppello->scritto;
  13.              while (tempScritto != NULL)
  14.             {
  15.                 tempOrale = tempAppello->orale;
  16.                 while (tempOrale != NULL)
  17.                    {
  18.                        if (tempScritto->matricola ==tempOrale->matricola)
  19.                       {
  20.                          conta++;
  21.                          break;
  22.                       }
  23.                      tempOrale = tempOrale->next;
  24.                    }
  25.                  tempScritto = tempScritto->next;
  26.              }
  27.            break;
  28.         }
  29.      tempAppello = tempAppello->next;
  30.   }
  31.  
  32. printf("Studenti che hanno concluso l'esame nell'appello con data
  33. indicata: %d", conta);
  34. }



secondo me, questa soluzione è sbagliatissima, a livello di logica. Ora mi spiego: nella lista ci sono studenti solo che hanno passato l'esame (ovvero da 18 a 30), quelli bocciati non ci sono.  la prof nella condizione per incrementare il numero di studenti (il conta++), ha questa condizione:

if (tempScritto->matricola == tempOrale->matricola)
   {
     conta++;
     break;
}


ma cosa vuol dire???? se il voto orale è uguale allo scritto, allora conta++???? pper quale motivo??? se pincopallino prende 30 orale e prende 23 nello scritto, i numeri sono diversi, il conta non si incrementa ma, il tipo ha comunque passato l'esame......

CHE RAZZA DI RAGIONAMENTO C'è DIETRO???

Ultima modifica effettuata da tonno16 il 06/01/2013 alle 15:47
PM Quote
Avatar
TheHerbalist (Normal User)
Newbie


Messaggi: 1
Iscritto: 06/01/2013

Segnala al moderatore
Postato alle 17:21
Domenica, 06/01/2013
Riguardo alla stampa studenti:
nella funzione ins_anno manca nuovo->testa_stud=NULL;
prima della riga nuovo->next_anno=*testa_anno; (aggiornamento puntatore)
Così sembra funzionare correttamente.

PM Quote
Avatar
Phi (Member)
Expert


Messaggi: 241
Iscritto: 30/12/2009

Segnala al moderatore
Postato alle 23:32
Domenica, 06/01/2013
Concordo dovrebbe essere:
Codice sorgente - presumibilmente C/C++

  1. if (tempScritto->matricola ==tempOrale->matricola) {
  2.           if ((tempScritto->v0to > 17)&&(tempOrale->voto > 17)) conta++;
  3.           break;
  4. }




Testo quotato


nella funzione ins_anno manca nuovo->testa_stud=NULL;


Non dovrebbe essere necessario: in qualsiasi sistema operativo decente quando alloco una variabile la zona di memoria andrebbe liberata(tuttavia non so se Windows rientri in questo insieme :), quindi si può aggiungerla per sicurezza).

PM Quote
Avatar
tonno16 (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2013

Segnala al moderatore
Postato alle 10:54
Lunedì, 07/01/2013
Codice sorgente - presumibilmente C/C++

  1. if (tempScritto->matricola ==tempOrale->matricola) {
  2.           if ((tempScritto->v0to > 17)&&(tempOrale->voto > 17)) conta++;
  3.           break;
  4. }


concordi col mio ragionamento??? quindi hai aggiunti quella condizione. Il mio dubbio sta nel primo. if. cosa serve verificare che il numeri di matricola per il voto orale deve essere uguale alla matricola del voto per lo scritto???

Testo quotato



Non dovrebbe essere necessario: in qualsiasi sistema operativo decente quando alloco una variabile la zona di memoria andrebbe liberata(tuttavia non so se Windows rientri in questo insieme :), quindi si può aggiungerla per sicurezza).



non ci ho mai fatto caso. Comunque ci impongono di usare questa istruzione subito dentro la main.

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo