[C] Ordinamento lista

di il
16 risposte

[C] Ordinamento lista

Come suggerito da oregon ho creato un nuovo thread.

Ciao ragazzi, come immaginavo sto trovando difficoltà nel creare la funzione per ordinare la lista.

Spiego meglio ciò che devo fare:
-Stampare a monitor l'elenco ordinato dei dati sulla base di una delle 4 chiavi, a scelta dell'utente.

Tenendo conto che la lista ha questo aspetto:
Barolo 19E2 2011 Asti
Chianti 48K1 2009 Siena
Amarone 68A5 2010 Verona
Gravner 39U4 2006 Udine
Valentini 57L3 2012 Chieti
dove le chiavi sono chiaramente: nome_vino, id_bottiglia, anno_produzione, luogo_imbottigliamento.

Per adesso ho creato questa parte nella funzione main:
if ((operazione == 4) && (file_caricato != 0))
		{
			/*Acquisisco la chiave scelta dall'utente */
			printf("Digitare la chiave secondo la quale si desidera ordinare gli elementi:\n");
			printf("(Scelte disponibili: nome, id, anno, luogo)\n");
			scanf("%s",
				scelta);

			/* Uso uno switch per suddividere i casi di ordinamento */
			switch(scelta)
			{
				case 'nome':
				ordinamento();
				break;

				case 'id':
				ordinamento();
				break;
				
				case 'anno':
				ordinamento();
				break;
				
				case 'luogo':
				ordinamento();
				break;
			}

			/* Chiedo se l'utente vuole compiere altre operazioni */			
			printf("\n\nEseguire ulteriori operazioni? Digitare '1' in caso affermativo, '2' in caso negativo\n");
			scanf("%d",
				&esegui_altre_operazioni);
		}
Mancano ancora i dati da passare in input alla funzione per ordinare, ma immagino siano *testa_p (puntatore alla testa della lista) e una delle chiavi a seconda di quale case si verifica.

Detto questo, non ho veramente idea su come implementare questa funzione e qualunque tipo di aiuto è ben accetto.
Mentre attendo risposte sarò comunque qua a ragionarci su.
Grazie in anticipo.

EDIT: ne approfitto per aggiungere la typedef della lista che magari potrebbe servirvi (?)
/* Definizione della struttura dati */
typedef struct lista
{
	char nome_vino[DIM_NOME+1];
	char id_bott[DIM_ID+1];
	char anno_prod[DIM_ANNO+1];
	char luogo_imb[DIM_LUOGO+1];
	struct lista *succ_p;
}lista_t;

