Re: [C++] Invertire un vettore

Messaggioda vict85 » 18/09/2017, 20:13

Quello che intendevo è mostrato in questa codice:
Codice:
#include <utility>
#include <iostream>

int main(void) {
   int A[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

   std::cout << "Array iniziale = {";
   std::cout << A[0];
   for (int i = 1; i != 10; ++i) {
      std::cout << ", " << A[i];
   }
   std::cout << "}" << std::endl;

   for (int i = 0; i != 5; ++i) {
      // questa e' la funzione standard per
      // fare lo scambio di elementi
      std::swap(A[i], A[9 - i]);
   }

   std::cout << "Array invertito = {";
   std::cout << A[0];
   for (int i = 1; i != 10; ++i) {
      std::cout << ", " << A[i];
   }
   std::cout << "}" << std::endl;

   for (int i = 0; i != 5; ++i) {
      // questo e' un metodo che non usa
      // variabili d'appoggio
      A[i] ^= A[9 - i];
      A[9 - i] ^= A[i];
      A[i] ^= A[9 - i];
   }

   std::cout << "Array ri-invertito = {";
   std::cout << A[0];
   for (int i = 1; i != 10; ++i) {
      std::cout << ", " << A[i];
   }
   std::cout << "}" << std::endl;
}
vict85
Moderatore
Moderatore
 
Messaggio: 9167 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C++] Invertire un vettore

Messaggioda Cip Upupa » 19/09/2017, 14:32

Ciao vict, grazie per esserti preso il disturbo. Una domanda veloce sul tuo codice: perché scrivi std:: ogni volta anziché usare namespace std? Sono curioso...
Cip Upupa
Starting Member
Starting Member
 
Messaggio: 10 di 40
Iscritto il: 16/07/2017, 17:34

Re: [C++] Invertire un vettore

Messaggioda vict85 » 19/09/2017, 19:27

Usare namespace std inserisce i nomi del namespace sdt all'interno del namespace in cui ti trovi. Quindi perdi un po' il senso di avere un namespace. Inoltre rischi che in quel namespace sia definita una funzione o una classe con lo stesso nome. Con cose come cout è raro, ma le funzioni come swap o le classi come vector o map lo sono molto meno.
vict85
Moderatore
Moderatore
 
Messaggio: 9170 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C++] Invertire un vettore

Messaggioda mpg » 20/04/2018, 14:57

Super Squirrel ha scritto:Nel codice da te postato ci sono effettivamente molte cose che non vanno bene:

- innanzitutto non compila perchè nella riga
cin >> v[index];
la variabile index non risulta dichiarata. Il motivo è che non utilizzi le parentesi graffe per racchiudere il corpo del primo ciclo for. Le parentesi si possono anche omettere, ma in quel caso il corpo del ciclo sarà costituito solo dalla prima istruzione successiva al for (stessa cosa vale anche per if, while, else, ecc...). In ogni caso ti consiglio per una questione di leggibilità e chiarezza di usare sempre le parentesi graffe, anche quando l'istruzione è unica;
- sempre per una questione di leggibilità e chiarezza ti consiglio anche di scrivere codice in modo indentato;
- prima dichiari un array di 10 int e poi dici che il numero di elementi debba essere inferiore a 100. Il 100 al posto del 10 sarà sicuramente un errore di distrazione (infatti nell'if successivo torni ad utilizzare il 10), ma invece dire che n deve essere minore di 10 è un errore vero e proprio, perchè se la capienza dell'array è 10 anche 10 è un valore accettabile. Quindi la condizione dell'if deve essere n < 11;
- il costrutto if/else da te utilizzato non funziona in questo caso, infatti se inserisci un valore di n non valido il programma continua normalmente e non dà la possibilità di inserire un nuovo valore di n. Il costrutto che utilizzerei in questo caso è un do/while;
- per quanto riguarda il secondo for se ci pensi ti renderai conto che senza l'utilizzo di un "appoggio" la perdita di dati è inevitabile. Inoltre un array di appoggio è superfluo in quanto il problema può essere risolto utilizzando una semplice variabile d'appoggio. Visto che chiedi perchè il ciclo da te scritto non va bene, vediamo cosa succede partendo dall'inizio. Ipotizzando che n=5 avremo che per i=0 l'istruzione diventerà v[0]=v[5]. A questo punto i problemi sono due: il valore contenuto in v[0] è andato perduto irrimediabilmente ed è stato sostituito da un valore casuale in quanto v[5] si trova al di fuori del range dell'array (l'ultimo elemento infatti è v[4]). Risulta quindi inutile continuare con i=1,2,3,4;
- il return 0 è superfluo.

Dopo nel caso ti posto il modo in cui io avrei risolto l'esercizio.


EDIT:

Codice:
#include <iostream>

using namespace std;

int main()
{
    int v[10];
    int n;
    int temp;
    do
    {
        cout << "Inserire quanti elementi si desidera allocare nel vettore (max 10): ";
        cin >> n;
    }
    while(n > 10);
    for(int i = 0; i < n; i++)
    {
        cout << "v[" << i << "] = ";
        cin >> v[i];
    }
    for(int i = 0; i < n / 2; i++)
    {
        temp = v[i];
        v[i] = v[n - i - 1];
        v[n - i - 1] = temp;
    }
    for(int i = 0; i < n; i++)
    {
        cout << v[i] << " ";
    }
}


Se hai dubbi chiedi pure.


Ciao guardavo la tua soluzione, non capisco all'interno di "for(int i = 0; i < n / 2; i++)" perchè e cosa significa i< n/2.
Ti ringrazio.
mpg
Average Member
Average Member
 
