Oppure

Loading
04/01/13 11:16
tonno16
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:

img97.imageshack.us/img97/4989/…

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.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct __studente{
  int matricola;
  char nome[20];
  char cognome[20];
  int esame[6];
  struct __studente* next_stud;
}studente;

typedef struct __anno{
  int anno;
  struct __anno* next_anno;
  struct __studente* testa_stud;
}anno;

studente* testa_studente=NULL;

void ins_anno(anno** testa_anno){
    
    int aanno;
    printf("inserire anno: "); scanf("%d", &aanno); // ATTENZIONE è AANNO E NON ANNO
    
    anno* temp;
    temp=*testa_anno; // mi appoggio a temp
    
    while(temp!=NULL){ // CONTROLLO SE L' ANNO è GIà PRESENTE
        if(temp->anno==aanno){ printf("anno già inserito"); return; }
        temp=temp->next_anno;
    }
    
    anno* nuovo;
    nuovo=(anno*)malloc(sizeof(anno));
    nuovo->anno=aanno;
    nuovo->next_anno=*testa_anno;
    *testa_anno=nuovo;
}    

void stampa_anno(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
    
     if(testa_anno!=NULL){
         printf(" %d\n", testa_anno->anno);      
         stampa_anno(testa_anno->next_anno);
     }
}

void ins_stud(anno** testa_anno){
    
    int esiste=0,aanno;
    printf("anno frequentato: ");  scanf("%d", &aanno); // appositamente scritto aanno
    
    anno* ultimo=*testa_anno;
    ultimo->testa_stud=NULL;
    
    do{
        if(aanno==ultimo->anno){  esiste=1;   break;   }
        else{
             ultimo=ultimo->next_anno;
        }
    }
    while(ultimo!=NULL);
    
    if(esiste==0){ puts("non esiste alcun anno selezionato"); }
    else{
         char nome[15],cognome[15];
         int matricola;
         
         puts("matricola: "); fflush(stdin);  scanf("%d", &matricola);
         puts("nome: ");      fflush(stdin);  gets(nome);
         puts("cognome: ");   fflush(stdin);  gets(cognome);
         
         studente* nuovo;
         nuovo=(studente*)malloc(sizeof(studente));
         nuovo->matricola=matricola;
         strcpy(nuovo->nome,nome);
         strcpy(nuovo->cognome,cognome);
         
         if(ultimo->testa_stud==NULL){// se non ci sono studente in quell anno
             testa_studente=nuovo;
             testa_studente->next_stud=NULL;
             ultimo->testa_stud=testa_studente;
         }
         else{
              nuovo->next_stud=testa_studente; // lo studente nuovo viene inserito in testa
              testa_studente=nuovo;
         }           
             
    }//else   
        
}  
    
void stampa_stud(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
     
     int aanno;
     studente* temp_stud;
     anno* temp_anno;
     
     temp_stud=testa_studente;
     temp_anno=testa_anno;
     
     while(temp_anno->next_anno!=NULL){
         printf("\n\n------- A N N O  %d --------- \n", temp_anno->anno);
         
         while(temp_stud!=NULL){
             printf(" nome: %s\n cognome: %s\n matricola: %d \n", temp_stud->nome, temp_stud->cognome, temp_stud->matricola);
             temp_stud=temp_stud->next_stud;
         }
         
        temp_anno=temp_anno->next_anno;
     }        
     
     
}    

    
int main(){
    
    int scelta=1;
    anno* testa_anno=NULL;
    
    
    while(scelta!=0){
        system("cls");
        printf("1 inserisci anno\n2 stampa anni\n3 inserisci studente\n4 stampa studenti");
        printf("scelta: ");  scanf("%d", &scelta); 
    
            if(scelta==1){ system("cls"); ins_anno(&testa_anno);   system("pause"); }
            if(scelta==2){ system("cls"); stampa_anno(testa_anno); system("pause"); } // omettendo & non viene modficato niente
            if(scelta==3){ system("cls"); ins_stud(&testa_anno);   system("pause"); }
            if(scelta==4){ system("cls"); stampa_stud(testa_anno);   system("pause"); }// omettendo & non viene modficato niente
    }    


system("pause");
return;
}   


aaa
04/01/13 17:32
Bonny
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:
//per ogni nodo (anno) della lista
while(lista_anno->next != NULL){
  //prendo il ptr alla lista degli studenti
  lista studenti = lista_anno->lista;
  printf("ANNO : %d", lista_anno->id);
  //per ogni studente 
  while(studenti->next != NULL){
       //.. stampo le credenziali
       printf("%s\n", atudente->nome, ....);
       studenti = studenti->next;
  }

 lista_anno = lista-anno-next;
}


