PDA

View Full Version : [C] è decente come soluzione?!?!


D4rkAng3l
28-05-2005, 16:31
Ciao....altro esercizio per l'esame di programmazione 1...questa volta non ho guardato la soluzione del proff e l'ho risolto a modo mio (diverso da come l'ha fatto lui...) dite che può andare?è decente come soluzione o fà schifo?

L'esercizio dice:

Scrivere una funzione con prototipo int *extract(List *pL, int *nE) che elimini dalla lista *pL gli elementi x per i quali esiste un elemento successivo y tale y.cod > x.cod, alloca dinamicamente un vettore che contiene i valori dei campi cod degli elementi eliminati, restituisce in *pL il puntatore al primo elemento della lista modificata, in *nE il numero degli elementi eliminati e ritorna il vettore.

Se non ci sono elementi eliminati la funzione ritorna NULL. Si assume che i valori dei campi cod siano tutti distinti

Esempio: se la lista è 5->12->7->10->9 viene modificata in: 5->7->9, il vettore creato è [12, 10] e in *nE è restituito 2.

Mia Soluzione:


/* La funzione extract() riceve il puntatore al primo nodo della lista e il
puntatore alla variabile nE dove andare ad inserire il numero degli elementi
eliminati e ritorna l'indirizzo del vettore di interi */

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

typedef struct Elem{
int cod;
struct Elem *next;
} Elem, *List;

int *extract(List *pL, int *nE){

List L; // Dichiaro il puntatore al nodo corrente
List succ; // Dichiaro il puntatore al nodo successivo
int dimvet; // Numero di elementi che compongono il vettore
int *vett=NULL; // Puntatore alla prima locazione del vettore di interi
int val1; // Contiene il valore del campo cod del nodo puntato da L
int val2; // Contiene il valore del campo cod del nodo puntato da suc
int contatore = 0; // Indice di scorrimento del vettore

L = pL; // Setta L al primo nodo della lista
succ = L->next; // Setta suc al nodo successivo ad L

/* Ciclo che calcola quanti elementi vanno eliminati dalla lista e quante
locazioni dovranno essere allocate per il vettore di interi vet */

while(succ != NULL){

val1 = L->cod;
val2 = succ->cod;

if(Less(val1, val2) == 1){ // Se la funzione Less restituisce 1
dimvet++; // incrementa dimvet
}

L = L->next; // Aggiorna L e fallo puntare al prossimo nodo
succ = succ->next; // Aggiorna succ e fallo puntare al prossimo nodo
*nE = dimvet;
}

vett = calloc(dimvet, sizeof(int)); // Alloca un vettore di dimevet interi

L = pL; // Reimposta nuovamente il puntatore L al primo nodo della lista
succ = L->next; // Reimposta suc al nodo successivo a L

/* Ciclo che salva i valori da eliminare nel vettore ed elimina i nodi */

while(succ != NULL){

val1 = L->cod;
val2 = succ->cod;

if(Less(val1, val2) == 1){ // Se la funzione Less restituisce 1

/* Imposta il valore del campo next puntato da L con il valore
del campo next del nodo puntato da succ */
L->next = succ->next;

/* Copia il valore del campo cod del nodo puntato da suc nel
vettore di interi alla posizione indicizzata da contatore */
vett[contatore] = succ->cod;

contatore++; // Incrementa il contatore

free(succ); // Elimina il nodo puntato da succ
}

L = pL; // Reimposta nuovamente il puntatore L al primo nodo
succ = L->next; // Reimposta suc al nodo successivo a L
}

return(vett); // Ritorna il puntatore alla prima locazione del vettore
}

/* La funzione Less() riceve il valore del campo cod del nodo corrente e il
valore del campo cod del nodo successivo, se il valore corrente < del valore
successivo restituisce 1, 0 altrimenti */

short Less(int val, int valsucc){

if(valsucc > val)
return 1;
else
return 0;
}

sirus
28-05-2005, 18:04
la soluzione non l'ho ancora guardata però mi chiedevo...sono questi gli esercizi che fanno fare all'uni :mbe: sono esattamente come quelli che si fanno alle superiori, immaginavo qualche programma più impegnativo :rolleyes:
ps ora do una occhiata al programma :read:

sirus
28-05-2005, 18:06
Ciao....altro esercizio per l'esame di programmazione 1...questa volta non ho guardato la soluzione del proff e l'ho risolto a modo mio (diverso da come l'ha fatto lui...) dite che può andare?è decente come soluzione o fà schifo?

L'esercizio dice:

Scrivere una funzione con prototipo int *extract(List *pL, int *nE) che elimini dalla lista *pL gli elementi x per i quali esiste un elemento successivo y tale y.cod > x.cod, alloca dinamicamente un vettore che contiene i valori dei campi cod degli elementi eliminati, restituisce in *pL il puntatore al primo elemento della lista modificata, in *nE il numero degli elementi eliminati e ritorna il vettore.

Se non ci sono elementi eliminati la funzione ritorna NULL. Si assume che i valori dei campi cod siano tutti distinti

Esempio: se la lista è 5->12->7->10->9 viene modificata in: 5->7->9, il vettore creato è [12, 10] e in *nE è restituito 2.

Mia Soluzione:


/* La funzione extract() riceve il puntatore al primo nodo della lista e il
puntatore alla variabile nE dove andare ad inserire il numero degli elementi
eliminati e ritorna l'indirizzo del vettore di interi */

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

typedef struct Elem{
int cod;
struct Elem *next;
} Elem, *List;

int *extract(List *pL, int *nE){

List L; // Dichiaro il puntatore al nodo corrente
List succ; // Dichiaro il puntatore al nodo successivo
int dimvet; // Numero di elementi che compongono il vettore
int *vett=NULL; // Puntatore alla prima locazione del vettore di interi
int val1; // Contiene il valore del campo cod del nodo puntato da L
int val2; // Contiene il valore del campo cod del nodo puntato da suc
int contatore = 0; // Indice di scorrimento del vettore

L = pL; // Setta L al primo nodo della lista
succ = L->next; // Setta suc al nodo successivo ad L

/* Ciclo che calcola quanti elementi vanno eliminati dalla lista e quante
locazioni dovranno essere allocate per il vettore di interi vet */

while(succ != NULL){

val1 = L->cod;
val2 = succ->cod;

if(Less(val1, val2) == 1){ // Se la funzione Less restituisce 1
dimvet++; // incrementa dimvet
}

L = L->next; // Aggiorna L e fallo puntare al prossimo nodo
succ = succ->next; // Aggiorna succ e fallo puntare al prossimo nodo
*nE = dimvet;
}

vett = calloc(dimvet, sizeof(int)); // Alloca un vettore di dimevet interi

L = pL; // Reimposta nuovamente il puntatore L al primo nodo della lista
succ = L->next; // Reimposta suc al nodo successivo a L

/* Ciclo che salva i valori da eliminare nel vettore ed elimina i nodi */

while(succ != NULL){

val1 = L->cod;
val2 = succ->cod;

if(Less(val1, val2) == 1){ // Se la funzione Less restituisce 1

/* Imposta il valore del campo next puntato da L con il valore
del campo next del nodo puntato da succ */
L->next = succ->next;

/* Copia il valore del campo cod del nodo puntato da suc nel
vettore di interi alla posizione indicizzata da contatore */
vett[contatore] = succ->cod;

contatore++; // Incrementa il contatore

free(succ); // Elimina il nodo puntato da succ
}

L = pL; // Reimposta nuovamente il puntatore L al primo nodo
succ = L->next; // Reimposta suc al nodo successivo a L
}

return(vett); // Ritorna il puntatore alla prima locazione del vettore
}

/* La funzione Less() riceve il valore del campo cod del nodo corrente e il
valore del campo cod del nodo successivo, se il valore corrente < del valore
successivo restituisce 1, 0 altrimenti */

short Less(int val, int valsucc){

if(valsucc > val)
return 1;
else
return 0;
}

scusa ma usi il tipo List che non hai mai definito, e poi la soluzione mi sembra un po' un accrocchio :( è piuttosto contorta :muro:

71104
28-05-2005, 18:14
non ho ancora letto il codice, ma ti faccio notare che l'esempio è sbagliato: in teoria dovresti eliminare gli x che hanno un successore y strettamente maggiore, quindi se hai

5->12->7->10->9

la lista originale deve diventare

12->10->9

perché vanno eliminati il 5 e il 7. l'esempio della traccia l'ha scritta sempre il solito prof., vero? si riconosce lo stile...

PS x sirus: be', lui è solo al primo anno e quindi è ancora tutto molto semplice, ma concordo con te che cmq all'università si dovrebbe fare molto di più... e penso anche che bisognerebbe piantarla con questa stupida moda di Linux immotivata (o motivata solo da ragioni economiche peraltro nemmeno tanto valide): casomai se proprio proprio, bisognerebbe essere "equi" e dare un'istruzione sia in ambito Linux che in ambito Windows.

71104
28-05-2005, 18:15
scusa ma usi il tipo List che non hai mai definito [...]
si che l'ha definito

sirus
28-05-2005, 18:18
si che l'ha definito
e dove??? :mbe:

71104
28-05-2005, 18:20
e dove??? :mbe:
all'undicesima riga

sirus
28-05-2005, 18:23
all'undicesima riga
a già... c'è il typedef davanti, non avevo visto :sofico: chiedo venia :mc:

sirus
28-05-2005, 18:26
imho sarebbe meglio evitare i due cicli e fare tutto in uno ;) ogni volta (se necessario) estendi l'array e via... :)

D4rkAng3l
28-05-2005, 18:49
mmm me ne sono accorto...che dire...quello è un altro errore del proff !!! aveva scitto male le specifiche :mc: :mc: :mc: cmq la lista deve essere come quella dell'esempio...e mi pare che il mio lo faccia...

io avevo pensato di usare la realloc per riallocare lo spazio dell'array di volta in volta che si aggiungeva un elemento...si può fare?

Grazie cmq :-)

