Newsgroup: it.comp.lang.c++
Titolo: puntatori(c++)

Scusate, ho ancora un problema.
Mi spiegate perche' questa funzione non funziona?
L'elemento viene si' inserito nella lista nella posizione pos, ma poi
la lista non viene modificata, perche' il puntatore inizio non viene
modificata.
grazie ancora.
struct Slist *inserisci_in_posizione(struct Slist *inizio,int elem,int
pos){
    struct Slist *scorri;
	struct Slist *temp;
	int a=0; 
    if (pos!=0){  
		scorri = inizio;
		while (a != pos) {
			a++;
			scorri = scorri->next;
		}
		temp = (struct Slist *) malloc (sizeof(struct Slist));
		temp->elemento = elem;
		temp->next = scorri;
		scorri = temp;
		}
	else 
	{
        scorri = (struct Slist *) malloc(sizeof(struct Slist));
		scorri->elemento = elem;
        scorri->next = inizio;
		inizio = scorri;
    }
return inizio;
}

Il Sun, 12 Sep 1999 19:56:04 GMT, 
kyl...@tiscalinet.it
 (Giacomo) ha
scritto:

Il passaggio per i parametri ad una funzione viene eseguito per
valore: viene fatta una copia della variabile passata come parametro.
La funzione "lavora" sulla copia e la variabile originale non viene
modificata.
Se necessiti di un passaggio dei parametri per riferimento, in modo
che essi vengano modificati dalla funzione, nel C standard dovevi
quindi passare il puntatore al parametro (nel tuo caso avresti dovuto
passare un puntatore al puntatore al primo elemento della lista).
In C++ il problema viene risolto in maniera analoga, anche se
l'operazione viene fatta implicitamente e diventa trasparente per il
programmatore devi però modificare la funzione come segue, utilizzando
la chiamata per indirizzo
struct Slist *inserisci_in_posizione(struct Slist *(&inizio),int
elem,int pos){
Per concludere, il passaggio di parametri per indirizzo evita che
venga chiamata l'eventuale funzione distruttore alla fine della
chiamata della funzione, operazione che altrimenti viene svolta nel
passaggio di parametri per valore (con pericolosi effetti collaterali:
pensa se avessi creato una funzione distruttore per la lista che
eliminava tutta la lista: al termine ogni chiamata alla funzione che
aggiungeva elementi avresti cancellato tutta la lista!)
_____________________________________________________
Francesco Trotta
http://space.tin.it/computer/ftrotta
elimina "x_" dal mio indirizzo per le risposte

Salve Giacomo.
Hai quasi ragione, nel senso che dici che la lista non viene modificata
(ed è perfettamente vero), ma il motivo non risiede nel fatto che il
puntatore inizio non viene modificato.
Quello che succede è che viene correttamente allocato un elemento della
lista, puntato da temp, ma questo resta scollegato dalla lista, dato che
nessun elemento di questa lo indirizzerà. L'assegnazione scorri=temp non
modifica la lista, ma assegna semplicemente alla variabile scorri un nuovo
valore.
Allora nel tuo ciclo devi necessariamente fermarti all'elemento che
precederà quello da inserire:
scorri = inizio;
while (a < pos-1) {
    a++;
    scorri = scorri->next;
    }
temp = (struct Slist *) malloc (sizeof(struct Slist));
temp->next = scorri->next; //punta al prossimo
scorri->next = temp; //il precedente punta a quello inserito
Nella condizione di controllo si preferisce generalmente utilizzare (in C,
almeno, finchè non utilizzerai gli iteratori dell C++) una condizione più
"robusta", che non entra in un ciclo infinito nel caso di pos
malauguratamente negativo.
La condizione pos==0 è corretta.
Roberto Cavada

La condizione pos==0 è corretta.
Questa condizione non viene utilizzata così
	if(pos== 0)
e neanche 
	if(pos!=0)
Si utilizzano invece in maniera molto più efficiente
	if(!pos)
e
	if(pos)
Cha hanno esattamente lo stesso significato ed evitano un confronto (e
sono più eleganti).


 sono piů eleganti).