Per stampare gli studenti di un determinato anno:


lista studenti;
int found = 0;
int anno = 1993;

//per ogni anno della lista e fino a quando non trovo l'anno 1993...
while(lista_anno->next != NULL && !found){
   //se trovo l'anno 1993    
   if(lista_anno->id == anno){
      //prendo il ptr alla lista degli studenti
      studenti = lista_anno->lista;
      found = 1;

   }else{
      lista_anno = lista-anno-next;
   }
  
}

//stamp gli studenti del 1993

while(studenti->next != NULL){

       printf("%s\n", atudente->nome, ....);
       studenti = studenti->next;
}


Spero sia chiaro:k:
aaa
04/01/13 17:37
Phi
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ì :
void ins_stud(anno** testa_anno){
    int esiste=0,aanno;
    printf("anno frequentato: ");  scanf("%d", &aanno); // appositamente scritto aanno
    anno* ultimo=*testa_anno;
    do{
        if(aanno==ultimo->anno){  esiste=1;   break;   }
        else  ultimo=ultimo->next_anno;
    }
    while(ultimo!=NULL);
    if(esiste==0){ puts("non esiste alcun anno selezionato"); }
    else{
         char nome[15],cognome[15];
         int matricola;
         puts("matricola: "); fflush(stdin);  scanf("%d", &matricola);
         puts("nome: ");      fflush(stdin);  gets(nome);
         puts("cognome: ");   fflush(stdin);  gets(cognome);
         studente* nuovo;
         nuovo=(studente*)malloc(sizeof(studente));
         nuovo->matricola=matricola;
         strcpy(nuovo->nome,nome);
         strcpy(nuovo->cognome,cognome);
         nuovo->next_stud=ultimo->testa_stud;
         ultimo->testa_stud=nuovo;
    } 
}


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ì :
void stampa_stud(anno* testa_anno){//** VISUALIZZAZIONE LISTA -- parte dalla coda.
     studente* temp_stud;
     anno* temp_anno;
     temp_anno=testa_anno;
     while(temp_anno!=NULL){
        printf("\n\n------- A N N O  %d --------- \n", temp_anno->anno);
        temp_stud=temp_anno->testa_stud;
        while(temp_stud!=NULL){
             printf(" nome: %s\n cognome: %s\n matricola: %d \n", temp_stud->nome, tem$
             temp_stud=temp_stud->next_stud;
        }
        temp_anno=temp_anno->next_anno;
     } 
}


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 04/01/13 17:45
aaa
05/01/13 15:05
tonno16
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
aaa
06/01/13 12:51
Bonny
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:
aaa
06/01/13 14:35
tonno16
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......

STRUTTURE DATI USATE;
struct Esame {
int matricola;
int voto;
struct Esame *next;
}
struct Appello {
int data_esame;
struct Esame *scritto;
struct Esame *orale;
struct Appello *next;
};



LO SPEZZONE DI CODICE DELLA PROF:

void conta_numero_studenti(struct Appello *elencoAppelli, int data_esame){
     struct Appello *tempAppello;
     struct Esame *tempScritto;
     struct Esame *tempOrale;
     int conta = 0;
     tempAppello = elencoAppelli
     
     while (tempAppello != NULL)
    {
          if (tempAppello->data_esame == data_esame)
         {
             tempScritto = tempAppello->scritto;
             while (tempScritto != NULL)
            {
                tempOrale = tempAppello->orale;
                while (tempOrale != NULL)
                   {
                       if (tempScritto->matricola ==tempOrale->matricola)
                      {
                         conta++;
                         break;
                      }
                     tempOrale = tempOrale->next;
                   }
                 tempScritto = tempScritto->next;
             }
           break;
        }
     tempAppello = tempAppello->next;
  }

printf("Studenti che hanno concluso l'esame nell'appello con data
indicata: %d", conta);
}


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 06/01/13 14:47
aaa
06/01/13 16:21
TheHerbalist
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.
aaa
06/01/13 22:32
Phi
Concordo dovrebbe essere:
if (tempScritto->matricola ==tempOrale->matricola) {
          if ((tempScritto->v0to > 17)&&(tempOrale->voto > 17)) conta++;
          break;
}



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).
aaa