[C++]Esercizio scambio di variabili
Mi potete aiutare, o dire dove sbaglio, in questo esercizio (come ho scritt nel titolo, finora abbiamo fatto solo variabili di tipo int):
Il testo dell'esercizio è questo:
Scrivere un programma che legge in ingresso due valori interi e li memorizza in due variabili e lo stampa sullo schermo, quindi scambia il contenuto delle variabili e lo stampa sullo schermo.
N.B.: Senza utilizzare nessuna variabile di appoggio!
Linguaggio C++
Con la variabili di appoggio non ho avuto nessun problema, ma adesso che non dobbiamo più usarla mi esce l'errore che manca input... allora il mio file sorgente è questo:
#include
using namespace std;
main ()
{
int i, j;
cout<<"inserisci il valore di i";
cin>>i;
cout<<"inserisci il valore di j";
cin>>j;
i=j;
j=i;
cout<<"Dopo lo scambio:i="< return 0;
}
Credevo di averlo risolto, ma invece il problema è che dopo lo scambio il valore delle due variabili è lo stesso i=j: credo quindi che sia un problema di definizione... Come fareste voi senza usare l'appoggio per scambiare le variabili (solo tipo int per ora)?
Grazie... e scusate le tante modifiche!!!!
Il testo dell'esercizio è questo:
Scrivere un programma che legge in ingresso due valori interi e li memorizza in due variabili e lo stampa sullo schermo, quindi scambia il contenuto delle variabili e lo stampa sullo schermo.
N.B.: Senza utilizzare nessuna variabile di appoggio!
Linguaggio C++
Con la variabili di appoggio non ho avuto nessun problema, ma adesso che non dobbiamo più usarla mi esce l'errore che manca input... allora il mio file sorgente è questo:
#include
using namespace std;
main ()
{
int i, j;
cout<<"inserisci il valore di i";
cin>>i;
cout<<"inserisci il valore di j";
cin>>j;
i=j;
j=i;
cout<<"Dopo lo scambio:i="< return 0;
}
Credevo di averlo risolto, ma invece il problema è che dopo lo scambio il valore delle due variabili è lo stesso i=j: credo quindi che sia un problema di definizione... Come fareste voi senza usare l'appoggio per scambiare le variabili (solo tipo int per ora)?
Grazie... e scusate le tante modifiche!!!!
Risposte
In un programma reale la risposta corretta è usare la funzione offerta dalla libreria standard std::swap():
Però immagino che questo esercizio sia volto a familiarizzare con le variabili, quindi dovrai scrivere tu l'equivalente di una funzione swap*.
La tua soluzione non funziona perché una volta che assegni ad i il valore di j, il valore originale di i non è più accessibile. Devi fare in modo da memorizzare entrambi i valori di i, j dentro un'unica variabile, e devi poter riottenerli entrambi.
Il metodo più famoso utilizza l'operatore logico "o esclusivo", simbolo ^:
Nota che non funziona se a == b (ma a quel punto non devi già fare niente, non ha senso scambiare due valori uguali).
Una variante, che forse è un po' più intuitiva, è usare somma e sottrazione:
Nota che questo metodo funziona solo per tipi unsigned, perché una delle somme potrebbe sforare il massimo (o minimo) valore possibile (overflow/underflow). In quel caso i tipi unsigned lavorano in aritmetica modulare e il risultato è corretto, mentre per i tipi signed un overflow/underflow ha risultato indefinito.
* Ma in un programma reale usa sempre std::swap()! È più chiara, e per alcuni tipi di dati complessi è molto più veloce di scambiare i valori esplicitamente. Per la cronaca std::swap() usa una variabile d'appoggio (anche se nell'ultima versione del C++ è di un tipo particolare che la rende più rapida anche in molti altri casi, ma questo è un argomento abbastanza avanzato).
#include <algorithm> ... int a = 3; int b = 8; std::swap(a, b); // Ora a == 8, b == 3
Però immagino che questo esercizio sia volto a familiarizzare con le variabili, quindi dovrai scrivere tu l'equivalente di una funzione swap*.
La tua soluzione non funziona perché una volta che assegni ad i il valore di j, il valore originale di i non è più accessibile. Devi fare in modo da memorizzare entrambi i valori di i, j dentro un'unica variabile, e devi poter riottenerli entrambi.
Il metodo più famoso utilizza l'operatore logico "o esclusivo", simbolo ^:
if (a != b) { a = a ^ b; b = b ^ a; a = a ^ b; }
Nota che non funziona se a == b (ma a quel punto non devi già fare niente, non ha senso scambiare due valori uguali).
Una variante, che forse è un po' più intuitiva, è usare somma e sottrazione:
unsigned int a = 3; unsigned int b = 8; a = a + b; // Ora a == 3 + 8 b = a - b; // Ora b == a - 8 == (3 + 8) - 8 == 3 a = a - b; // Ora a == a - b == (3 + 8) - 3 == 8 // a == 8, b == 3
Nota che questo metodo funziona solo per tipi unsigned, perché una delle somme potrebbe sforare il massimo (o minimo) valore possibile (overflow/underflow). In quel caso i tipi unsigned lavorano in aritmetica modulare e il risultato è corretto, mentre per i tipi signed un overflow/underflow ha risultato indefinito.
* Ma in un programma reale usa sempre std::swap()! È più chiara, e per alcuni tipi di dati complessi è molto più veloce di scambiare i valori esplicitamente. Per la cronaca std::swap() usa una variabile d'appoggio (anche se nell'ultima versione del C++ è di un tipo particolare che la rende più rapida anche in molti altri casi, ma questo è un argomento abbastanza avanzato).
Sinceramente lo trovo un esercizio di utilità limitata, persino la versione con gli or alle volte è più lenta della versione con la variabile di appoggio (per una descrizione più accurata si veda su wiki http://en.wikipedia.org/wiki/XOR_swap_algorithm). La maggior ragione per non farlo è che i compilatori sanno bene come ottimizzare un codice standard come uno scambio con una variabile temporanea costante e che alcune architetture possiedono un'istruzione per lo scambio, a quel punto richiamare quella istruzione, nel caso degli interi, ha molto più senso che usare lo scambio con gli or.
Grazie Claudio86: alla fine ho ricontrollato tutto e ci sono riuscita. Grazie infiinete!