Messaggio: 73 di 654
Iscritto il: 28/11/2017, 09:35

Re: [C++] Invertire un vettore

Messaggioda vict85 » 20/04/2018, 16:05

mpg ha scritto:Ciao guardavo la tua soluzione, non capisco all'interno di "for(int i = 0; i < n / 2; i++)" perchè e cosa significa i< n/2.
Ti ringrazio.


Il codice C raramente cambia significato a seconda di dove lo vedi. Se fosse stato
Codice:
int m = n/2;
for(int i =0; i<m; i++)
ti sarebbe stato più chiaro?
vict85
Moderatore
Moderatore
 
Messaggio: 9303 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C++] Invertire un vettore

Messaggioda mpg » 20/04/2018, 16:18

vict85 ha scritto:
mpg ha scritto:Ciao guardavo la tua soluzione, non capisco all'interno di "for(int i = 0; i < n / 2; i++)" perchè e cosa significa i< n/2.
Ti ringrazio.


Il codice C raramente cambia significato a seconda di dove lo vedi. Se fosse stato
Codice:
int m = n/2;
for(int i =0; i<m; i++)
ti sarebbe stato più chiaro?


No non mi sono spiegato bene io, non capisco perchè metti n/2 che funzione avrebbe in questo contesto scusami non sono ancora superferrato..
mpg
Average Member
Average Member
 
Messaggio: 74 di 654
Iscritto il: 28/11/2017, 09:35

Re: [C++] Invertire un vettore

Messaggioda mpg » 20/04/2018, 16:33

Ho letto a metà del thread la spiegazione di Squirrel, non ci sarei mai arrivato, caspita!!
mpg
Average Member
Average Member
 
Messaggio: 75 di 654
Iscritto il: 28/11/2017, 09:35

Re: [C++] Invertire un vettore

Messaggioda apatriarca » 20/04/2018, 23:37

Super Squirrel ha scritto:E' imprescindibile e adesso ti spiego il perchè. Immagina di avere due variabili x=0 e y=1, e di volerne scambiare il contenuto. Nel C++ non esiste un comando base per scambiare il contenuto di due variabili, bisogna quindi procedere per assegnazioni successive. Ora con le sole variabili x e y le uniche assegnazioni possibili sono x=y (quindi x=y=1) e y=x (quindi x=y=0), ma in entrambi i casi perderemo uno dei valori contenuti nelle variabili. Risulta quindi indispensabile l'utilizzo di una terza variabile d'appoggio che conservi temporaneamente il valore contenuto in una delle due variabili e che eviti quindi la perdita di dati.
Immagina per esempio avere un bicchiere d'acqua e uno di aranciata e di volerne scambiare il contenuto. Risulta evidente in questo caso che l'utilizzo di un terzo contenitore diventa indispensabile.

Su due variabili è possibile fare molte più operazioni che assegnare loro un valore. Prendiamo per esempio due valori interi (con infinita precisione per il momento). Se facciamo le seguenti operazioni:
Codice:
x <- x + y
y <- x - y
x <- x - y

Avremo che alla fine le due variabili sono state scambiate. Se chiamiamo infatti ogni nuova versione diversamente abbiamo che:
Codice:
x1 = x + y
y1 = x1 - y
x2 = x1 - y1

Abbiamo che y1 vale x1 - y e quindi x + y - y = x. In modo simile, x2 è uguale a x1 - y1 e quindi a x + y - x = y. Alla fine di queste operazioni avremo quindi scambiato le due variabili. Lo stesso procedimento è possibile con ogni operazione binaria che possa essere invertita. In C++ l'operazione migliore per questa operazione è lo XOR bitwise (rappresentato con ^). Il tuo codice sarà quindi in questo caso:
Codice:
x = x ^ y;
y = x ^ y;
x = x ^ y;

Il codice finale è però decisamente oscuro e in pratica più lento di quello che fa uso di una variabile intermedia. La ragione è principalmente che lo scambio può essere implementato come segue in un qualche pseudo-assembly:
Codice:
MOV r0, [x]  // sposto il valore in x nel registro r0
MOV r1, [y]  // sposto il valore di y nel registro r1
MOV [x], r1  // sposto il valore in r1 in x
MOV [y], r0  // sposto il valore in r0 in y

Nel caso degli XOR invece il codice avrà la seguente forma:
Codice:
MOV r0, [x]         // sposto il valore in x nel registro r0
MOV r1, [y]         // sposto il valore in y nel registro r1
XOR r0, r0, r1     // faccio lo XOR tra r0 e r1 e memorizzo il valore in r0
XOR r1, r0, r1     // faccio lo XOR tra r0 e r1 e memorizzo il valore in r1
XOR r0, r0, r1     // faccio lo XOR tra r0 e r1 e memorizzo il valore in r0
MOV [x], r0         // sposto il valore di r0 in x
MOV [y], r1         // sposto il valore di r1 in y

Quando si parla di C++ questo trucco è abbastanza inutile. Ha forse un senso in assembly per scambiare registri in situazioni in cui non ci sono altri registri liberi. Ma anche in questo caso fa più che altro parte del passato in cui il numero di registri era molto più limitato e comunque in situazioni molto più particolari. Credo sia poi utile per vedere come spesso sia possibile trovare soluzioni a problemi che sembravano irrisolvibili mettendo in dubbio le proprie convinzioni (che l'unica operazione utilizzabile per uno scambio fosse l'assegnazione di un valore ad esempio).
apatriarca
Moderatore
Moderatore
 
Messaggio: 5034 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Precedente

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite

cron