PDA

View Full Version : [newbie] problema "liste" con il C.


Diabolik.cub
21-05-2004, 23:21
salve a tutti! Sono un totale principiante che sta cercando di imparare il C per esigenze scolastiche.. ho un problema nella gestione delle liste dinamiche.

Ho definito una struttura in questo modo:

struct elem {
char Titolo[20];
char Autori[20];
struct elem *link_t;
struct elem *link_a;
};

il problema è che inizializzando un puntatore in questo modo *t2 = NULL si verifica questa situazione:

t2->Titolo = NULL
t2->Autori= ""

così quando dopo controllo se t2 != NULL la risposta è positiva. Come posso fare??

grazie per l'aiuto!!

allego il file sorgente completo e la finestra con l'errore

p.s. il programmino dovrebbe collocare la struttura creata in ordine alfabetico rispetto alle altre...

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

struct elem {
char Titolo[20];
char Autori[20];
struct elem *link_t;
struct elem *link_a;
};

void ordina_autori (struct elem *aux, struct elem **testa ) {
struct elem *t1 = NULL, *t2 = NULL;

t1 = t2 = *testa; //Collega la struttura in base agli autori

while (t2->Autori && strcmp(aux->Autori, t2->Autori) > 0 ) {
t1 = t2;
t2 = t1->link_a;
}

if (t1 == t2) {
aux->link_a = *testa;
*testa = aux;
}
else {
t1->link_a = aux;
aux->link_a = t2;
}
}
main () {
struct elem *testa_a = NULL, *testa_t = NULL, *nuova_t = NULL, *nuova_a = NULL;
char istruzione[40];
int i;

printf("\nInserire una scheda (EOF per finire) => ");
for (i=0; i<5; i++) {
gets(istruzione);
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
sscanf(istruzione, "%s %s", nuova_t->Titolo, nuova_t->Autori);

ordina_autori (nuova_a, &testa_a);

printf("Inserire un altra scheda (EOF per finire) => ");
}

return 0;
}

Diabolik.cub
21-05-2004, 23:23
errore

Ziosilvio
21-05-2004, 23:46
Ciao.
Solo qualche nota qua e là, non ho letto il codice a fondo.

Se esegui:
*t2=NULL;
non inizializzi a NULL t2, ma la variabile il cui indirizzo è il valore di t2; e che, di solito, non è NULL.

Il codice:
t2->Titolo=NULL;
t2->Autori="";
contiene almeno due errori.
Anzitutto, Titolo e Autori sono array e non puntatori, quindi non puoi inizializzarli, né a NULL, né a nessun altro valore.
Inoltre, se pure Autori fosse un puntatore, la riga non lo inizializzerebbe a NULL, ma lo farebbe puntare all'inizio di una stringa vuota (che non è NULL, ma una stringa che contiene il solo null character).

Inoltre, attenzione: quando esegui:
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
nuova_t e nuova_a puntano tutti e due allo stesso oggetto, e non ciascuno a una copia diversa dello stesso oggetto: sei sicuro di volere questo?

Diabolik.cub
22-05-2004, 00:05
innanzitutto grazie per l'aiuto

Originariamente inviato da Ziosilvio
Il codice:
t2->Titolo=NULL;
t2->Autori="";
contiene almeno due errori...

ops mi sono spiegato male io!! questo è quello che vedo nel watch, non quello che ho scritto nel file sorgente ;)


Inoltre, attenzione: quando esegui:
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
nuova_t e nuova_a puntano tutti e due allo stesso oggetto, e non ciascuno a una copia diversa dello stesso oggetto: sei sicuro di volere questo?

si è proprio così perchè alla fine devo ottenere due concatenazioni di puntatori: una per il campo titolo e una per autori.

Cmq ho focalizzato il problema che mi blocca tutto: non riesco a trovare un controllo che mi ritorni NULL quando t2->Autori punta ad una stringa vuota!!
Ho provato con (t2->Autori[0] != '\0') e (strlen(t2->Autori)) ma in entrambi i casi il programma si blocca...

Diabolik.cub
23-05-2004, 13:56
sto incontrando altri problemi con il compilatore Tc++ 4.5
Allego un programmino elementare che però non gira!!

se inizializzo un vettore di strutture di 3 elementi tutto ok, se gli elementi sono già 10 si pianta

sembrerebbero problemi di memoria...

sapreste dirmi come evitarli??

grazie

anx721
23-05-2004, 14:23
Nel primo for l'indice i lo fai andare da 1 a N_LIBRI il che è errato, in quanto gli array sono indicizzati a partire da zero, quindi i deve variare da zero fino a N_LIBRI - 1, come fai nel secondo for.

