|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
[C] Consigli su creazione lista
Devo creare una lista da una serie di dati statistici prelevati da un secondo programma che sono riuscito a completare.
La mia funzione che crea la lista riceve in ingresso: un risultato (stringa dim variabile da 1 a 30 char) e un id sessione (intero a 3 cifre). Per ogni risultato voglio tenere conto di quante volte viene ricevuto in ogni sessione (sempre intero a 3 cifre) quindi ho scelto di fare una cosa del genere: Codice:
typedef struct nodo
{
struct nodo *next;
char *result;
int (*sessioni)[2];
}
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° Ultima modifica di Andrea16v : 03-09-2007 alle 11:39. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Le operazioni da fare le ho capite (in altri linguaggi non avrei problemi a farlo), però non mi sono chiare proprio alcune operazioni che fai nella funzione append.
Lo riquoto un secondo: Codice:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo
{
int data;
struct nodo *next;
} NODO, *PNODO, **PPNODO;
int List_Append (PPNODO pproot, int data)
{
PNODO pnodo;
if (pproot == NULL)
return 0;
if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
return 0;
pnodo->data = data;
pnodo->next = NULL;
while (*pproot != NULL)
pproot = &(*pproot)->next;
*pproot = pnodo;
return 1;
}
int main (void)
{
PNODO proot = NULL;
List_Append (&proot, 27);
List_Append (&proot, 7);
List_Append (&proot, 87);
return 0;
}
Con il secondo if controlli che ci sia spazio sufficiente (la malloc non restituisca NULL), in caso contrario esci. La mia malloc è molto più complessa avendo un array di lunghezza non fissa? Poi assegni i valori al nuovo nodo (con puntatore next nullo in quanto lo metti in fondo), scorri "ricorsivamente" la struttura sino alla fine e inserisci... grazie mille!
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|
|
|
|
|
#4 | |||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Quote:
Quote:
Quote:
Sì, tra l'altro ho usato il "trucchetto" di usare un puntatore a puntatore, perché in questo modo non devo differenziare tra primo nodo (da assegnare al root) o successivi nodi (da assegnare al next precedente).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|||||
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Penso di aver capito abbastanza: ho provato ad adattarlo ai miei scopi, per ora lasciando ancora da parte le cose difficili, questo è il risultato (che definirei abbastanza penoso..):
Codice:
typedef struct nodo
{
char *result;
int sessione;
struct nodo *next;
} NODO, *PNODO, **PPNODO;
int main() {
PNODO proot = NULL;
list_Append (&proot, "PrimoRisultato", 1);
list_Append (&proot, "SecondoRisultato", 2);
list_Append (&proot, "TerzoRisultato", 2);
list_Append (&proot, "QuartoRisultato", 3);
stampa (&proot);
return 0;
}
int list_Append (PPNODO pproot, char *result, int sessione)
{
PNODO pnodo;
if (pproot == NULL)
return 0;
if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
return 0;
pnodo->result = result;
pnodo->sessione = sessione;
pnodo->next = NULL;
while (*pproot != NULL)
pproot = &(*pproot)->next;
*pproot = pnodo;
return 1;
}
void stampa (PPNODO pproot)
{
if (pproot == NULL)
exit(1);
printf("Risultato: %s\n", (*pproot)->result);
printf("Id sessione: %d\n\n", (*pproot)->sessione);
stampa((*pproot)->next);
}
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Codice:
void stampa (PNODO pnodo)
{
while (pnodo != NULL)
{
printf("Risultato: %s\n", pnodo->result);
printf("Id sessione: %d\n\n", pnodo->sessione);
pnodo = pnodo->next;
}
}
Finché assegni l'indirizzo di stringhe "literal", no problem.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Ho provato a complicare un po' le cose aggiungendo la matrice.
Ad ogni risultato ho associato una matrice di due colonne in cui la prima riporta il numero di sessione e la seconda il numero di volte che il risultato è pervenuto in quella sessione. Dovrei trovare un modo per scorrere la matrice verticalmente sino all'ultima riga, ma ora come ora non mi sono venute idee (salvo inserire nella struct un campo che mi dice il numero di sessioni in cui appare quel risultato). Inoltre c'è sicuramente anche qualche problema di allocazione... Codice:
int list_Append (PPNODO pproot, char *result, int sessione)
{
PNODO pnodo;
int i;
if (pproot == NULL)
return 0;
if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
return 0;
while (*pproot != NULL) {
/*cerco il risultato nella lista dei risultati*/
if((*pproot)->result) == result) {
/*cerco la sessione all'interno del nodo*/
for(i=0;i<???) /*dovrei iterare sino all'ultima riga*/
if( (*pproot)->sessioni[i][0] == sessione){
(*pproot)->sessioni[i][1]++;
return 1;
}
}
/*la sessione non e' presente, la aggiungo*/
(*pproot)->sessioni[i][0] = sessione;
(*pproot)->sessioni[i][1] = 1;
return 1;
}
pproot = &(*pproot)->next;
}
/* il risultato non e' presente, lo aggiungo in coda*/
pnodo->result = result;
pnodo->sessioni[0][0] = sessione;
pnodo->sessioni[0][1] = 1;
pnodo->next = NULL;
*pproot = pnodo;
return 1;
}
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Perché tra l'altro: a) Fare int (*sessioni)[2] vuol dire "un puntatore ad un array di 2 int". Ho il dubbio che probabilmente non è proprio quello che ti serve. b) Nella funzione non assegni un valore a questo puntatore. Fai: pnodo->sessioni[0][0] = sessione; pnodo->sessioni[0][1] = 1; e cioè cerchi di accedere agli elementi nell'array puntato ma pnodo->sessioni non è inizializzato, quindi ... boh. c) Nel while fai dei return 1 ma in caso di tale uscita, hai comunque allocato un NODO che poi non viene usato (memory leak).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) Ultima modifica di andbin : 03-09-2007 alle 13:19. |
|
|
|
|
|
|
#9 | |||
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Quote:
E' valida come idea oppure effettivamente si poteva fare anche con un puntatore ad un array di 2 int? Quote:
La dinamica del tutto è la seguente: ricevo un risultato, controllo se il risultato è già in lista, se non è in lista lo aggiungo in coda, se è già in lista controllo se era già stato ricevuto in quella sessione scorrendo la prima colonna della matrice, in caso positivo aumento il numero di hit di quella sessione e esco, in caso negativo aggiungo una riga alla matrice con il numero sessione e 1 come numero hit. Quote:
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|||
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Codice:
typedef struct
{
int id;
int hit;
} SESSIONE;
Codice:
SESSIONE *sessioni;
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) Ultima modifica di andbin : 03-09-2007 alle 14:42. |
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Ho guardato un po' come verrebbe con l'array di record e cosa dovrei cambiare negli altri moduli del programma e mi viene un bel caos, dovrei rifare una marea di cose che al momento sono faticosamente funzionanti, preferisco insistere sulla strada della matrice.
Codice:
RisultatoA
[2][6]
[4][3]
[7][1]
La dinamica del tutto è la seguente: ricevo un risultato, controllo se il risultato è già in lista, se non è in lista lo aggiungo in coda, se è già in lista controllo se era già stato ricevuto in quella sessione scorrendo la prima colonna della matrice, in caso positivo aumento il numero di hit di quella sessione e esco, in caso negativo aggiungo una riga alla matrice con il numero sessione e 1 come numero hit. Qualche suggerimento su come gestire le malloc nei vari casi? Questo è quando ho prodotto: nsess è stato aggiunto alla struct: indica il numero di sessioni in cui il risultato è presente, e quindi il numero di righe della matrice... Codice:
int list_Append (PPNODO pproot, char *result, int sessione)
{
PNODO pnodo;
int i;
if (pproot == NULL)
return 0;
while (*pproot != NULL) {
if(((*pproot)->result) == result) {
for(i=0;i<(*pproot)->nsess;i++){
if( (*pproot)->sessioni[i][0] == sessione){
(*pproot)->sessioni[i][1]++;
return 1;
}
}
/*la sessione non e' presente, la aggiungo*/
(*pproot)->sessioni[i][0] = sessione;
(*pproot)->sessioni[i][1] = 1;
(*pproot)->nsess++;
return 1;
}
pproot = &(*pproot)->next;
}
/* il risultato non e' presente, lo aggiungo in coda*/
if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
return 0;
pnodo->result = result;
pnodo->sessioni[0][0] = sessione;
pnodo->sessioni[0][1] = 1;
pnodo->next = NULL;
pnodo->nsess = 1;
*pproot = pnodo;
return 1;
}
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° Ultima modifica di Andrea16v : 03-09-2007 alle 16:50. |
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Un esempio banale: Codice:
int (*sessioni)[2]; int arr[2]; sessioni = &arr; Ma posso pure allocare dinamicamente la memoria per i due int: Codice:
int (*sessioni)[2]; sessioni = (int(*)[2]) malloc (2 * sizeof (int)); Codice:
sessioni = (int(*)[2]) malloc (2 * 10 * sizeof (int)); sessioni[0][0] = .... sessioni[0][1] = .... .... sessioni[9][0] = .... sessioni[9][1] = ....
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jul 2006
Messaggi: 1568
|
Mi intrometto nella discussione chiedendo 2 cose;
Questi due modi sono equivalenti vero? Codice:
int (*sessioni)[2]; int arr[2]; Codice:
&(*pproot); pproot; Ultima modifica di nico88desmo : 03-09-2007 alle 22:20. |
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
In questo caso sì, sono equivalenti (sebbene il primo sia un po' "stupido").
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
...vedi post sotto!
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° Ultima modifica di Andrea16v : 10-09-2007 alle 00:43. |
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Quote:
Comunque ancora un paio di cose non mi tornano: la mia struttura è fatta così: typedef struct nodo { struct nodo *next; char *result; int (*sessioni)[2]; int pippo; //aggiunto per esempio int pluto[4]; //aggiunto per esempio } Quando chiamo la malloc con il parametro sizeof (NODO) quanto spazio viene allocato per la struttura sopra? Esempio: se voglio scrivere qualcosa nel campo nodo->result potrei farlo senza richiamare la malloc (ho un esempio però che non funziona!), mentre se voglio scrivere in sessioni[..] non posso in quanto sessioni è un puntatore e la malloc precedente non ha allocato spazio per i puntatori definiti nella struct.. pluto[0] dovrebbe essere "disponibile" senza ulteriori malloc però se volessi espandere l'array a 6 posizioni potrei chiamare realloc(&pluto, 6*sizeof(int)) Vorrei insomma capire con che criterio viene allocato lo spazio con la chiamata sizeof(NODO)
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|
|
|
|
|
|
#17 | |||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Prendiamo la tua struttura originale: Codice:
typedef struct nodo
{
struct nodo *next;
char *result;
int (*sessioni)[2];
}
Quote:
La questione quindi è: chi deve gestire la memoria di quella stringa, in pratica chi deve essere "responsabile" della gestione dell'area di memoria puntata da result. Se nella funzione di Append fai una cosa come: pnodo->result = result; vuol dire semplicemente che la funzione non sa nulla di come è stata gestita l'allocazione della stringa e si limita solo a copiare l'indirizzo. Quindi sei tu che dovrai preoccuparti all'esterno di allocare/deallocare (eventualmente) la memoria. Quote:
Per come hai dichiarato pluto, cioè int pluto[4];, non puoi ridimensionarlo in alcun modo. Quello è un array di dimensione fissa. Nella struttura ci saranno quindi già 4*sizeof(int) byte allocati per questa variabile. E l'indirizzo di questo array è anche fisso. Per dirla in altri termini, l'epressione 'pluto' non può essere un l-value, cioè non puoi fare ad esempio: pluto = realloc........
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|||
|
|
|
|
|
#18 | |||
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Quote:
Quote:
Quote:
Nel caso avessi dichiarato quindi sessioni come array di 2 int e non puntatore a, non avrei potuto aumentarlo dinamicamente a seconda delle esigenze. Ultima cosa: tutte le volte che chiamo la malloc() è necessario testarne il valore di ritorno? Nel mio caso ho 3 chiamate: una sul sizeof(NODO), la seconda per la stringa e la terza per la matrice/array, quindi mi ritroverei un codice un po' incasinato..
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|||
|
|
|
|
|
#19 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Se ad esempio la malloc del NODO e ok ma poi la malloc per sessioni fallisce, beh, basta che fai il free di ciò che hai allocato prima e ritorni NULL.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Mar 2003
Messaggi: 3852
|
Ho fatto ancora delle prove sulla realloc, il frammento seguente mi funziona, ma è giusto dal punto di visto logico? Se ho capito bene il programma potrebbe funzionare anche eliminando la chiamata alla malloc(), però lo spazio non verrebbe riservato, quindi ulteriori operazioni potrebbero andare ad alterare il contenuto dell'array...
Codice:
int (*s)[2];
int i=0, dim=2;
s = (int(*)[dim]) malloc (dim * sizeof(int));
while(i<dim){
*(s[i])= ...;
i++;
}
dim = dim + 2; // aggiungo due posizioni
s = (int(*)[dim]) realloc(s, dim * sizeof(int));
*(s[i]) = ...;
*(s[i+1]) = ...;
dim = dim + 6; // ne aggiungo altre sei
s = (int(*)[dim]) realloc(s, dim * sizeof(int)):
*(s[i+2]) = ...;
*(s[i+3]) = ...;
...
*(s[i+7]) = ...;
Idem dicasi per il cast sulle chiamate malloc e realloc è solo una questione stilistica o impatta in qualche modo sulla "gestione dello spazio"?
__________________
Cerco fotocamera con buono zoom!! CLICCA! ° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) ° |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:52.




