Il confronto viene fatto in ogni caso, altrimenti e' impossibile
sapere se pos e' uguale a 0 o no.
Sull'eleganza si puo' discutere, ma e' una questione di gusti.
	Mauro

         if(pos)
Fermo restando quello che ho scritto sopra a proposito di questa condizione,
ad essa si arriva indirettamente con <else>.
Per quanto riguarda la forma if(pos), è più efficiente solamente perché si
risparmiano 3 digitate (il 50%!), ma dal punto di vista del codice oggetto
generato non vi sono differenze, dal momento che certamente il compilatore
utilizzerà l'istruzione di comparazione con lo zero, senza un CMP che coinvolge
anche una sottrazione.

         if(pos)
Fermo restando quello che ho scritto sopra a proposito di questa condizione,
ad essa si arriva indirettamente con <else>.
Per quanto riguarda la forma if(pos), č piů efficiente solamente perché si
risparmiano 3 digitate (il 50%!), ma dal punto di vista del codice oggetto
generato non vi sono differenze, dato che per entrambi i casi il compilatore
utilizzerŕ CMP o, nel migliore dei casi, un AND.
Roberto Cavada

         if(pos)
Per quanto riguarda la forma if(pos), è più efficiente solamente perché si
risparmiano 3 digitate (il 50%!), ma dal punto di vista del codice oggetto
generato non vi sono differenze, dato che per entrambi i casi il compilatore
utilizzerà CMP o, nel migliore dei casi, un AND, seguite da un salto
condizionato J[N]Z.
Saluti.
Roberto Cavada

 sono più eleganti).
Nessuno garantisce che le due forme vengano tradotte diversamente dal
compilatore e normalmente un minimo di ottimizzazione da parte di
quest'ultimo le rende assolutamente identiche. L'eleganza poi è una
questione puramente soggettiva. A me sembra più chiara la prima forma in
quanto è un'esplicito confronto tra due valori mentre nella seconda
sembrerebbe quasi che pos fosse una variabile booleana.
EMG

visitare le strutture di containers indipendentemente dalle
[omissis]
Potresti fare un esempio?


 Potresti fare un esempio?
Eccolo:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector <int> vi;
    for ( int i = 1; i <= 10; ++i )
        vi.push_back( i );
    for ( vector <int>::iterator i = vi.begin(); i < vi.end(); ++i )
        cout << *i << '\n';
    cout << endl;
}
Nota le analogie con un normale puntatore che scorre un normale array:
int vi[ 10 ];
for ( int i = 1; i <= 10; ++i )
        vi[ i - 1 ] = i;
for ( int *i = vi; i < vi + 10; ++i )
    cout << *i << '\n';
e tieni presente che un vector è a lunghezza dinamica (a differenza
dell'array) e che la tecnica di cui sopra rimane inalterata qualunque
sia il contenitore (list, map, ...) e il tipo in esso contenuto.
EMG

sia il contenitore (list, map, ...) e il tipo in esso contenuto.
Mi sa che mi sto perdendo. "vector" è un tipo primitivo del C++? Ho
provato a cercare in "Thinking in C++" ma non mi sembra di trovare
niente a riguardo. Potresti essere più chiaro?
Grazie


Mi sa che mi sto perdendo. "vector" è un tipo primitivo del C++? 
E` una classe template della libreria standard.
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

niente a riguardo. Potresti essere piů chiaro?
Non sono tipi nativi del C++, si tratta dei template che ti mette
a disposizione la STL, che e' una libreria che fa comunque parte 
dello standard. Detto per inciso, penso che STL sia un monumento
alla genalita'.

 Potresti essere piů chiaro?
Se c'č qualcosa in particolare che vuoi sapere ti rispondo (ovviamente
nei limiti delle mie conoscenze).
EMG