Ciao.

Diabolik.cub
23-05-2004, 16:14
ops è vero...

cmq mettendo a posto quello il problema rimane!

:cry:

poi un'altra cosa... nei file exe generati da Tc pp101 (avrà 10 anni) cliccando con il destro su proprietà posso impostare il quantitativo di memoria da riservagli (è su auto e va bene infatti...).

Al contrario con gli eseguibili generati da Tc++4.5 per win cliccando su proprietà appaiono solo 3 "linguetti" e posso solo cambiare autore, note etc.. niente riguardo la memoria!!!

il risultato finale è che i file compilati dal primo funzionano sempre, quelli compilati dal secondo funzionano solo se il numero di variabili è ridotto.

anx721
23-05-2004, 20:09
Ma perkè non cambi compilatore? Non l'ho mai sentito questo...

Diabolik.cub
24-05-2004, 00:16
boh a scuola è quello che va per la maggiore, pensavo fosse abbastanza conosciuto! Il nome completo è "Borland Turbo C++ 4.5 for win".

Cmq alla fine sono riusciuto a risolvere tutti i problemi, è bastato dichiarare il vettore di strutture come *record e allocargli la memoria necessaria solo in un secondo momento con la malloc!!

Ora il prog è Rock Solid :cool:

Diabolik.cub
25-05-2004, 00:12
rieccomi qui con il quesito del giorno... cosa c'è che non va in

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL) {
printf("Memoria insufficiente, impossibile inserire nuovo record.\n");
return -1;
}

qui il programma si pianta

(Libro è una struttura rinominata con typedef)

Ziosilvio
25-05-2004, 00:59
Originariamente inviato da Diabolik.cub
rieccomi qui con il quesito del giorno... cosa c'è che non va in

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL) {
printf("Memoria insufficiente, impossibile inserire nuovo record.\n");
return -1;
}

qui il programma si pianta

(Libro è una struttura rinominata con typedef)
Attenzionissima alle precedenze degli operatori!
L'espressione:
aux = (Libro *) malloc (sizeof(Libro)) == NULL
non corrisponde a:
(aux=(Libro*)malloc(sizeof(Libro))) == NULL
ma a:
aux = ((Libro*)malloc(sizeof(Libro))==NULL)
Tutte queste espressioni sono vere se e solo se l'allocazione di memoria per un nuovo oggetto di tipo Libro riesce; ma mentre la seconda assegna ad aux l'indirizzo della nuova struttura allocata oppure NULL, l'ultima (o la prima, tanto sono equivalenti) gli assegna o il valore 0 o il valore 1.
Siccome aux è un puntatore, qualunque cosa cerchi in seguito di usare il suo valore si ritrova o alla locazione zero, che non è utilizzabile, o alla locazione 1, che è occupata dal sistema (sei sotto DOS, se ho capito bene): un'operazione di scrittura su una di queste zone provoca un errore.

[Modalità "io ciò Linux :D " ON]
Solo che Linux ti fa uscire con un messaggio di errore, Microzozz si impianta.
[Modalità "io ciò Linux :D " OFF]

Prova a correggere questa riga, e facci sapere che succede.

anx721
25-05-2004, 01:07
Purtroppo la sintassi del c ti permette di scrivere un sacco di cose, ma è anche piena di trappole e se non la si conosce a fondo si possono combinare dei casini, sopratutto se il programma non va in crash come nel tuo caso, per cui ti accorgi subito che c'è un bug.

Nel caso specifico almeno un errore è nella riga:

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL)

perkè quello che tu vuoi fare è assegnare a aux l'indirizzo restituito dalla malloc e poi vedere se tale indirizzo è NULL, però, in virtù della precedenza degli operatori, viene eseguito prima il controllo sull'uguaglianza a NULL e poi l'assegnamento; se tu scrivi:

int ok = 1 == 0;

viene prima eseguito 1 == 0 producendo il risultato booleano che viene quindi assegnato alla variabile ok; analogamente con

aux = (Libro *) malloc (sizeof(Libro)) == NULL

viene eseguito prima

(Libro *) malloc (sizeof(Libro)) == NULL

che restituisce zero se l'indirizzo restituito dalla malloc non è NULL (come accade quasi sempre), o uno viceversa, e quindi assegni a aux rispettivamente zero o uno, ovvero hai un puntatore che punta a zero (NULL) o alla locazione 1, causando quindi il crash.

Prova allora a mettere le parentesi

if ((aux = (Libro *) malloc (sizeof(Libro)) )== NULL)

