DOMANDA Linguaggio C: Problema funzione

saro1995

Nuovo Utente
82
3
Salve a tutti ragazzi, sto svolgendo un esercizio in linguaggio C, mi sono imbattuto in una funzione che non riesco proprio ad implementare. La funzione ha questa richiesta: Funzione di modifica turno tra due studenti. Scambia tra loro due studenti(appartenenti a turni diversi). La funzione da implementare deve avere la seguente struttura:
nome della funzione: Scambia Turno
valore restituito: esito operazione (0: operazione fallita, 1: eliminazione effettuata con successo.
parametri: lista dei prenotati, matricola studente 1, matricola studente 2;
Questa è la struttura dati:
(fino ad adesso questo è tutto quello che ho fatto, so implementare bene o male questa funzione ma non mi riesce! Aiutatemi voi pls
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*DEFINIZIONE STRUTTURE DATI*/
typedef struct Prenotato {
    char cognome[15];
    char nome[15];
    char matricola[10];
}TPrenotato;

typedef struct NodoPrenotato {
    TPrenotato info;
    struct NodoPrenotato *next;
}TNodoPrenotato;
typedef TNodoPrenotato* TListaPrenotati;

typedef struct Turno {
    int numero_turno;
    TListaPrenotati elenco_prenotati;
}STurno;

typedef struct NodoTurno {
    STurno info;
    struct NodoTurno *next;
}TNodoTurno;
typedef TNodoTurno* TListaTurni;



/*FUNZIONI IMPLEMENTATE*/
TListaPrenotati CreaListaPrenotati() {
    return NULL;
}
TListaTurni CreaListaTurni() {
    return NULL;
}
//1 Funzione: Inserimento in ordine in base al cognome degli studenti
void InserisciInOrdineInListaPrenotati(TListaPrenotati *lis, TPrenotato elem) {
    TListaPrenotati prec, curr, newnode;
    if ((newnode = (TListaPrenotati)malloc(sizeof(TNodoPrenotato))) == NULL) {
        printf("Errore: Impossibile allocare memoria.\n");
        exit(1);
    }
    newnode->info = elem;
    prec = NULL;
    curr = *lis;
    while (curr != NULL && strcmp(curr->info.cognome, elem.cognome) < 0) {
        prec = curr;
        curr = curr->next;

    }
    newnode->next = curr;
    if (prec != NULL) {
        prec->next = newnode;
    }
    else {
        *lis = newnode;
    }
}

//2 Funzione: Caricamento degli studenti prenotati all'esame tramite un file .txt
int CaricaPrenotati(char *nomefile, TListaPrenotati *plis) {
    FILE *f;
    TPrenotato prenotato;
    int numero_studenti = 0;
    if ((f = fopen(nomefile, "r")) == NULL) {
        printf("Errore nell'apertura del file.\n");
        exit(1);
    }
    *plis = NULL;
    while (!feof(f)) {
        if (fscanf(f, "%s\t%s\t%s", prenotato.cognome, prenotato.nome, prenotato.matricola) != 3)
            break;
        InserisciInOrdineInListaPrenotati(plis, prenotato);
        numero_studenti++;
    }
    fclose(f);
    return numero_studenti;
}





/*FUNZIONE PRINCIPALE MAIN*/
int main(void) {
    char nomefile[20];
    int n;
    TListaPrenotati lista_prenotati;
    TListaTurni lista_turni;
    lista_prenotati = CreaListaPrenotati();
    lista_turni = CreaListaTurni();
    printf("Inserisci il nome del file da cui caricare gli studenti: ");
    scanf("%s", nomefile);
    n = CaricaPrenotati(nomefile, &lista_prenotati);
    printf("\n");
    printf("Sono stati caricati %d studenti.\n", n);



    return 0;
}

//3 Funzione: Modifica il turno tra
 

Sysken

Nuovo Utente
51
20
Ciao @saro1995,
Parere altamente personale: secondo me tutte queste definizioni "corrompono" un pò la leggibilità/chiarezza del programma:
C:
/*DEFINIZIONE STRUTTURE DATI*/
struct Prenotato {
    char cognome[15];
    char nome[15];
    char matricola[10];
};
typedef struct Prenotato nome_delNodo;
typedef nome_delNodo* nome_delPuntatore;

struct Turno {
    int numero_turno;
    NODE_PTR nome_significativo;
};
typedef struct Turno nome_delNodo;
typedef nome_delNodo* nome_delPuntatore;

Inoltre, se ho capito bene devi scambiare la posizione di due studenti, giusto? Oppure devi scambiare solo il turno? Potresti postare la traccia dell'esercizio?
 

Sysken

Nuovo Utente
51
20
Bene, una volta letto il file avremo una lista di prenotati lunga N. Quando dovremo creare la lista dei turni, a quanto ho capito, sarà necessario dividere la lista prenotati in M sottoliste, dove M è il numero dei turni totali, non noto a priori. Ogni sottolista sarà composta da 50 prenotati, potremmo procedere in questo modo: scrolliamo la lista fino alla fine e mediante un indice verifichiamo se è necessario creare un nuovo turno. Ogni turno avrà un proprio numero di turno e il campo elenco, il campo elenco sarà il puntatore al prenotato riscontrato al momento della creazione del nuovo turno, quindi per intenderci, al primo turno avremo il puntatore alla lista prenotati (primo elemento, ovvero la testa), al secondo il puntatore al 50-esimo elemento della lista e così via. Dobbiamo ora però risolvere un problema, ovvero che le M sottoliste sono ancora logicamente collegate, per sconnetterle porremo a NULL il puntatore al prossimo prenotato del 50-esimo prenotato della sottolista, questa operazione può essere effettuata o una volta creati tutti i turni scrollando ogni singola lista fino all'ultimo elemento, o prima della creazione di un nuovo turno (facendo attenzione che non sia il primo), supponendo di trovarsi al 50-esimo elemento, salviamo il puntatore al 51-esimo in una variabile temporanea (tempPtr = listaPrenotato->prossimoPrenotato), poniamo a NULL il prossimo elemento listaPrenotato->prossimoPrenotato = NULL e infine avanziamo nella lista listaPrenotato = tempPtr. Ho utilizzato 50 solo a scopo illustrativo, il tutto scalerà di 50 in 50 (50 100 150 ...).
A questo il problema di scambiare di turno due studenti si semplifica nello scambio di elementi tra due liste. Quindi, partendo dal puntatore elenco del primo nodo e dal puntatore elenco del secondo, individuo la posizione dei due prenotati, ed effettuo lo scambio.

>> Sicuro che la lista dei prenotati sia una lista autoreferenziale? Non vedo nessun puntatore nella struct, potrebbe trattarsi anche di un array, volendo.
 
Ultima modifica:

Sysken

Nuovo Utente
51
20
Di quale parte in particolare? Lo scambio tra le due sottoliste o la creazione della lista turni e quindi delle sottoliste?

Ripropongo:
>> Sicuro che la lista dei prenotati sia una lista autoreferenziale? Non vedo nessun puntatore nella struct, potrebbe trattarsi anche di un array, volendo.
 

saro1995

Nuovo Utente
82
3
Di quale parte in particolare? Lo scambio tra le due sottoliste o la creazione della lista turni e quindi delle sottoliste?

Ripropongo:
Si, penso si tratti anche di un array. Comunque puoi farmi un esempio in codice diella creazione della lista turni e sottoliste? Lo scambio degli studenti penso che sarà uno scambio semplice sicuramente che è una funzione che so già implementare, ma se non ti secchi scrivi anche quello per la mia sicurezza per favore XD... Grazie
 

Sysken

Nuovo Utente
51
20
Bene, tratterò il caso in cui si tratti di una lista, adattarlo non sarà poi un problema, l'importante è trovare una "pseudo"-soluzione per poi affinarla e questo sarà ovviamente compito tuo:
C:
/*DEFINIZIONE STRUTTURE DATI*/
struct Prenotato {
    char cognome[15];
    char nome[15];
    char matricola[10];
    struct Prenotato* nextPrenotato; // Aggiunto da me
};
typedef struct Prenotato PRENOTATO;
typedef PRENOTATO* PRENOTATO_PTR;

struct Turno {
    int numero_turno;
    PRENOTATO_PTR subLista_Prenotati;    // Puntatore alla sottolista
};
typedef struct Turno TURNO;
typedef TURNO* TURNO_PTR;

// Supponiamo che la lista dei Prenotati sia già stata inserita

TURNO_PTR createList(PRENOTATO_PTR listaPrenotati){
    int numero_turno = 1;
    int index = 0;
    NODE_PTR prevPrenotato = NULL;
    while(listaPrenotati != NULL){
        if(index % 50 == 0){
            TURNO_PTR newNode = ... // Alloca memoria per un nuovo nodo della lista turno
            if(newNode != NULL){    // Se l'allocazione è avvenuta con successo
                newNode->numero_turno = numero_turno;
                numero_turno++;
                newNode->subLista_Prenotati = listaPrenotati; // Il puntatore corrente della lista Prenotati equivale alla testa della sottolista dei prenotati
                if(index != 0){     // Nel caso il nodo allocato non fosse il primo (in alternativa: if(prevPrenotato != NULL))
                    prevPrenotato->nextPrenotato = NULL;      // Distacco le due sottoliste adiacenti, prevPrenotato contiene il puntatore alla coda della sottolista del turno precedente
                }
            }
        }
        index++;
        prevPrenotato = listaPrenotati;
        listPrenotati = listaPrenotati->nextPrenotato;
    }
}

Premetto, non ho testato il codice, l'ho scritto ora in due minuti, quindi potrebbe contenere errori, il mio consiglio è di "approfondirlo". Per quanto riguarda la funzione di scambio, prova a scriverla, se poi dovessi incontrare delle difficoltà sarò disponibile per aiutarti. :ok:
 
  • Mi piace
Reazioni: saro1995

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili