Newsgroup: it.comp.lang.c
Titolo: Ancora problemi con l'allocazione dinamica

Come da oggetto il seguente programma(una lista ordinata) non ne vuol 
sapere di funzionare, steso messaggio di errore:La memeoria non poteva 
essere read, etc. etc.
Aiutatemi
GRAZIE A TUTTI(non è un urlo, ma un sentito ringraziamento!)
#include <stdio.h>
#include <stdlib.h>
struct lista{
	int data;
	struct lista *next;
};
typedef struct lista LISTA;
typedef LISTA *LISTAPTR;
int menu(void);
void insert(LISTAPTR *, int);
int remove(LISTAPTR *, int);
main()
{
	LISTAPTR start=NULL;
	int i=0, n, m,y;
	do
	{
		i=menu();
		if(i==1)
		{
			printf("Digita l'elemento da inserire nella lista\n");
			scanf("%d", &n);
			insert(&start, n);
		}
		if(i==2)
		{
			printf("Digita l'elemento da rimuovere dalla lista \n");
			scanf("%d", &m);
			y=remove(&start, m);
			if(y==0)
				printf("L'elemento non e' stato trovato\n");
			else
				printf("L'elemento %d e' stato rimosso con successo\n", m);
		}
		if(i!=1 && i!=2 && i!=3)
			printf("Selezione incorretta\n");
	}
	while(i!=3);
	return 0;
}
int menu(void)	/* carica il menu */
{
	int x;
	printf("1-Inserisci un elemento nella lista\n");
	printf("2-Rimuovi un elemento dalla lista\n");
	printf("3-Esci dal programma\n");
	scanf("%d", &x);
	return x;
}
void insert(LISTAPTR *s, int p)  /*Funzione di inserzione nell'albero  */
{
	LISTAPTR create, previous, current;
	create=malloc(sizeof(LISTA));
	if(create==NULL)
		printf("Impossibile allocare memoria\n");
	else
	{
		create->data=p;
		create->next=NULL;
		current=*s;
		previous=NULL;
		while((current->data)<p && current!=NULL)
			{
				previous=current;
				current=current->next;
			}
		if(previous=NULL)
			{
				create->next=*s;
				*s=create;
			}
		if((current->data)==p)
				printf("L'elemento e' gia' stato inserito\n");
		else
			{
				previous->next=create;
				create->next=current;
			}
 
		}
 
}
int remove(LISTAPTR *s, int r) /* Funzione rimozione dall'albero */
{
	LISTAPTR temp, current, previous;
	if(r==(*s)->data)
	{
		temp=*s;
		*s=(*s)->next;
		free(temp);
		return 1;
	}
	else
	{
		while(r!=(current->data) && current!=NULL)
		{
			previous=current;
			current=current->next;
		}
		if(current!=NULL)
		{
			temp=current;
			current=current->next;
			previous->next=current;
			free(temp);
			return 1;
		}
		else
		{
			printf("L'elemento non e' stato trovato\n");
			return 0;
		}
	}
 
}
 
-- 
Zarathustra
(18/22 PO 80 B/S; S)
Parkpre, LeeCougan and Eleven munito

 int remove(LISTAPTR *, int);
Possibile che questo non ti dia nemmeno un Warning piccolo piccolo?
E ti sembra una cosa furba quella di fregarsene?
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

         if(previous=NULL)
Se tu compili con tutti i Warning on (-Wall sotto gcc, sotto win non lo
so ma sicuramente c'e' una opzione) cosa che andrebbe fatta sempre dai
principianti e almeno una volta da tutti gli altri,
il compilatore ti avrebbe certamente avvertito che l'istruzione
sopra puzza di errore. (E' un assegnamento dove di solito (if)
c'e' un test). Per esempio il mio compilatore mi dice:
warning: suggest parentheses around assignment used as truth value
cioe' mi dice che sto usando un assegnamento dove di solito c'e' un
valore booleano (cosa fattibilissima, ma meno frequente).
Inoltre (anche se penso che il tuo errore dipenda da quel = al posto di 
==) il compilatore mi dice anche che stai ridefinendo la funzione
remove che e' gia' definita per altri scopi in stdio.h
Anche se questo non e' proprio un errore e' meglio secondo me evitare
di usare nomi gia' contenuti nelle librerie.
ciao,
g.
-- 
AIUTARE= Accrescere il numero degli ingrati
(Ambrose Bierce, Il Dizionario del Diavolo)

 Aiutatemi