o ancora meglio evita queste facilitazioni della sintassi, che secondo me complicano solo la vita perche rendono il codice poco leggibile e favoriscono i bug:

aux = (Libro *) malloc (sizeof(Libro));
if(aux == NULL){

}


non ti piace cosi?

anx721
25-05-2004, 01:14
Solo che Linux ti fa uscire con un messaggio di errore, Microzozz si impianta.



Sempre a denigrare windows...windows non si pianta affatto, ti fà uscire la finestrella in cui ti dice che il programma ha causato un errore, clicchi sul pulsante 'chiudi', e continua normalmente, linux ti fa uscire il messagio 'segmentation fault' (credo) sulla console, non vedo la differenza :O

Diabolik.cub
25-05-2004, 02:24
:rolleyes:

avete ragione l'errore era proprio lì... probabilmente mi ha fregato il gran numero di parentesi aperte.
:p ;)

grazie a tutti.

p.s. la cosa veramente vergognosa è che per 4-5 volte ho ignorato il warning che invece mi segnalava il tentativo di conversione INT->PTR... devo iniziare a leggere quei messaggi!!
:muro:

h1jack3r
25-05-2004, 18:17
Eh Diabolik...anche tu con Valenzano?

Diabolik.cub
25-05-2004, 22:22
Originariamente inviato da h1jack3r
Eh Diabolik...anche tu con Valenzano?

:eek: :eek: :eek:

incredibile adesso scopriamo che siamo compagni di corso!!!

io sono 'inf' PRLP quindi al primo corso... (ovviamente primo anno) e tu?

h1jack3r
25-05-2004, 23:56
eh si...
:sofico:
sto forum è una figata cmq...e quella esercitazione è una bella rogna..

Diabolik.cub
26-05-2004, 22:45
ho praticamente ultimato il programmino che devo fare, e funziona tutto se non fosse per un piccolo problema legato alla funzione free per "disallocare" la memoria di strutture da eliminare.

Per lo scopo ho definito una funzione "libera_memoria (Libro **ptr_aux)" dove Libro è una struttura composta da 2 campi: una stringa e un puntatore alla struttura (per creare una lista dinamica).

Il corpo della funzione è il seguente:
{
free (&(*ptr_aux)->Titolo);
free (&(*aux)->link_t);
}

subito dopo averla eseguita nel main con
Libro *aux;

libera_memoria (&aux);

libero il puntatore alla struttura con

free (aux);

Trovate qualche errore eclatante in queste righe di codice? Perchè dopo avermi liberato 5-6 puntatori mi viene il classico "Processor Fault" e non riesco a capire perchè!

ciao e grazie.

anx721
26-05-2004, 23:07
Il campo titolo non è un puntatore a della memoria allocata dinamicamente, quindi non dovrebbe essere deallocato con free, almeno cosi penso, poi non capisco perche usi l'operatore & e perche passi un puntatore a puntatore come argomento della funzione. Io avrei fatto così:


void libera_memoria (Libro *ptr_aux){
Libro * temp;
while(ptr_aux != NULL){
//mi mantengo il puntatore all'elemento successivo
temp = ptr_aux -> link_t;
free(ptr_aux);
ptr_aux = temp;
}
}


In questo caso ti basta l'istruzione

libera_memoria(aux);

per liberare tutta la memoria allocata.

Diabolik.cub
27-05-2004, 10:20
dunque non ho capito...

la tua funzione se non sbaglio mi dealloca tutti i puntatori da quello che inserisci fino all'ultimo, giusto?

io devo solo deallocare una singola struttura.

Mettiamo che questa struttura *aux sia composta da 3 stringhe a un puntatore alla struttura, non devo deallocare manualmente questi 4 puntatori prima di deallocare il puntatore 'aux' alla struttura??

anx721
27-05-2004, 15:46
Originariamente inviato da Diabolik.cub
la tua funzione se non sbaglio mi dealloca tutti i puntatori da quello che inserisci fino all'ultimo, giusto?

Si

Originariamente inviato da Diabolik.cub
Mettiamo che questa struttura *aux sia composta da 3 stringhe a un puntatore alla struttura, non devo deallocare manualmente questi 4 puntatori prima di deallocare il puntatore 'aux' alla struttura??

Si, se sono variabili allocate dinamicamente, se le stringe sono dichiarate come

char *

e le hai allocate con malloc allora vanno deallocate, se no no. Il campo t_lonk del successivo non lo devi dealocare, perche tu hai detto che vuoi deallocare una signola struttura, quindi non va deallocata la memoria della struttura seguente.