View Full Version : [C]Crash del programma con free()
ciao a tutti questo il codice del mio programmino...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct nomi{
char *n;
nomi *suc;
};
int main()
{
nomi *inizio,*lista;
char *a;
int i,n;
printf("Quanti nomi vuoi inserire?--> ");
scanf("%d",&n);
system("cls");
printf("Inseire prima stringa");
fflush(stdin);
a=(char*)malloc(sizeof(char));
gets(a);
inizio=(nomi*)malloc(sizeof(nomi));
inizio->n=(char*)malloc(strlen(a)*sizeof(char)+1);
strcpy(inizio->n,a);
lista=inizio;
for(i=1; i<n; i++){
system("cls");
a=(char*)malloc(sizeof(char));
lista->suc=(nomi*)malloc(sizeof(nomi));
lista=lista->suc;
printf("%d nome : ",i+1);
gets(a);
lista->n=(char*)malloc(strlen(a)*sizeof(char)+1);
strcpy(lista->n,a);
}
lista->suc=NULL;
fflush(stdin);
while(inizio!=NULL){
printf("\n%s",inizio->n);
inizio=inizio->suc;
}
system("pause");
free(inizio->n);
free(lista);
free(inizio);
system("pause");
free(a);
return 0;
}
come mai quando il programma arriva nel punto free(a); quindi dovrebbe liberare la memoria occupata da *a il programma crasha?
ho provato senza free(a); e il programma esce senza problemi ma io voglio liberare quella memoria...è strana come cosa ho sbaglio?:mbe:
Cait Sith
28-01-2013, 13:54
se hai un crash sul free ci sono due possibilità:
- doppio free su quel puntatore
- accesso di memoria invalido su quel puntatore
nel primo caso lo risolvi assegnando NULL a tutti i puntatore liberati (se non succede è questo il motivo)
nel secondo caso bisogna trovare l'errore
se programmi su linux ti consiglio di usare valgrind,
valgrind [opzioni] tuo_programma
e lui se ci sono degli accessi alla memoria non validi te lo dice
Hmm, non so come hai fatto a compilare, perchè è sbagliato l'utilizzo della struttura nomi.
Se non definisci un nuovo tipo così:
typedef struct miastruttura{
int a;
char c;
}miastruttura;
Allora ogni volta che vuoi usare una variabile con questa struttura, devi dichiararla:
struct miastruttura miavariabile;
Prova ad aggiustare questa cosa e poi dicci.
sottovento
28-01-2013, 14:06
a=(char*)malloc(sizeof(char));
gets(a);
Qui allochi lo spazio necessario per un solo carattere, vale a dire il terminatore.
E' chiaramente insufficiente; di conseguenza, la stringa inserita andra' a "sporcare" memoria altrove. Alcuni compilatori inseriscono una "No man's land", ovvero alcuni byte con valori prefissati subito dopo la tua allocazione, appunto per verificare se ha sfondato.
Tali valori sono controllati al momento della free(). Cosi' vai in crash
In C++ si puo' fare, evidentemente sta compilando in modalita' C++.
Ok, non lo sapevo! :D
Ma poi, qual è il significato di allocare un solo spazio per un carattere? :mbe:
char *a;
a=(char*)malloc(sizeof(char));
Non era meglio fare un semplice char?
come potrei allocare più di un carattere?comunque sto usando visual c++ perchè è l'unico che mi va su windows 8..
Vincenzo1968
28-01-2013, 18:01
come potrei allocare più di un carattere?comunque sto usando visual c++ perchè è l'unico che mi va su windows 8..
C'è anche GCC per Windows. ;)
eh ok questo lo sapevo,ma come faccio a sapere quanti caratteri avrà la stringa che inserisce l'utente?mi servirebbe un modo per allocarla senza sapere il numero di caratteri..
Vincenzo1968
28-01-2013, 18:20
eh ok questo lo sapevo,ma come faccio a sapere quanti caratteri avrà la stringa che inserisce l'utente?mi servirebbe un modo per allocarla senza sapere il numero di caratteri..
Ci vorrebbe la sfera di cristallo. Puoi allocare un buffer ragionevolmente grande(1024 byte) in modo da essere sicuro che riuscirà a contenere la stringa inserita dall'utente.
Dopo puoi calcolare la lunghezza della stringa inserita con strlen e riallocare il buffer con realloc.
;)
mi puoi fare un esempio veloce veloce?..
Vincenzo1968
28-01-2013, 18:44
http://www.cplusplus.com/reference/cstdlib/realloc/
;)
char *szMiaStringa = NULL;
int len;
szMiaStringa = (char*)malloc(sizeof(char) * 1024);
if ( !MiaStringa )
{
printf("Impossibile allocare la memoria. Addio!\n");
return -1;
}
printf("Inserisci una stringa: ");
fgets (szMiaStringa, 1024, stdin);
len = strlen(szMiaStringa);
szMiaStringa = realloc(szMiaStringa, len + 1);
if ( szMiaStringa )
printf("Hai inserito la stringa \"%s\". La stringa inserita è lunga %d byte.\n", szMiaStringa, len);
/* Qui altro codice */
if ( szMiaStringa )
free(MiaStringa);
Vincenzo1968
28-01-2013, 19:14
E comunque, se la memoria non è un problema, puoi evitare di riallocare il buffer:
char *szMiaStringa = NULL;
int len;
szMiaStringa = (char*)malloc(sizeof(char) * 1024);
if ( !MiaStringa )
{
printf("Impossibile allocare la memoria. Addio!\n");
return -1;
}
printf("Inserisci una stringa: ");
fgets (szMiaStringa, 1024, stdin);
len = strlen(szMiaStringa);
if ( szMiaStringa )
printf("Hai inserito la stringa \"%s\". La stringa inserita è lunga %d byte.\n", szMiaStringa, len);
/* Qui altro codice */
if ( szMiaStringa )
free(MiaStringa);
Vincenzo1968
28-01-2013, 19:16
Nientedimeno puoi evitare del tutto(sempre se lo spazio di memoria non è un problema) di allocare il buffer sullo heap:
char szMiaStringa[1024]
int len;
printf("Inserisci una stringa: ");
fgets (szMiaStringa, 1024, stdin);
len = strlen(szMiaStringa);
printf("Hai inserito la stringa \"%s\". La stringa inserita è lunga %d byte.\n", szMiaStringa, len);
/* Qui altro codice */
grazie provero:) ah ultimo cosa ho provato a compilare con Code::Blocks...ma come mai quando per esempio scrivo una frase con printf le parole me le segna di rosso?compilare compila ma da fastidio
Vincenzo1968
29-01-2013, 18:21
grazie provero:) ah ultimo cosa ho provato a compilare con Code::Blocks...ma come mai quando per esempio scrivo una frase con printf le parole me le segna di rosso?compilare compila ma da fastidio
Perché, come ogni altro IDE(Visual Studio, etc), Code::Blocks evidenzia la sintassi. E' una caratteristica comoda che ti consente di distinguere al volo le varie parti sintattiche: identificatori, costanti, etc.
Se non ti piace il colore rosso puoi cambiarlo con quello che preferisci(o toglierlo del tutto).
Dovrebbe esserci la voce nel menù opzioni.
;)
EDIT: Settings -> Editor -> Syntax highlighting -> String
nome ma me le segna di rosso sotto come se avessi scritto male,un po come fa word :)
Vincenzo1968
29-01-2013, 18:48
A me le segna in blu le stringhe:
http://img685.imageshack.us/img685/8185/codeblocks1.jpg
Ma posso cambiare il colore attraverso "Settings -> Editor -> Syntax highlighting -> String".
Per esempio, se mi piace il rosso(e io sono di sinistra, quindi si, mi piace il rosso):
http://img28.imageshack.us/img28/9508/codeblocks2.jpg
;)
no a me mette dei segnetti sotto le parrole di errore come su word ,non capisco perchè...esempio printf("ciao a tutti");su ciao a tutti mi mette dei segnetti rossi
Vincenzo1968
29-01-2013, 20:05
no a me mette dei segnetti sotto le parrole di errore come su word ,non capisco perchè...esempio printf("ciao a tutti");su ciao a tutti mi mette dei segnetti rossi
Allora non saprei. Puoi fare uno screenshot?
Vincenzo1968
29-01-2013, 20:32
Un'immagine di quello che ti appare sullo schermo da uploadare su imageshack come ho fatto io nel post precedente.
;)
Di solito gli IDE(e quindi anche Code::Blocks) sottolineano in rosso gli errori sintattici. Ma se dici che il programma compila tranquillamente...
Ci vorrebbe una bella immagine(screenshot ;) ) per capire che diamine è.
appunti ma non so come si fa...comunque ho riscritto il codice....
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
char *info;
struct data *suc;
}data;
int main()
{
bool trovata=false;
char *cerca;
int i,n;
data *lista=NULL;
data *lista2;
char *tmp;
data *tmp2=NULL;
tmp=(char*)malloc(100*sizeof(char));
lista=( data*)malloc(sizeof( data));
printf("Quante persone vuoi inserire?");
scanf("%d",&n);
fflush(stdin);
printf("primo nome-> ");
gets(tmp);
lista->info=(char*)malloc(strlen(tmp)*sizeof(char)+1);
strcpy(lista->info,tmp);
free(tmp);
lista2=lista;
fflush(stdin);
//////Inserisco nuovi nodi
for(i=1; i<n; i++){
lista2->suc=(data*)malloc(sizeof(data));
lista2=lista2->suc;
printf("%d nome:--> ",i+1);
tmp=(char*)malloc(100*sizeof(char));
gets(tmp);
lista2->info=(char*)malloc(strlen(tmp)*sizeof(char)+1);
strcpy(lista2->info,tmp);
free(tmp);
}
lista2->suc=NULL;
//stampo la lista
while(lista!=NULL){
printf("%s\n",lista->info);
lista=lista->suc;
}
system("pause");
//cerco un nome
system("cls");
printf("Quale nome vuoi cercare?");
cerca=(char*)malloc(100*sizeof(char));
gets(cerca);
while(lista!=NULL){
if(strcmp(lista->info,cerca)==0){
printf("Trovata");
trovata=true;
free(cerca);
break;
}
lista=lista->suc;
}
if(trovata==true){
printf("\n\n\Trovato");
}
else
printf("Non trovato");
//elimino tutta la lista
while(lista!=NULL){
tmp2=lista->suc;
free(lista->info);
free(lista);
lista=tmp2;
free(tmp2);
tmp2=lista2->suc;
free(lista2->info);
free(lista2);
lista=tmp2;
free(tmp2);
}
//ristampo per controllare
while(lista!=NULL){
printf("%s\n",lista->info);
lista=lista->suc;
}
system("pause");
return 0;
}
ma non mi riesce a trovare il nome che cerco,cosa sto sbagliando?
sottovento
31-01-2013, 05:33
nessuno?
//stampo la lista
while(lista!=NULL){
printf("%s\n",lista->info);
lista=lista->suc;
}
qui ti perdi il puntatore alla lista, generando memoria non piu' recuperabile (i.e. memory leak). Alla fine di questo ciclo, la tua lista e' nulla poiche' hai perso tutti gli elementi.
Ci sono alcune cose da controllare:
1 - la malloc() puo' fallire, quindi una volta allocato memoria, controlla se l'operazione e' andata a buon fine.
2 - continui ad allocare/deallocare tmp. Non ti serve fare tutte quelle operazioni inutili. Anzi, non e' neppure necessario allocare tmp dinamicamente, come ti ha mostrato Vincenzo;
3 - se usi gets(), l'utente potrebbe inserire un numero arbitrario di caratteri, anche superiori a 100, e farti incartare l'applicazione. fgets() ti risolve il problema. Oppure puoi fare le cose piu' complicate usando una getchar();
4 - tratti il primo elemento separatamente. A ben vedere non ce ne sarebbe bisogno;
5 - quanto posti del codice su questo forum, e' consigliabile usare i tag di CODE, cosi' da mantenere l'indentazione.
Spero ti possa essere d'aiuto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
char *info;
struct data *suc;
}data;
///creo i nodi successivi
data *crea_lista(data *lista){
int lun;
char *nome=(char*)malloc(sizeof(char)*1024);
lista=(data*)malloc(sizeof(data));
if(!lista){
printf("Errore!");
system("Exit");
}
system("cls");
printf("1 Nome:--> ");
fgets(nome,1024,stdin);
lun=strlen(nome);
nome=realloc(nome,lun+1);
lista->info=(char*)malloc(strlen(nome)*sizeof(char));
strcpy(lista->info,nome);
free(nome);
return lista;
}
///Creo i nodi successivi
data *crea_nodi(data *nodi,int n){
char *nome=(char*)malloc(sizeof(char)*1024);
int lun,i;
system("cls");
for(i=2; i<=n; i++){
nome=(char*)malloc(sizeof(char)*1024);
nodi->suc=(data*)malloc(sizeof(data));
nodi=nodi->suc;
printf("%d Nome:--> ",i);
fgets(nome,1024,stdin);
lun=strlen(nome);
nome=realloc(nome,lun+1);
nodi->info=(char*)malloc(strlen(nome)*sizeof(char));
strcpy(nodi->info,nome);
}
nodi->suc=NULL;
free(nome);
return nodi;
}
///stampo tutta la lista
void stampa(data*lista){
system("cls");
int i;
printf("\t\t-----lista-------\n\n\n");
while(lista!=NULL){
printf("%s\n",lista->info);
lista=lista->suc;
}
system("pause");
}
int cerca(data *lista){
int trovato;
system("cls");
char *cerca;
int lun;
cerca=(char*)malloc(sizeof(char)*1024);
printf("Quale nome vuoi cercare?--> ");
fgets(cerca,1024,stdin);
lun=strlen(cerca);
cerca=realloc(cerca,lun+1);
while(lista!=NULL){
lista=lista->suc;
if(strcmp(lista->info,cerca)==0){
trovato=1;
return trovato;
break;
}
}
free(cerca);
return trovato;
}
data *distruggi(data*lista){
data *tmp=NULL;
while(lista!=NULL){
tmp=lista->suc;
free(lista->info);
free(lista);
lista=tmp;
}
free(tmp);
return lista;
}
int main()
{
data *lista=NULL,*lista2;
int riscontro;
int n;
printf("Quanti nomi vuoi inserire?--> ");
scanf("%d",&n);
system("cls");
fflush(stdin);
lista=crea_lista(lista);
lista2=lista;
lista2=crea_nodi(lista2,n);
stampa(lista);
riscontro=cerca(lista);
if(riscontro==1){
system("cls");
printf("Nome trovato");
}
else
printf("Nome non trovato");
lista=distruggi(lista);
system("pause");
return 0;
}
ho provato a riscrivere il codice seguendo i vostri consigli...ma ancora non mi trova il nome che si inserisce precedentemente:doh: cosa non va ancora?:muro:
Vincenzo1968
31-01-2013, 19:34
Sam, ho trovato un programmino sulle liste che avevo scritto qualche tempo fa:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int nMemoriaAllocata = 0;
int nMemoriaDeallocata = 0;
typedef struct tagPersona
{
int Anni;
char Cognome[50];
char Nome[50];
struct tagPersona *next;
} Persona;
int ConfrontaAnni(Persona *p1, Persona *p2)
{
if ( p1->Anni < p2->Anni )
return -1;
else if ( p1->Anni > p2->Anni )
return 1;
else
return 0;
}
int ConfrontaCognome(Persona *p1, Persona *p2)
{
return strcmp(p1->Cognome, p2->Cognome);
}
int ConfrontaCognomeNome(Persona *p1, Persona *p2)
{
char szCognomeNome1[101];
char szCognomeNome2[101];
strcpy(szCognomeNome1, p1->Cognome);
strcat(szCognomeNome1, p1->Nome);
strcpy(szCognomeNome2, p2->Cognome);
strcat(szCognomeNome2, p2->Nome);
return strcmp(szCognomeNome1, szCognomeNome2);
}
int (*Confronta)(Persona *, Persona *) = NULL;
Persona* Find(Persona *Pers, Persona *first)
{
Persona *n = first;
while( n != NULL )
{
//if( n->Anni == Pers->Anni )
if( (*Confronta)(n, Pers) == 0 ) // confronta per cognome e nome
return n;
n = n->next;
}
return NULL;
}
Persona* Delete(Persona *Pers, Persona *first)
{
Persona *n = first;
n = Find(Pers, first);
if( n == NULL )
return first;
// Cancellazione primo elemento
if( n == first )
{
n = n->next;
free(first);
nMemoriaDeallocata += sizeof(Persona);
return n;
}
// Prendiamo un puntatore all'elemento precedente
// che ci servirà per cancellare l'elemento centrale o l'ultimo
Persona *prevPers = NULL;
n = first;
//while ( n->Anni != Pers->Anni )
while ( (*Confronta)(n, Pers) != 0 )
{
prevPers = n;
n = n->next;
}
// Cancellazione ultimo elemento
if ( n->next == NULL )
{
free(n);
nMemoriaDeallocata += sizeof(Persona);
prevPers->next = NULL;
return first;
}
// Cancellazione elemento centrale
prevPers->next = n->next;
free(n);
nMemoriaDeallocata += sizeof(Persona);
return first;
}
void Print(Persona *first)
{
Persona *n = first;
while( n != NULL )
{
printf("%d %s %s \n", n->Anni, n->Cognome, n->Nome);
n = n->next;
}
}
void Free(Persona *first)
{
Persona *n1 = first, *n2;
while ( n1 != NULL )
{
n2 = n1->next;
free(n1);
nMemoriaDeallocata += sizeof(Persona);
n1 = n2;
}
}
Persona* NewNode(Persona *Pers)
{
Persona *n;
n = (Persona *)malloc(sizeof(Persona));
if( n == NULL )
return NULL;
n->Anni = Pers->Anni;
strcpy(n->Cognome, Pers->Cognome);
strcpy(n->Nome, Pers->Nome);
n->next = NULL;
nMemoriaAllocata += sizeof(Persona);
return n;
}
Persona* Insert(Persona *Pers, Persona *first)
{
Persona *n = first, *nuovo;
// catena vuota
if ( first == NULL )
return NewNode(Pers);
if( (*Confronta)(n, Pers) > 0 )
{
nuovo = NewNode(Pers);
nuovo->next = first;
return nuovo;
}
while( n != NULL)
{
if( (*Confronta)(n, Pers) == 0 )
{
return first;
}
n = n->next;
}
n = first;
while( n->next != NULL )
{
if( (*Confronta)(n->next, Pers) > 0 )
{
nuovo = NewNode(Pers);
nuovo->next = n->next;
n->next = nuovo;
return first;
}
n = n->next;
}
nuovo = NewNode(Pers);
n->next = nuovo;
return first;
}
Persona* Append(Persona *Pers, Persona *first)
{
Persona *n = first, *nuovo;
// catena vuota
if ( first == NULL )
return NewNode(Pers);
n = first;
while( n->next != NULL )
{
n = n->next;
}
nuovo = NewNode(Pers);
//nuovo->next = NULL;
n->next = nuovo;
return first;
}
Persona *Reverse(Persona *first)
{
Persona *pr = NULL;
Persona *tmp = NULL;
while (first != NULL)
{
tmp = first->next;
first->next = pr;
pr = first;
first = tmp;
}
return pr;
}
int main(int argc, char* argv[])
{
Confronta = ConfrontaCognomeNome;
int i, N;
Persona Pers;
Persona *pPers = NULL;
Persona *pPersFind = NULL;
N = 5;
Pers.Anni = 45;
strcpy(Pers.Cognome, "Sciascia");
strcpy(Pers.Nome, "Leonardo");
pPers = Append(&Pers, pPers);
for ( i = 2; i <= N; i++ )
{
if ( i == 2 )
{
Pers.Anni = 70;
strcpy(Pers.Cognome, "Camilleri");
strcpy(Pers.Nome, "Andrea");
}
else if ( i == 3 )
{
Pers.Anni = 54;
strcpy(Pers.Cognome, "Orwell");
strcpy(Pers.Nome, "George");
}
else if ( i == 4 )
{
Pers.Anni = 65;
strcpy(Pers.Cognome, "Pirandello");
strcpy(Pers.Nome, "Luigi");
}
else if ( i == 5 )
{
Pers.Anni = 68;
strcpy(Pers.Cognome, "Simenon");
strcpy(Pers.Nome, "Georges");
}
//pPers = Insert(&Pers, pPers);
pPers = Append(&Pers, pPers);
}
Print(pPers);
//Pers.Anni = 45;
//strcpy(Pers.Cognome, "Sciascia");
//strcpy(Pers.Nome, "Leonardo");
//pPers = Delete(&Pers, pPers);
//Pers.Anni = 54;
//strcpy(Pers.Cognome, "Orwell");
//strcpy(Pers.Nome, "George");
//pPers = Delete(&Pers, pPers);
//Pers.Anni = 70;
//strcpy(Pers.Cognome, "Camilleri");
//strcpy(Pers.Nome, "Andrea");
//pPers = Delete(&Pers, pPers);
//printf("\n");
//Print(pPers);
pPers = Reverse(pPers);
printf("\nLista dopo aver chiamato la funzione Reverse:\n");
Print(pPers);
strcpy(Pers.Cognome, "Sciascia");
strcpy(Pers.Nome, "Leonardo");
pPersFind = Find(&Pers, pPers);
if ( pPersFind != NULL )
{
printf("\nNella lista esiste una persona chiamata %s %s di anni %d\n", pPersFind->Nome, pPersFind->Cognome, pPersFind->Anni);
}
else
{
printf("\nNella lista non esiste una persona chiamata %s %s di anni %d\n", pPersFind->Nome, pPersFind->Cognome, pPersFind->Anni);
}
Free(pPers);
printf("\nTotale Memoria Allocata: %d\nTotale Memoria Deallocata: %d\n", nMemoriaAllocata, nMemoriaDeallocata);
return 0;
}
http://img20.imageshack.us/img20/1425/listaxe.jpg
Confrontalo con il tuo e cerca di capire dove stanno gli errori. Eventualmente chiedi pure.
;)
Vincenzo1968
31-01-2013, 19:56
Nientedimeno avevo scritto pure la versione per liste doppiamente concatenate:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int nMemoriaAllocata = 0;
int nMemoriaDeallocata = 0;
typedef struct tagPersona
{
int Anni;
char Cognome[50];
char Nome[50];
struct tagPersona *prev;
struct tagPersona *next;
} Persona;
int ConfrontaAnni(Persona *p1, Persona *p2)
{
if ( p1->Anni < p2->Anni )
return -1;
else if ( p1->Anni > p2->Anni )
return 1;
else
return 0;
}
int ConfrontaCognome(Persona *p1, Persona *p2)
{
return strcmp(p1->Cognome, p2->Cognome);
}
int ConfrontaCognomeNome(Persona *p1, Persona *p2)
{
char szCognomeNome1[101];
char szCognomeNome2[101];
strcpy(szCognomeNome1, p1->Cognome);
strcat(szCognomeNome1, p1->Nome);
strcpy(szCognomeNome2, p2->Cognome);
strcat(szCognomeNome2, p2->Nome);
return strcmp(szCognomeNome1, szCognomeNome2);
}
int (*Confronta)(Persona *, Persona *) = NULL;
Persona* NewNode(Persona *Pers)
{
Persona *n;
n = (Persona *)malloc(sizeof(Persona));
if( n == NULL )
return NULL;
n->Anni = Pers->Anni;
strcpy(n->Cognome, Pers->Cognome);
strcpy(n->Nome, Pers->Nome);
n->prev = NULL;
n->next = NULL;
nMemoriaAllocata += sizeof(struct tagPersona);
return n;
}
Persona* Insert(Persona *Pers, Persona *first)
{
Persona *n = first, *nuovo;
int more = 1;
if ( first == NULL )
return NewNode(Pers);
if( (*Confronta)(n, Pers) > 0 )
{
nuovo = NewNode(Pers);
nuovo->next = first;
first->prev = nuovo;
return nuovo;
}
while( n != NULL)
{
if( (*Confronta)(n, Pers) == 0 )
{
return first;
}
n = n->next;
}
n = first;
while( n->next != NULL )
{
if( (*Confronta)(n->next, Pers) > 0 )
{
nuovo = NewNode(Pers);
n->next->prev = nuovo;
nuovo->next = n->next;
nuovo->prev = n;
n->next = nuovo;
return first;
}
n = n->next;
}
nuovo = NewNode(Pers);
n->next = nuovo;
nuovo->prev = n;
return first;
}
Persona* Append(Persona *Pers, Persona *first)
{
Persona *n = first, *nuovo;
int more = 1;
if ( first == NULL )
return NewNode(Pers);
n = first;
while( n->next != NULL )
{
n = n->next;
}
nuovo = NewNode(Pers);
n->next = nuovo;
nuovo->prev = n;
return first;
}
Persona* Find(Persona *Pers, Persona *first)
{
Persona *n = first;
while( n != NULL )
{
if( (*Confronta)(n, Pers) == 0 )
return n;
n = n->next;
}
return NULL;
}
Persona* Delete(Persona *Pers, Persona *first)
{
Persona *n = first;
n = Find(Pers, first);
if( n == NULL )
return first;
if( n->next != NULL )
n->next->prev = n->prev;
if( n->prev != NULL )
n->prev->next = n->next;
if( n == first )
{
n = n->next;
free(first);
nMemoriaDeallocata += sizeof(Persona);
return n;
}
free(n);
nMemoriaDeallocata += sizeof(Persona);
return first;
}
void Print(Persona *first)
{
Persona *n = first;
while( n != NULL )
{
printf("%d %s %s \n", n->Anni, n->Cognome, n->Nome);
n = n->next;
}
}
void Free(Persona *first)
{
Persona *n1 = first, *n2;
while ( n1 != NULL )
{
n2 = n1->next;
free(n1);
nMemoriaDeallocata += sizeof(Persona);
n1 = n2;
}
}
Persona *Reverse (Persona *first)
{
Persona *pr = NULL;
Persona *tmp = NULL;
while (first != NULL)
{
tmp = first->next;
first->next = pr;
first->prev = tmp;
pr = first;
first = tmp;
}
return pr;
}
int main(int argc, char* argv[])
{
int i, N;
Persona Pers;
Persona *pPers = NULL;
Persona *pPersFind = NULL;
Confronta = ConfrontaCognomeNome;
N = 5;
Pers.Anni = 45;
strcpy(Pers.Cognome, "Sciascia");
strcpy(Pers.Nome, "Leonardo");
pPers = Insert(&Pers, pPers);
//pPers = Append(&Pers, pPers);
for ( i = 2; i <= N; i++ )
{
if ( i == 2 )
{
Pers.Anni = 70;
strcpy(Pers.Cognome, "Camilleri");
strcpy(Pers.Nome, "Andrea");
}
else if ( i == 3 )
{
Pers.Anni = 54;
strcpy(Pers.Cognome, "Orwell");
strcpy(Pers.Nome, "George");
}
else if ( i == 4 )
{
Pers.Anni = 65;
strcpy(Pers.Cognome, "Pirandello");
strcpy(Pers.Nome, "Luigi");
}
else if ( i == 5 )
{
Pers.Anni = 68;
strcpy(Pers.Cognome, "Simenon");
strcpy(Pers.Nome, "Georges");
}
pPers = Insert(&Pers, pPers);
//pPers = Append(&Pers, pPers);
}
Print(pPers);
//Pers.Anni = 45;
//strcpy(Pers.Cognome, "Sciascia");
//strcpy(Pers.Nome, "Leonardo");
//pPers = Delete(&Pers, pPers);
//Pers.Anni = 54;
//strcpy(Pers.Cognome, "Orwell");
//strcpy(Pers.Nome, "George");
//pPers = Delete(&Pers, pPers);
//Pers.Anni = 70;
//strcpy(Pers.Cognome, "Camilleri");
//strcpy(Pers.Nome, "Andrea");
//pPers = Delete(&Pers, pPers);
pPers = Reverse(pPers);
printf("\nLista dopo aver chiamato la funzione Reverse:\n");
Print(pPers);
strcpy(Pers.Cognome, "Sciascia");
strcpy(Pers.Nome, "Leonardo");
pPersFind = Find(&Pers, pPers);
if ( pPersFind != NULL )
{
printf("\nNella lista esiste una persona chiamata %s %s di anni %d\n", pPersFind->Nome, pPersFind->Cognome, pPersFind->Anni);
}
else
{
printf("\nNella lista non esiste una persona chiamata %s %s di anni %d\n", pPersFind->Nome, pPersFind->Cognome, pPersFind->Anni);
}
Free(pPers);
printf("\nTotale Memoria Allocata: %d\nTotale Memoria Deallocata: %d\n", nMemoriaAllocata, nMemoriaDeallocata);
return 0;
}
è molto meglio del mio anche più efficiente..,e in più è dettagliato:D ma non capisco cosa sbaglio:muro: anche perchè dovrebbe confrontami le due scringhe con strcmp e se sono uguali mette la variabile trovato a 1,e invece crasha:muro:
Vincenzo1968
31-01-2013, 23:00
è molto meglio del mio anche più efficiente..,e in più è dettagliato:D ma non capisco cosa sbaglio:muro: anche perchè dovrebbe confrontami le due scringhe con strcmp e se sono uguali mette la variabile trovato a 1,e invece crasha:muro:
No Sam, non intendevo dire questo. La mia è migliore perché funziona, perché non crasha. Non perché è più efficiente. Il primo requisito di un software è che deve funzionare.
Intendevo dire, studiati il codice che ti ho postato(la prima versione, la lista semplice) e cerca di capire che cosa fa. Se hai dubbi su qualche punto chiedi.
Poi, una volta capito il funzionamento delle liste, potrai provare ad aggiustare la tua versione. Se non ci dovessi riuscire te l'azzizzo io. Però me la devi indentare bene.
;)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
char *info;
struct data *suc;
}data;
///creo i nodi successivi
data *crea_lista(data *lista){
int lun;
char *nome=(char*)malloc(sizeof(char)*1024);
lista=(data*)malloc(sizeof(data));
if(!lista){
printf("Errore!");
system("Exit");
}
system("cls");
printf("1 Nome:--> ");
fgets(nome,1024,stdin);
lun=strlen(nome);
nome=realloc(nome,lun+1);
lista->info=(char*)malloc(strlen(nome)*sizeof(char));
strcpy(lista->info,nome);
free(nome);
return lista;
}
///Creo i nodi successivi
data *crea_nodi(data *nodi,int n){
char *nome=(char*)malloc(sizeof(char)*1024);
int lun,i;
system("cls");
for(i=2; i<=n; i++){
nome=(char*)malloc(sizeof(char)*1024);
nodi->suc=(data*)malloc(sizeof(data));
nodi=nodi->suc;
printf("%d Nome:--> ",i);
fgets(nome,1024,stdin);
lun=strlen(nome);
nome=realloc(nome,lun+1);
nodi->info=(char*)malloc(strlen(nome)*sizeof(char));
strcpy(nodi->info,nome);
}
nodi->suc=NULL;
free(nome);
return nodi;
}
///stampo tutta la lista
void stampa(data*lista){
system("cls");
int i;
printf("\t\t-----lista-------\n\n\n");
while(lista!=NULL){
printf("%s\n",lista->info);
lista=lista->suc;
}
system("pause");
}
data *cerca(data *lista){
int trovato=1;
system("cls");
char *cerca;
int lun;
cerca=(char*)malloc(sizeof(char)*1024);
printf("Quale nome vuoi cercare?--> ");
fgets(cerca,1024,stdin);
lun=strlen(cerca);
cerca=realloc(cerca,lun+1);
while(lista!=NULL && strcmp(lista->info,cerca)!=0){
lista=lista->suc;
// if(strcmp(lista->info,cerca)!=0)
}
free(cerca);
return lista;
}
data *distruggi(data*lista){
data *tmp=NULL;
while(lista!=NULL){
tmp=lista->suc;
free(lista->info);
free(lista);
lista=tmp;
}
free(tmp);
return lista;
}
int main()
{
data *lista=NULL,*lista2;
int riscontro;
int n;
printf("Quanti nomi vuoi inserire?--> ");
scanf("%d",&n);
system("cls");
fflush(stdin);
lista=crea_lista(lista);
lista2=lista;
lista2=crea_nodi(lista2,n);
stampa(lista);
lista=cerca(lista);
if(lista!=NULL){
system("cls");
printf("%s trovato",lista->info);
}
else if(lista==NULL){
printf("Nome non trovato");
}
stampa(lista);
lista=distruggi(lista);
system("pause");
return 0;
}
ho modificato quella parte e ora funziona,ma non capisco cosa sbaglio...ti posso fare un paio di domande?:)
Vincenzo1968
01-02-2013, 15:31
Dimmi ;)
Vincenzo1968
01-02-2013, 15:52
Sam, da me non funge il tuo codice. Compila, ma non funge bene bene:
http://img690.imageshack.us/img690/4207/sam333error.jpg
http://img339.imageshack.us/img339/2083/sam333error02.jpg
Se metto distrattamente un numero per la ricerca va in crash. Poi non fa inserire il primo nome.
per il fatto del primo nome credo che sia perchè lo esegui su linux... mi sembra che il comando fflush(stdin) è solo per windows..e per i numeri lo so non avevo voglia di mettere i vari if di sicurezza perchè prima volevo capire il procedimento:D comunque ho due domande da fart che mi aiuterebbero MOLTO non solo per questo programma più una extra :asd: ma non ti vorrei rompere troppo
Vincenzo1968
01-02-2013, 18:08
Non mi rompi troppo, tranquillo ;)
Eventualmente giro le domande a qualcun altro(Vicius, Banryu) :D
Scherzo. Chiedi pure. ;)
ah ok grazie:) allora la prima è:in un qualsiasi programma c'è una funzione,un ciclio o qualsiasi altra cosa che mi permette di controllare se ho liberato tutta la memoria allocata dinamicamente?poi la seconda era io con lista=lista->suc vado avanti al nodo successivo c'è un modo invece per tornare indietro?cioè il processo inverso...
Vincenzo1968
01-02-2013, 18:40
ah ok grazie:) allora la prima è:in un qualsiasi programma c'è una funzione,un ciclio o qualsiasi altra cosa che mi permette di controllare se ho liberato tutta la memoria allocata dinamicamente?poi la seconda era io con lista=lista->suc vado avanti al nodo successivo c'è un modo invece per tornare indietro?cioè il processo inverso...
Puoi fare come ho fatto io nella mia versione. dichiari due variabili di tipo int:
int nMemoriaAllocata = 0;
int nMemoriaDeallocata = 0;
Per semplicità le ho messe come variabili globali ma è una cattiva pratica di programmazione.
Dovresti dichiararle localmente nel main e passarle come parametri-puntatore alle varie funzioni che allocano/deallocano memoria.
Quindi ogni volta che allochi la memoria, incrementi la variabile nMemoriaAllocata della quantità allocata.
Ogni volta che deallochi incrementi la variabile nMemoriaDeallocata della quantità deallocata.
Alla fine, prima di uscire dal main, fai stampare i valori delle due variabili. Se non sono uguali hai dimenticato a deallocare memoria allocata in precedenza.
In, alternativa, invece di dichiarare due variabili, puoi dichiarare soltanto la variabile nMemoriaAllocata incrementandola quando allochi la memoria e decrementandola quando disallochi. Alla fine, se tutto è a posto, il valore della variabile dev'essere 0(zero).
Per quanto riguarda la seconda domanda la risposta è si: guarda il secondo programma che ho postato. Implementa una lista doppiamente concatenata in modo da potersi muovere e in avanti e all'indietro.
Se ci sono cose che ti risultano poco chiare nel mio codice chiedi pure(basta che non ricominci con la sequela di "posso?", "disturbo?". :D
;)
ok provo a vedere se riesco a capire il procedimento:)
sottovento
01-02-2013, 21:32
<cut>
ho provato a riscrivere il codice seguendo i vostri consigli...ma ancora non mi trova il nome che si inserisce precedentemente:doh: cosa non va ancora?:muro:
data *crea_nodi(data *nodi,int n)
{
char *nome=(char*)malloc(sizeof(char)*1024); // Sottovento - questa memoria la vai a perdere
int lun,i;
system("cls");
for(i=2; i<=n; i++)
{
nome=(char*)malloc(sizeof(char)*1024); // Sottovento - altro memory leak
nodi->suc=(data*)malloc(sizeof(data));
nodi=nodi->suc;
printf("%d Nome:--> ",i);
fgets(nome,1024,stdin);
lun=strlen(nome);
nome=realloc(nome,lun+1);
nodi->info=(char*)malloc(strlen(nome)*sizeof(char));
strcpy(nodi->info,nome);
}
nodi->suc=NULL;
free(nome);
return nodi;
}
Qui vai a perdere nodi un'altra volta. Ritorni sempre l'ultimo nodo, e basta.
Attenzione anche ai 2 memory leak
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.