Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643

    [C] Secondo voi come soluzione è un delirio o ci può stare?

    WOW..l'esame di programmazione 1 è il 15 e non l'1...ho ancora 2 settimane per prepararmi (vi prego di sopportatmi ancora per un po').

    Ho fatto questo esercizio...sicuramente c'è qualcosa che non và perchè sono stanco (infatti il compilatore dà qualche messaggino inquietante di troppo).
    Ma visto che l'esame è su carta bada principalmente alla logica (poi nel caso domani mattina gli dò una sistemata e vedo cos'è che non và).
    Secondo voi la mia soluzione ha senso o è un delirio dal punto di vista logico?

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Dat{
        long coD;
        char *descr;    // Stringa allocata dinamicamente
        struct Dat *next;
    } Dat, *LDat;
    
    /* La funzione LDat() riceve in ingresso il puntatore al primo nodo di una lista
       L ed in puntatore al primo nodo di una lista M.
       Modifica la lista L nel seguente modo: per ogni elemento d della lista M se
       d.coD è negativo elimina da L, se esiste, l'elemento con campo coD uguale a
       -d.coD. Se invece d.cod è positivo inserisce (se un elemento con lo stesso
       valore del campo coD non esiste in L) un nuovo elemento in L uguale a d.
       La funzione ritorna il puntatore alla lista modificata (che può essere NULL).
       Le modifiche indotte dagli elementi di M devono essere effettuate seguendo
       l'ordine degli elementi di M, è quindi possibile che un elemento venga prima
       inserito e poi eliminato o viceversa.
       Si assume che  i valori dei campi coD degli elementi di L siano interi
       positivi distinti e che gli elementi siano in ordine crescente rispetto al
       campo coD.
       
       Esempio: L è: {4, "libro"}->{6, "mela"}->{7, "piede"}->{9, "mano"}
       M è: {3, "a"}->{-4, ""}->{-3, "b"}->{5,"poi"}->{7,"per"}->{8,"re"}->{-2,"se"}
       
       L modificata è: {5, "poi"}->{6, "mela"}->{7, "piede"}->{8, "re"}->{9, "mano"}
       */
    
    LDat Mod(LDat L, LDat M){
        
        LDat Ls = L;    // Puntatore di scorrimento della lista settato al 1° nodo
        LDat p;  // Puntatore che punta al predecessore in L del punto da modificare
        LDat nuovonodo;    // Puntatore al nuovo nodo da allocare dinamicamente
        int codcor;    // Valore del campo coD del nodo corrente in M
        
        while(M != NULL){    // Scorri la lista M fino in fondo
            
             codcor = M->coD;
             
             /* Se codcor è minore di 0 verrà eliminato un nodo nella lista L nel
                caso vi sia un elemento con uguale valore del campo coD */
             if(codcor<0){
                 
                 p = find(L, -(codcor)); // Nodo precedente alla potenziale modifica
                 
                 /* Se p punta a NULL vuol dire che l'elemento interessato è il
                    primo nodo della lista, se il primo nodo della lista ha il campo
                    coD uguale a -codcor eliminalo */
                 if(p==NULL && L->coD == -(codcor)){
                     Ls = L->next;  // Ls punta al nuovo primo nodo della lista
                     free(L->descr); // Libera la memoria per la stringa
                     free(L);        // Elimina il nodo
                     L = Ls;         // Ora anche L punta al nuovo primo nodo
                 }
                 
                 /* Se l'elemento puntato da (p->next)->next è NULL (non esiste)
                    significa che l'elemento puntato da p->next è l'ultimo nodo
                    della lista e se il campo coD di p->next è uguale al valore di
                    codcor allora sarà eliminato l'ultimo nodo dalla lista */
                 else if((p->next)->next == NULL && (p->next)->coD == codcor){
                     (p->next)->next = NULL; /* Setta a NULL il campo next del nodo
                                                puntato da p->next */
                      free((p->next)->descr);
                      free((p->next)->next);
                      Ls=L;
                 }
                 
                 /* Altrimenti si tratta di un elemento mediano posto tra altri due
                    nodi della lista */
                 
                 else{
                     if((p->next)->coD == codcor){
                         /* Setta il valore del campo next del nodo puntato da p
                            con l'indirizzo del nodo successivo a quello puntato da
                            p->next (p->next sarà eliminato e p sarà linkato al suo
                            successivo) */
                         p->next=(p->next)->next;
                         free((p->next)->descr); // Elimina la stringa
                         free(p->next); // Elimina il nodo successivo a p
                         Ls = L;        // Setta Ls al primo nodo della lista L
                     }
                 }
             }
             
             /* Se codcor è positivo verrà aggiunto un nodo in caso non esista un
                nodo avente campo coD uguale al valore di codcor */
             else{
                p = find(L, codcor); // Nodo precedente alla potenziale modifica
                
                /* Se il puntatore p è nullo, l'elemento successivo è il primo nodo
                   della lista, se il campo coD del primo nodo è diverso da codcor
                   allora sarà creato un nuovo primo elemento da linkare alla lista
                   */
                if(p == NULL && (L->coD) > codcor){
                    nuovonodo = malloc(sizeof(Dat)); // Alloca un nuovo nodo
                    /* Alloca dinamicamente la memoria per la stringa puntata dal
                       puntatore contenuto nel campo descr del nuovonodo */
                    nuovonodo->descr = malloc(strlen((M->descr)+1)*sizeof(char));
                    strcpy(nuovonodo->descr, M->descr); // Copia la stringa
                    nuovonodo->next=L; // Setta il campo next al vecchio ptimo nodo
                    L=nuovonodo;       // Setta L all'indirizzo del nuovo primo nodo
                    Ls=L;              // Setta Ls al primo nodo
                }
                
                /* Se (p->next)->next corrisponde a null significa che l'elemento
                   successivo a p (p->next) è l'ultimo nodo della lista.
                   Se il campo coD dell'ultimo nodo è minore del valore di codcor
                   allora bisogna linkare un nuovo ultimo nodo */
                   
                if((p->next)->next == NULL && (p->next)->coD < codcor){
                    nuovonodo = malloc(sizeof(Dat)); // Alloca un nuovo nodo
                    /* Alloca dinamicamente la memoria per la stringa puntata dal
                       puntatore contenuto nel campo descr del nuovonodo */
                    nuovonodo->descr = malloc(strlen((M->descr)+1)*sizeof(char));
                    strcpy(nuovonodo->descr, M->descr); // Copia la stringa
                    (p->next)->next=nuovonodo;
                    nuovonodo->next=NULL; // è l'ultimo nodo
                    Ls=L;
                }
                
                /* Altrimenti è un nodo mediano, se il campo coD di p->next è
                   diverso a codcor crea un nuovo nodo e linkalo */    
                else{
                    if((p->next)->coD != codcor){
                        nuovonodo = malloc(sizeof(Dat)); // Alloca un nuovo nodo
                       /* Alloca dinamicamente la memoria per la stringa puntata dal
                         puntatore contenuto nel campo descr del nuovonodo */
                       nuovonodo->descr = malloc(strlen((M->descr)+1)*sizeof(char));
                       strcpy(nuovonodo->descr, M->descr); // Copia la stringa
                       nuovonodo->next=(p->next)->next;
                       p->next=nuovonodo;
                       Ls=L;
                   }
               }
           }    
           return L;
    }
           
    LDat find(LDat L, int cd){
        
        LDat prev = NULL;
        
        while(cd < L->coD){
            prev = L;
            L = L->next;
        }
        
        return prev;
    }
    Ancora mille grazie
    Andrea

  2. #2
    Utente di HTML.it L'avatar di anx721
    Registrato dal
    Apr 2003
    Messaggi
    2,352
    La funzione LDat è errata perche scorre la lista senza fermarsi quando la lista è terminata:

    codice:
    while(cd < L->coD){
    	prev = L;
    	L = L->next;
    }
    mentre dovrebbe essere



    codice:
    while(L && (cd < L->coD)){
    	prev = L;
    	L = L->next;
    }
    codice:
    Un altro errore sta nel caso in cui devi eliminare l'ultimo elemento della lista perche scrivi.
    
    /* Se l'elemento puntato da (p->next)->next è NULL (non esiste)...
    else if((p->next)->next == NULL && (p->next)->coD == codcor){
    	(p->next)->next = NULL; /* Setta a NULL il campo next del nodo
    cioè se (p->next)->next è NULL lo imposti a NULL...mentre te devi impostare a NULL p->next e devi deallocare p->next, non (p->next)->next. Poi qualke piccola ottimizzazione, che più che altro serve a rendere piu compatto il codice e piu leggibile, ad esempio se il nodo lo devi aggiungere alla lista puoi crearlo una sola volta all'inizio prima di fare i 3 if, e non crearlo all'interno di ogni if.

    Sun Certified Java Programmer

    EUCIP Core Level Certified

    European Certification of Informatics Professionals

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    mmm grazie, credo di aver capito...eheh ero ababstanza stanco ieri sera...

    La cosa che mi risulta un po' più difficile capire è: p può anche puntare all'ultimo nodo quindi? giustamente puntando al punto precedente la modifica se và inserito un nuovo ultimo nodo allora p punta all'ultimo prima dell'inserimento del nuovo nodo nella lista....capito bene?

    Grazie
    Andrea

  4. #4
    Utente di HTML.it L'avatar di anx721
    Registrato dal
    Apr 2003
    Messaggi
    2,352
    Originariamente inviato da D4rkAng3l
    mmm grazie, credo di aver capito...eheh ero ababstanza stanco ieri sera...

    La cosa che mi risulta un po' più difficile capire è: p può anche puntare all'ultimo nodo quindi? giustamente puntando al punto precedente la modifica se và inserito un nuovo ultimo nodo allora p punta all'ultimo prima dell'inserimento del nuovo nodo nella lista....capito bene?
    si

    Sun Certified Java Programmer

    EUCIP Core Level Certified

    European Certification of Informatics Professionals

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    ok...grazie perfetto...l'esercizio era da 12 punt (era un esercizio d'esame...) fato così per te quanti ne avrei presi?sinceri

  6. #6
    Utente di HTML.it L'avatar di anx721
    Registrato dal
    Apr 2003
    Messaggi
    2,352
    ma..dipende come valuta il professore..direi un 9.5

    ot: sei alla sapienza? che prof?

    Sun Certified Java Programmer

    EUCIP Core Level Certified

    European Certification of Informatics Professionals

  7. #7
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    si Sapiemza...il proff è Silvestri...lo conosci?

  8. #8
    Utente di HTML.it L'avatar di anx721
    Registrato dal
    Apr 2003
    Messaggi
    2,352
    [C], può andar bene questa soluzione?
    L'esame è il 15...può andar bene questa soluzione:


    /* La funzione Agg(), modifica i valori del campo val degli elementi della lista
    L in modo tale che il valore del campo val di un elemento m sia pari alla
    somma dei (vecchi) valori dei campi val dell'elemento m e degli elementi
    successivi che sono interi dispari.
    Esempio: se la sequenza dei valori dei campi val della lista era:2,5,8,3,2,4
    allora l funzione la modifica così: 10,8,11,3,2,4. */

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Elem{
        long val;
        struct Elem *next;
    } Elem, *List;    
    
    void Agg(List L){
        
        /* Dichiaro il puntatore al nodo corrente e lo setto al primo nodo */
        List corrente = L; 
        
        while(corrente != NULL){    // Finchè non raggiunge la fine della lista
            L->val += Som(L->next);
            L = L->next;        // Passa al prossimo nodo
        }
    }
    
    
    /* La funzione Som() riceve l'indirizzo del nodo successivo al nodo corrente e
       calcola la somma di tutti gli elementi aventi campo val dispari per poi
       restituire il risultato alla funzione Agg() */
       
    long Som(List L){
        
        long somma = 0;
        
        if(L == 0)    return 0;   // Se non ci sono altri elementi la somma è 0
        
        else{
            while(L->next != NULL){
                if(L->val%2==1) // Se il campo val del nodo puntato da L è dispari
                     somma += L->val;
                
                L = L->next;    // Passa al prossimo nodo
            }
        return somma;            // Ritorna ad Agg il valore della somma
        }
    }
    Grazie
    Andrea
    La soluzione è giusta modificando la condizione del while della funzione somma in

    while(L != NULL)

    anche se non è molto efficiente in quanto scorri la lista per ogni elemento; ricorrendo alla ricorsione si può fare di meglio: l'idea e di avere una funzione ricorsiva che si occupa di aggiornare l'elemento su cui è chiamata facendo in modo che la funzione lavori dall'ultimo elemento verso il primo in modo che con un'unica passata sia progressivamente calcolata la somma da aggiungere al campo val di un elemento.


    Codice PHP:
    void Agg(List L){
        if((
    == NULL) || (-> next == NULL)
            return;
        
    //valore dell'elemento successivo prima dell'aggiornamento
        
    int prima -> next -> val;
        
    //aggiorno l'elemento successivo
        
    Agg(-> next);
        
    //Ora aggiorno l'elemento corrente: sommo il contributo
        //dei numeri dispari che è arrivato all'elemento successivo
        //e che corrisponde al suo incremento
        
    -> val -> val + (-> next -> val prima);
        
    //e infine sommo il vecchio valore dellìelemento successivo
        //se era dispari
        
    if((prima 2) == 1)
            
    -> val -> val prima;


    Sun Certified Java Programmer

    EUCIP Core Level Certified

    European Certification of Informatics Professionals

  9. #9
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    Altro esercizio..pls helpme

    Ecco l'ennesimo esercizio del proff risolto prima dell'esame.

    codice:
    Esercizio 2    (max 10 punti)
    
    Scrivere una funzione, con prototipo int Inv(char *nameF, char *invF), che legge il file di tipo testo il cui nome è nella
    stringa nameF, contenente una sequenza di stringhe separate da spazi, e crea un nuovo file di testo, con nome dato dalla stringa invF,
    scrivendoci la sequenza inversa e ritorna la massima lunghezza delle stringhe. Le stringhe hanno una lunghezza non superiore a 100.
    Ad esempio se il file nameF contiene la sequenza giallo verde blu allora il nuovo file deve contenere
    blu verde giallo e la funzione deve ritornare 6.
    Soluzione Esercizio 2
    /* Funzione ausiliaria che ritorna la k-esima stringa del file f. Se tale stringa
       non esiste ritorna NULL                                                        */
    const char *KthStr(FILE *f, int k)
    {   
        static char str[101];
        rewind(f);
        while (k > 0 && fscanf(f, "%s", str) == 1) k--;
        return (k == 0 ? str : NULL);
    }
    int Inv(char *nameF, char *invF)
    {
        FILE *f = fopen(nameF, "r");        //Apri il file in lettura
        FILE *newF = fopen(invF, "w+");     //Crea ed apri il nuovo file
        int nStr = 0, max = 0;
        char str[101];                            //Calcola il numero di stringhe
        while (fscanf(f, "%s", str) == 1) nStr++;
        while (nStr > 0) {                        //A partire dall'ultima stringa,
            const char *s = KthStr(f, nStr);      //leggi le stringhe in ordine inverso
            int len = strlen(s);                  //e scrivile nel nuovo file,
            if (len > max) max = len;             //aggiornando il calcolo della
            fprintf(newF, "%s ", s);              //lunghezza massima.
            nStr--;
        }
        fclose(f);
        fclose(newF);
        return max;
    }
    La funzione ausiliaria riceve il numero del k-esima stringa el la ritorna:
    ma che vuol dire: while (k > 0 && fscanf(f, "%s", str) == 1) k--; perchè nel corpo del while viene anche inserito che fscanf deve essere == 1 ? Se io gli passo il numro della stringa da restituire e gli dico di ciclare finchè non ci arriva non è uguale?!?!

    Altra cosa....

    che significa questa riga (mi ci impiccio ancora con le scritture compresse):
    return (k == 0 ? str : NULL);

    Grazie e scusate la mia estrema ignoranza

  10. #10
    Utente di HTML.it L'avatar di byaur
    Registrato dal
    Aug 2004
    Messaggi
    1,061
    è l'operatore ternario...
    alla sapienza lo dovrebbero spiegare...

    cmq a parole significa:
    se k== 0 allora ritorna str altrimenti ritorna NULL.

    Chi di noi non vorrebbe
    sollevare il velo sotto cui sta nascosto il
    futuro...
    David Hilbert

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.