sirus
28-05-2005, 18:58
mmm me ne sono accorto...che dire...quello è un altro errore del proff !!! aveva scitto male le specifiche :mc: :mc: :mc: cmq la lista deve essere come quella dell'esempio...e mi pare che il mio lo faccia...

io avevo pensato di usare la realloc per riallocare lo spazio dell'array di volta in volta che si aggiungeva un elemento...si può fare?

Grazie cmq :-)
si...
e poi non dichiarare così tante variabili...usa una sintassi più stringata ;) è più bello :D tipo

...
val1 = L->cod;
val2 = succ->cod;

if(Less(val1, val2) == 1){ // Se la funzione Less restituisce 1
dimvet++; // incrementa dimvet
}
...

lo cambi in

if(!Less(L->cod,succ->cod))
dimvet++;

è più C :sofico:

71104
28-05-2005, 19:07
evitiamo tanti giri di parole: non è che è più C, semplicemente è più facile, più leggibile e quindi più manutenibile ;)
non è colpa nostra se quel sedicente professore non spiega agli alunni che tra parentesi nelle chiamate di funzioni ci stanno espressioni, non variabili.

sirus
28-05-2005, 19:08
evitiamo tanti giri di parole: non è che è più C, semplicemente è più facile, più leggibile e quindi più manutenibile ;)
non è colpa nostra se quel sedicente professore non spiega agli alunni che tra parentesi nelle chiamate di funzioni ci stanno espressioni, non variabili.
è anche più bello, lo stile è importante :D come una buona indentazione :sofico:

71104
28-05-2005, 19:21
è anche più bello, lo stile è importante :D come una buona indentazione :sofico:
così stai parlando di leggibilità ;)

sirus
29-05-2005, 09:12
così stai parlando di leggibilità ;)
già...ogni tanto vedo i programmi dei miei compagni (quando mi chiedono di aiutarli) e la prima cosa che faccio è indentarli e magari cambiare qualche cosetta tipo quella che ho detto prima... :muro: altrimenti è una cosa impossibile...
riescono ad indentare male anche con visual c++ che fa tutto lui :mbe:

71104
29-05-2005, 12:20
già...ogni tanto vedo i programmi dei miei compagni (quando mi chiedono di aiutarli) e la prima cosa che faccio è indentarli e magari cambiare qualche cosetta tipo quella che ho detto prima... :muro: altrimenti è una cosa impossibile...
riescono ad indentare male anche con visual c++ che fa tutto lui :mbe:
LOL in effetti che ne vuole :D