[C] Ordinamento di una struct, è la soluzione adatta?

di il
6 risposte

[C] Ordinamento di una struct, è la soluzione adatta?

Salve a tutti, avrei voluto direttamente allegarvi il file .c che ho creato ma ricevo un errore allegandolo alla discussione. Per cui provo a spiegare lo scopo del programma e come lo ho risolto.
Data una struttura dati costituita dai campi titolo, autore, anno e costo, voglio simulare il funzionamento di un applicazione simile ad iTunes. Creati un array di struttura all'interno del quale carico una lista di brani, ed un secondo chiamato playlist dove inserirò un numero definito di brani sviluppo ogni problema con una funzione o procedura a seconda dei casi:
procedura per l'acquisizione della lista dei brani;
procedura che stampa la lista;
procedura che crea la playlist, chiedendo all'utente di inserire dei dati relativi ad un brano e inserendoli nella playlist solo se tutti corrispondono a quelli di un brano presente nella lista principale

void creaPlaylist(struct brani lista[],struct brani preferiti[])
{
	int i,j,trovato;
	printf("\n-----------CREAZIONE PLAYLIST-----------\n\n");
	for(i=0;i<DIMplaylist;i++)
	{
		trovato=0;
		do
		{
			j=0;
			printf("Inserire i dati relativi al %do brano della playlist: ",i+1);
			printf("\nTitolo, Autore, Anno di uscita, Prezzo\n");
			scanf("%29s",preferiti[i].titolo);
			scanf("%29s",preferiti[i].autore);
			scanf("%d",&preferiti[i].anno);
			scanf("%f",&preferiti[i].prezzo);
			do
			{
				if(strcmp(preferiti[i].titolo,lista[j].titolo)==0 && strcmp(preferiti[i].autore,lista[j].autore)==0 && preferiti[i].anno==lista[j].anno && preferiti[i].prezzo==lista[j].prezzo)
				{
					trovato=1;
				}
				j++;
			}while(j<DIMlista && trovato==0);
			if(trovato==0)
				printf("\a");
		}while(trovato==0);
	}
}
procedura che ordina alfabeticamente in base al titolo del brano la playlist

void ordinaPlaylist(struct brani preferiti[])
{
	struct brani temp;
	int i,j;
	for(i=0;i<DIMplaylist;i++)
	{
		for(j=0;j<DIMplaylist-i-1;j++)
		{
			if(strcmp(preferiti[j].titolo,preferiti[j+1].titolo)>0)
			{
				temp=preferiti[j];
				preferiti[j]=preferiti[j+1];
				preferiti[j+1]=temp;
			}
		}
	}
}
funzione che calcola e stampa il costo dei brani presenti nella playlist.
Il codice funziona correttamente, ma chiedo a chi è più esperto se dal punto di vista didattico, per ordinare alfabeticamente i brani, il metodo utilizzato sia il più consono o sia meglio lavorare attraverso dei puntatori a struttura?
NB: Ho scelto di ordinare con il bubble sort anche se sono consapevole che esistano metodi più efficienti.