16 Risposte

  • Re: [C] Ordinamento lista

    Questa funzione è più intricata di quello che pensavo.
  • Re: [C] Ordinamento lista

    Guarda la prima risposta di Qu@ker in

    http://www.hwupgrade.it/forum/showthread.php?t=112312
  • Re: [C] Ordinamento lista

    Ho letto e ora sto ragionando sul codice scritto da Qu@ker
    lista *ordina(lista *pointer)
    {
    	if (pointer && pointer->prox) {
    		int k;
    
    		do {
                            lista *punt = pointer;
    
    			k = 0;
    			while (punt->prox) {
    				lista *punt1 = punt;
    
    				punt = punt->prox;
    				if ((punt1->elem) > (punt->elem)) {
    					int tmp = punt1->elem;
    
    					punt1->elem = punt->elem;
    					punt->elem = tmp;
    					k = 1;
    				}
    			}
    		} while (k != 0);
    	}
    
    	return pointer;
    }
    Ciò che mi manda in confusione è, più che altro, il fatto che ogni mio elemento della lista ha all'interno 4 stringhe.
    Immagino di dover utilizzare strcpy per effettuare gli scambi, giusto?
  • Re: [C] Ordinamento lista

    Sì, usa delle strcpy.
  • Re: [C] Ordinamento lista

    Non ti seguo.
    Riesci a farmi un esempio?
    Grazie mille per le risposte oregon.

    EDIT: ah ok. avevo letto il tuo messaggio prima dell'edit
  • Re: [C] Ordinamento lista

    Quindi se ho capito bene, questo If
    if ((punt1->elem) > (punt->elem)) 
    {
    		int tmp = punt1->elem;
    
    		punt1->elem = punt->elem;
    		punt->elem = tmp;
    		k = 1;
    }
    devo riadattarlo in questo modo:
    if (strcmp(punt1->nome_vino, punt->nome_vino) == 1)
    {
            char tmp[DIM_NOME]; 
            strcpy(tmp[DIM_NOME], punt1->nome_vino);
    
            strcpy(punt1->nome_vino, punt->nome_vino);
            strcpy(punt->nome_vino, tmp[DIM_NOME];
            k=1;
    }
  • Re: [C] Ordinamento lista

    La strcmp non restituisce 1 ma un valore "maggiore di zero", "minore di zero" o "zero".

    E attenzione ... l'esempio è per una lista in cui esiste un solo dato (elem).

    Qui tu non hai solo un dato ma 4 dati ... devi scambiarli tutti altrimenti mischi i vini (e non è bello ...).
  • Re: [C] Ordinamento lista

    Capito, quindi immagino io debba usare > 0 nella strcmp.
    Per quanto riguarda l'altro errore, ora scambio anche tutti gli altri dati, grazie.
  • Re: [C] Ordinamento lista

    Ecco qua, questo sarebbe il case '1' dello switch(scelta). Ovvero quando l'utente vuole ordinare in base alla chiave nome_vino:
    void ordinamento(lista_t *testa_p)
    {
    	if (testa_p && testa_p->succ_p)
    	{
    		int k;
    
    		do 
    		{
                            lista_t *elem_p = testa_p;
    
    			k = 0;
    			while (elem_p->succ_p) 
    			{
    				lista_t *elem_p1 = elem_p;
    
    				elem_p = elem_p->succ_p;
    
    				if (strcmp(elem_p1->nome_vino, elem_p->nome_vino) > 0)
    				{
            				char tmp_nome[DIM_NOME]; 
    					char tmp_id[DIM_ID];
    					char tmp_anno[DIM_ANNO];
    					char tmp_luogo[DIM_LUOGO];
    
            				strcpy(tmp_nome, elem_p1->nome_vino);
    				        strcpy(elem_p1->nome_vino, elem_p->nome_vino);
            				strcpy(elem_p->nome_vino, tmp_nome);
    
    					strcpy(tmp_id, elem_p1->id_bott);
    					strcpy(elem_p1->id_bott, elem_p->id_bott);
    					strcpy(elem_p->id_bott, tmp_id);
    
    					strcpy(tmp_anno, elem_p1->anno_prod);
    					strcpy(elem_p1->anno_prod, elem_p->anno_prod);
    					strcpy(elem_p->anno_prod, tmp_anno);
    
    					strcpy(tmp_luogo, elem_p1->luogo_imb);
    					strcpy(elem_p1->luogo_imb, elem_p->luogo_imb);
    					strcpy(elem_p->luogo_imb, tmp_luogo);					
    
            				k = 1;
    				}
    			}
    		} while (k != 0);
    	}
    }
    
    Corretto?
    Invece per implementare gli altri casi mi basta passare 'scelta' in input alla funzione e poi fare un
    If (scelta == 1) ...
    If (strcmp...) /* Chiave: nome vino */
    faccio gli scambi...
    if (scelta == 2) ...
    if (strcmp...) /* Chiave: id bottiglia */
    faccio gli scambi...
    etc.
    giusto?
  • Re: [C] Ordinamento lista

    Non ho provato se è corretto. Tu hai provato il codice? Funziona?
  • Re: [C] Ordinamento lista

    Il compilatore non mi da alcun errore, ne warning, però non so ancora se funziona.
    Adesso ti posto la funzione completa:
    /* Definizione funzione di ordinamento */
    
    void ordinamento(lista_t *testa_p,
    			int scelta)
    {
    	if (testa_p && testa_p->succ_p)
    	{
    		int k;
    
    		do 
    		{
                            lista_t *elem_p = testa_p;
    
    			k = 0;
    			while (elem_p->succ_p) 
    			{
    				lista_t *elem_p1 = elem_p;
    
    				elem_p = elem_p->succ_p;
    	
    				if (scelta == 1)
    				{
    					if (strcmp(elem_p1->nome_vino, elem_p->nome_vino) > 0)
    					{
            					char tmp_nome[DIM_NOME]; 
    						char tmp_id[DIM_ID];
    						char tmp_anno[DIM_ANNO];
    						char tmp_luogo[DIM_LUOGO];
    	
            					strcpy(tmp_nome, elem_p1->nome_vino);
    					        strcpy(elem_p1->nome_vino, elem_p->nome_vino);
            					strcpy(elem_p->nome_vino, tmp_nome);
    	
    						strcpy(tmp_id, elem_p1->id_bott);
    						strcpy(elem_p1->id_bott, elem_p->id_bott);
    						strcpy(elem_p->id_bott, tmp_id);
    
    						strcpy(tmp_anno, elem_p1->anno_prod);
    						strcpy(elem_p1->anno_prod, elem_p->anno_prod);
    						strcpy(elem_p->anno_prod, tmp_anno);
    
    						strcpy(tmp_luogo, elem_p1->luogo_imb);
    						strcpy(elem_p1->luogo_imb, elem_p->luogo_imb);
    						strcpy(elem_p->luogo_imb, tmp_luogo);					
    
            					k = 1;
    					}
    				}
    				else if (scelta == 2)
    				{
    					if (strcmp(elem_p1->id_bott, elem_p->id_bott) > 0)
    					{
            					char tmp_nome[DIM_NOME]; 
    						char tmp_id[DIM_ID];
    						char tmp_anno[DIM_ANNO];
    						char tmp_luogo[DIM_LUOGO];
    	
            					strcpy(tmp_nome, elem_p1->nome_vino);
    					        strcpy(elem_p1->nome_vino, elem_p->nome_vino);
            					strcpy(elem_p->nome_vino, tmp_nome);
    	
    						strcpy(tmp_id, elem_p1->id_bott);
    						strcpy(elem_p1->id_bott, elem_p->id_bott);
    						strcpy(elem_p->id_bott, tmp_id);
    
    						strcpy(tmp_anno, elem_p1->anno_prod);
    						strcpy(elem_p1->anno_prod, elem_p->anno_prod);
    						strcpy(elem_p->anno_prod, tmp_anno);
    
    						strcpy(tmp_luogo, elem_p1->luogo_imb);
    						strcpy(elem_p1->luogo_imb, elem_p->luogo_imb);
    						strcpy(elem_p->luogo_imb, tmp_luogo);					
    
            					k = 1;
    					}
    
    				}
    				else if (scelta == 3)
    				{
    					if (strcmp(elem_p1->anno_prod, elem_p->anno_prod) > 0)
    					{
            					char tmp_nome[DIM_NOME]; 
    						char tmp_id[DIM_ID];
    						char tmp_anno[DIM_ANNO];
    						char tmp_luogo[DIM_LUOGO];
    	
            					strcpy(tmp_nome, elem_p1->nome_vino);
    					        strcpy(elem_p1->nome_vino, elem_p->nome_vino);
            					strcpy(elem_p->nome_vino, tmp_nome);
    	
    						strcpy(tmp_id, elem_p1->id_bott);
    						strcpy(elem_p1->id_bott, elem_p->id_bott);
    						strcpy(elem_p->id_bott, tmp_id);
    
    						strcpy(tmp_anno, elem_p1->anno_prod);
    						strcpy(elem_p1->anno_prod, elem_p->anno_prod);
    						strcpy(elem_p->anno_prod, tmp_anno);
    
    						strcpy(tmp_luogo, elem_p1->luogo_imb);
    						strcpy(elem_p1->luogo_imb, elem_p->luogo_imb);
    						strcpy(elem_p->luogo_imb, tmp_luogo);					
    
            					k = 1;
    					}
    				}
    				else if (scelta == 4)
    				{
    					if (strcmp(elem_p1->luogo_imb, elem_p->luogo_imb) > 0)
    					{
            					char tmp_nome[DIM_NOME]; 
    						char tmp_id[DIM_ID];
    						char tmp_anno[DIM_ANNO];
    						char tmp_luogo[DIM_LUOGO];
    	
            					strcpy(tmp_nome, elem_p1->nome_vino);
    					        strcpy(elem_p1->nome_vino, elem_p->nome_vino);
            					strcpy(elem_p->nome_vino, tmp_nome);
    	
    						strcpy(tmp_id, elem_p1->id_bott);
    						strcpy(elem_p1->id_bott, elem_p->id_bott);
    						strcpy(elem_p->id_bott, tmp_id);
    
    						strcpy(tmp_anno, elem_p1->anno_prod);
    						strcpy(elem_p1->anno_prod, elem_p->anno_prod);
    						strcpy(elem_p->anno_prod, tmp_anno);
    
    						strcpy(tmp_luogo, elem_p1->luogo_imb);
    						strcpy(elem_p1->luogo_imb, elem_p->luogo_imb);
    						strcpy(elem_p->luogo_imb, tmp_luogo);					
    
            					k = 1;
    					}
    				}
    			}
    		} while (k != 0);
    	}
    }
    
    ^ Eccola qui.
    La invoco dalla main in questo modo:
    		/* Se l'utente sceglie di ordinare i dati secondo una delle chiavi */
    		if ((operazione == 4) && (file_caricato != 0))
    		{
    			/*Acquisisco la chiave scelta dall'utente */
    			printf("Scegliere la chiave secondo la quale si desidera ordinare gli elementi:\n\n");
    			printf("Scelte disponibili:\ndigitare '1' per scegliere la chiave nome;\n"
    						     "digitare '2' per scegliere la chiave id;\n"
    						     "digitare '3' per scegliere la chiave anno;\n"
    					 	     "digitare '4' per scegliere la chiave luogo.\n");
    			scanf("%d",
    				&scelta);
    
    			/* Uso uno switch per suddividere i casi di ordinamento */
    			switch(scelta)
    			{
    				case '1':
    				ordinamento(testa_p,
    						scelta);
    				stampa_lista(testa_p);
    				break;
    
    				case '2':
    				ordinamento(testa_p,
    						scelta);
    				stampa_lista(testa_p);
    				break;
    				
    				case '3':
    				ordinamento(testa_p,
    						scelta);
    				stampa_lista(testa_p);
    				break;
    				
    				case '4':
    				ordinamento(testa_p,
    						scelta);
    				stampa_lista(testa_p);
    				break;
    
    			}
    
    			/* Chiedo se l'utente vuole compiere altre operazioni */			
    			printf("\n\nEseguire ulteriori operazioni? Digitare '1' in caso affermativo, '2' in caso negativo\n");
    			scanf("%d",
    				&esegui_altre_operazioni);
    		}
    
    E questa è la funzione per stampare la lista una volta ordinata:
    /* Definizione della funzione per stampare la lista ordinata */
    void stampa_lista(lista_t *testa_p)
    {
    	lista_t *punt;
    	
    	for (punt = testa_p;
    		(punt != NULL);
    		punt = punt->succ_p)
    		printf("%s %s %s %s\n",
    			punt->nome_vino,
    			punt->id_bott,
    			punt->anno_prod,
    			punt->luogo_imb);
    }
    Purtroppo però non mi stampa nulla, forse c'è qualcosa che non va in quest'ultima funzione.
  • Re: [C] Ordinamento lista

    Qualche idea sul dove possa essere il problema?
  • Re: [C] Ordinamento lista

    E' possibile scaricare tutto il sorgente compilabile ?
  • Re: [C] Ordinamento lista

    Ecco qua, ho effettuato un upload della cartella che contiene tutto ciò che serve:
    sorgente;
    file da cui prendere i dati (txt).

    http://speedy.sh/qHj42/new2.zi
Devi accedere o registrarti per scrivere nel forum
16 risposte