Non capisco bene che aiuto cerchi. Vuoi che qualcuno ti riscriva 'remove' in
modo che funzioni? O vuoi piuttosto che ti si siano dati dei consigli per
individuare gli errori? Immagino la seconda. Le mie dritte sono:
 1. usa un debugger, se puoi
 2. traccia (stampandolo, se non usi il debugger) il valore assunto da
'current'
 3. controlla i punti in cui dereferenzi 'current' e accertati che non possa
essere NULL. In particolare nella clausola del 'while' e in uno degli 'if'
successivi.
 4. Controlla bene l'istruzione 'if' che segue il ciclo 'while'!!
(BTW, 'remove' è il nome di una funzione della libreria C; meglio usare un
nome diverso.)
Max

 principianti e almeno una volta da tutti gli altri,
Per evitare problemi del genere io utilizzo, ogni volta che e'
possibile, la notazione
  if(NULL == ptrP)
Se per caso mi dovesse scappare un '=' al posto di un '==' l'istruzione
di sopra verrebbe segnalata come errore: impossibile non accorgersene.
Questo e' possibile farlo ogni volta che si deve confrontare una
costante con una variabile, ma nella maggior parte dei programmi
che ho visto questo piccolo accorgimento non e' mai usato.
Eppure... Basta poco, che ce vo'! :-)


Allora ho cambiato il nome della funzione remove e ho cambiatoanche 
l'if(..=...) con if (...==...), ma non è cambiato proproio nulla.Mi da 
sempre che un'istruzione ha fatto riferimento a una memeoria che non 
poteva essere read.P.s Non mi dà alcun warning nè in compilazione nè in 
fase di linker.


 fase di linker.
Allora. Non ho proprio voglia di leggermi il tuo codice.
(Quindi questa e' la mia ultima risposta.)
Dovresti farlo tu. Il tuo programma si incanta quando inserisci il
primo numero, mica dopo 15000 iterazioni.
Quindi, se non sai usare un debugger, ti armi di carta e penna (come 
facevo io 25 anni fa)
e simuli "passopasso" il tuo programma a mano.
Vedrai che l'errore lo trovi subito (visto che la funzione di 
inserimento contiene una decina di righe di codice).
Per dimostrarti la mia buona volonta' ti dico gratis un
errore che salta all'occhio come un canguro:
quando fai questo test o dei test simili con
l'if al posto del while
while((current->data)<p && current!=NULL)
commetti un errore gravissimo.
Infatti se per caso current e' proprio uguale a NULL il
compilatore cerchera' comunque per prima cosa di valutare
la prima condizione, ovvero
current->data < p.
Solo che se current e' NULL stai cercando di dereferenziare
un puntatore nullo, con conseguente errore.
In questi casi devi sfruttare il fatto che il C
prevede l'esecuzione dei test solo se necessari, e quindi
scrivere al contrario
(current!=NULL) && (current->data)<p
in questo modo PRIMA controlla che current non sia nullo
e SOLO se NON e' nullo allora valuta la seconda condizione.
In questo modo eviti il segmentation fault.
Questo perche' il compilatore sa che in un && entrambi
gli operandi devono essere true, e se trova il primo
falso non valuta il secondo.
Analogamente nella condizione cond1 || cond2 se
il compilatore trova vera la prima non valuta la seconda
perche' l'or ( || ) e' comunque vero.


 fase di linker.
L'errore (uno degli) e' provocato da questa sequenza
LISTAPTR start=NULL
...
insert(&start, n);
...
void insert(LISTAPTR *s, int p)  /*Funzione di inserzione nell'albero
*/
{
...
// *s Vale NULL!!!!
current=*s;
....
while((current->data)<p && current!=NULL)
{
BOOM!
BOOM che avresti evitato invertendo l'ordine dei test.
Qualche suggerimento spassionato
- Evita i typedef non sono (ancora) per te.
- Impara ad usare il debugger (io ho impiegato 2 secondi netti a
  trovare il problema, ho impiegato infinitamente di piu' a scrivere
  questo post);
- Scrivi in maniera meno incasinata EVITANDO DI SCRIVERE VARIABILI
  CHE SI CHIAMANO s, x, p ed altri monocaratteri. Il compilatore una
  variabile che si chiama pListaPP (ovvero doppio puntatore ad una
  lista che ti arriva come parametro) la produce allo stesso prezzo
  del monocarattere s.


Finalmente ho risolto il problema della lista, avevo problemi quando la 
lista era vuota, ma ora è tutto a posto.Ringrazio vivamente chi mi ha 
aiutato