6 Risposte

  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    Una prima valutazione andrebbe fatta riguardo al tipo di contenitore (array, lista, ...) più adatto a contenere i dati in questione. Tale scelta dovrebbe tenere in conto di vari fattori. Non è detto inoltre che database principale e playlist personale debbano utilizzare lo stesso tipo di contenitore.
    Il codice funziona correttamente, ma chiedo a chi è più esperto se dal punto di vista didattico, per ordinare alfabeticamente i brani, il metodo utilizzato sia il più consono o sia meglio lavorare attraverso dei puntatori a struttura?
    Nel momento in cui il database principale risulta "consultabile", ovviamente lavorare con puntatori alla struct risulta molto più efficiente da diversi punti di vista.
  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    Per quanto riguarda il tipo di contenitore, ho utilizzato le struct avendo dei tipi di dato misto e volendo gestirli come un blocco unico nelle fasi successive. Considera che sono alle prime armi e sto sperimentando tutte le possibili soluzioni per capire effettivamente come gestirle.
    Dopo aver caricato i dati sul database principale, sarò sincero, ho avuto grosse difficoltà nel riuscire ad effettuare l'ordinamento sui singoli campi, e nel caso specifico, dopo aver consultato varie fonti sul web, ho capito di poter gestire l'intera struct come un dato omogeneo effettuando l'ordinamento per tutti i campi in maniera abbastanza elementare
    
    if(strcmp(preferiti[j].titolo,preferiti[j+1].titolo)>0)
    			{
    				temp=preferiti[j];
    				preferiti[j]=preferiti[j+1];
    				preferiti[j+1]=temp;
    			}
    
    In questo caso risulta tutto funzionante visto che il blocco di informazioni viene sempre trattato insieme: che stampi, crei playlist, ho sempre bisogno di tutti i campi. Mentre se, per fare dei test, volessi ordinare una lista solo attraverso i campi stringa (autore e titolo), la cosa si complicherebbe.
    Naturalmente potrei utilizzare le stesse procedure e semplicemente stampare una playlist con meno campi, ma aggirerei solamente il problema.
    Visto che è un esercizio a scopo didattico, vorrei provare ad utilizzare i puntatori alla struct per ottimizzare il processo, dovendo però così scambiare ogni singolo campo. E' corretto? Dovrei beneficiarne in velocità di esecuzione, giusto?
  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    Non sono sicuro di aver compreso appieno quale sia il problema, in ogni caso... ipotizziamo che il database principale sia un array di brani ordinati secondo la data di inserimento; a questo punto la singola playlist può essere costituita da un array di puntatori alla struct che può essere ordinato in base al generico campo (anno, titolo, costo...).
  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    Nippolo ha scritto:


    Non sono sicuro di aver compreso appieno quale sia il problema, in ogni caso... ipotizziamo che il database principale sia un array di brani ordinati secondo la data di inserimento; a questo punto la singola playlist può essere costituita da un array di puntatori alla struct che può essere ordinato in base al generico campo (anno, titolo, costo...).
    E' solo un problema di comprensione: la soluzione adottata può essere migliorata con l'utilizzo dei puntatori, o risulta già ottimizzata? L'utilizzo di array di struct mi permette di avere una soluzione dove l'ordinamento viene effettuato già per indirizzo. Ma ho il dubbio che la soluzione adottata sia piuttosto elementare. Posto il codice completo per far comprendere meglio
    
    #include<stdio.h>
    #include<string.h>
    
    #define DIMlista 3
    #define DIMplaylist 2
    
    struct brani
    {
    	char titolo[30];
    	char autore[30];
    	int anno;
    	float prezzo;
    };
    
    void Caricamento(struct brani lista[]);
    void stampaElenco(struct brani lista[]);
    void creaPlaylist(struct brani lista[],struct brani preferiti[]);
    void ordinaPlaylist(struct brani preferiti[]);
    void stampaPlaylist(struct brani preferiti[]);
    float costoPlaylist(struct brani preferiti[]);
    
    
    
    int main(){
    	struct brani elencoBrani[10], playlist[3];
    	float tot=0;
    	int scelta;
    	Caricamento(elencoBrani);
    	do
    	{
    		do
    		{
    			printf("\nMenu':\n");
    			printf("1-Stampa elenco\t\t2-Creazione playlist\t3-Ordinamento playlist\n4-Stampa playlist\t5-Costo playlist\t6-Uscita\n");
    			scanf("%d",&scelta);
    			if(scelta<0||scelta>6)
    			{
    				printf("Scelta errata: premere un tasto compreso tra 1 e 6\n");
    			}
    		}while(scelta<0||scelta>6);
    		
    		switch(scelta)
    		{
    			case 1:
    				stampaElenco(elencoBrani);
    				break;
    			case 2:
    				creaPlaylist(elencoBrani,playlist);
    				break;
    			case 3:
    				ordinaPlaylist(playlist);
    				break;
    			case 4:
    				stampaPlaylist(playlist);
    				break;
    			case 5:
    				tot=costoPlaylist(playlist);
    				
    				printf("Il costo totale della playlist e': %.2f euro",tot);
    				break;
    			case 6:
    				printf("\nGrazie per aver utilizzato l'applicazione\n");
    				break;
    			default:
    				printf("\nScelta errata");
    				break;
    		}
    	}while(scelta!=6);
    	
    	getch();
    	return 0;
    }
    
    void Caricamento(struct brani lista[])
    {
    	int i;
    	
    	for(i=0;i<DIMlista;i++)
    	{
    		printf("Inserire i dati relativi al %do brano in elenco: ",i+1);
    		printf("\nTitolo, Autore, Anno di uscita, Prezzo\n");
    		scanf("%29s",lista[i].titolo);
    		scanf("%29s",lista[i].autore);
    		scanf("%d",&lista[i].anno);
    		scanf("%f",&lista[i].prezzo);
    	}
    }
    
    void stampaElenco(struct brani lista[])
    {
    	int i;
    	
    	for(i=0;i<DIMlista;i++)
    	{
    		printf("Brano %d\n",i+1);
    		printf("  Titolo: %s\t",lista[i].titolo);
    		printf("Autore: %s\n",lista[i].autore);
    		printf("  Anno: %d\t",lista[i].anno);
    		printf("Prezzo: %.2f euro\n",lista[i].prezzo);
    	}
    }
    
    void creaPlaylist(struct brani lista[],struct brani preferiti[])
    {
    	int i,j,trovato;
    	
    	for(i=0;i<DIMplaylist;i++)
    	{
    		trovato=0;
    		do
    		{
    			j=0;
    			printf("Inserire i dati relativi al %do brano della playlist: ",i+1);
    			printf("\nTitolo, Autore, Anno di uscita, Prezzo\n");
    			scanf("%29s",preferiti[i].titolo);
    			scanf("%29s",preferiti[i].autore);
    			scanf("%d",&preferiti[i].anno);
    			scanf("%f",&preferiti[i].prezzo);
    			do
    			{
    				if(strcmp(preferiti[i].titolo,lista[j].titolo)==0 && strcmp(preferiti[i].autore,lista[j].autore)==0 && preferiti[i].anno==lista[j].anno && preferiti[i].prezzo==lista[j].prezzo)
    				{
    					trovato=1;
    				}
    				j++;
    			}while(j<DIMlista && trovato==0);
    			if(trovato==0)
    				printf("\a");
    		}while(trovato==0);
    	}
    }
    
    void ordinaPlaylist(struct brani preferiti[])
    {
    	struct brani temp;
    	int i,j;
    	for(i=0;i<DIMplaylist;i++)
    	{
    		for(j=0;j<DIMplaylist-i-1;j++)
    		{
    			if(strcmp(preferiti[j].titolo,preferiti[j+1].titolo)>0)
    			{
    				temp=preferiti[j];
    				preferiti[j]=preferiti[j+1];
    				preferiti[j+1]=temp;
    			}
    			else if(strcmp(preferiti[j].titolo,preferiti[j+1].titolo)==0 && strcmp(preferiti[j].autore,preferiti[j+1].autore)>0)
    				{
    					temp=preferiti[j];
    					preferiti[j]=preferiti[j+1];
    					preferiti[j+1]=temp;
    				}
    		}
    	}
    }
    
    void stampaPlaylist(struct brani preferiti[])
    {
    	int i;
    	for(i=0;i<DIMplaylist;i++)
    	{
    		printf("Brano %d\n",i+1);
    		printf("  Titolo: %s\t",preferiti[i].titolo);
    		printf("Autore: %s\n",preferiti[i].autore);
    		printf("  Anno: %d\t",preferiti[i].anno);
    		printf("Prezzo: %.2f euro\n",preferiti[i].prezzo);
    	}
    }
    
    
    float costoPlaylist(struct brani preferiti[])
    {
    	int i;
    	float totale=0;
    	for(i=0;i<DIMplaylist;i++)
    	{
    		totale=totale+preferiti[i].prezzo;
    	}
    	return totale;
    }
    
  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    E' solo un problema di comprensione: la soluzione adottata può essere migliorata con l'utilizzo dei puntatori, o risulta già ottimizzata?
    Credo di averti già risposto, in ogni caso cerco di essere più chiaro:
    - se hai già un array di brani (quello che nel main tu chiami elencoBrani), a che pro creare tanti duplicati dei brani da inserire nelle varie playlist?! E' solo uno spreco inutile di memoria;
    - nel momento in cui vai ad ordinare, una cosa è scambiare degli indirizzi di memoria, un'altra è copiare l'intera struct più e più volte!

    Quindi sì, utilizzare per le playlist degli array di puntatori alla struct risulta più efficiente.
  • Re: [C] Ordinamento di una struct, è la soluzione adatta?

    Nippolo ha scritto:


    E' solo un problema di comprensione: la soluzione adottata può essere migliorata con l'utilizzo dei puntatori, o risulta già ottimizzata?
    Credo di averti già risposto, in ogni caso cerco di essere più chiaro:
    - se hai già un array di brani (quello che nel main tu chiami elencoBrani), a che pro creare tanti duplicati dei brani da inserire nelle varie playlist?! E' solo uno spreco inutile di memoria;
    - nel momento in cui vai ad ordinare, una cosa è scambiare degli indirizzi di memoria, un'altra è copiare l'intera struct più e più volte!

    Quindi sì, utilizzare per le playlist degli array di puntatori alla struct risulta più efficiente.
    grazie per i chiarimenti! provo a migliorarlo in questa direzione
Devi accedere o registrarti per scrivere nel forum
6 risposte