[C++] Insert/Delete di elementi di un array di interi
A lezione abbiamo visto due algoritmi basilari per gli array, ma ho alcuni dubbi sul codice:
- Insert:
che ho modificato in
Ho modificato:
- la condizione dell'if, scrivendo r+1<=N (perché posso aggiungere un elemento anche quando r=N-1) e pos<=r (perché così posso aggiungere un elemento anche quando pos=r)
- Delete:
(Qui credo che ci sia proprio un errore)
che ho modificato in
Ho modificato:
- la condizione dell'if, scrivendo r-1>=0,perché posso cancellare un elemento anche se r=1: non potrei se fosse 0. Ottengo un vettore con riempimento r=0, ma non credo sia un problema.
- la condizione di terminazione del for, scrivendo i-1, perché se i=r-1, eseguo v[r-1]=v[r]: nel caso migliore potevo risparmiare quest'ultima iterazione, ma se r=N, vado ad accedere a un'area di memoria che non è assegnata all'array, no?
Eppure non ottengo alcun errore a runtime, e in v[N-1] viene copiato 0 (sempre?)
Analogamente, se provo a scrivere su v[N] non ottengo alcun errore, né su v[N+1], ma solo per valori molto maggiori di N (circa N+150).
Le modifiche che ho fatto sono giuste?
P.S.: N è la cardinalità del vettore
- Insert:
int insertVettore(vettore v, int &r, int pos, int elem) { int i, exit; if(r+1<N && pos>=0 && pos<r) { for(i=r;i>pos;i--) v[i]=v[i-1]; v[pos]=elem; r++; exit=1; } else exit=0; return exit; }
che ho modificato in
int insertVettore(vettore v, int &r, int pos, int elem) { int i, exit; if(r+1<=N && pos>=0 && pos<=r) { for(i=r;i>pos;i--) v[i]=v[i-1]; v[pos]=elem; r++; exit=1; } else exit=0; return exit; }
Ho modificato:
- la condizione dell'if, scrivendo r+1<=N (perché posso aggiungere un elemento anche quando r=N-1) e pos<=r (perché così posso aggiungere un elemento anche quando pos=r)
- Delete:
(Qui credo che ci sia proprio un errore)
int deleteVettore(vettore v, int &r, int pos) { int i, exit; if(r-1>0 && pos>=0 && pos<r) { for(i=pos;i<r;i++) v[i]=v[i+1]; r--; exit=1; } else exit=0; return exit; }
che ho modificato in
int deleteVettore(vettore v, int &r, int pos) { int i, exit; if(r-1>=0 && pos>=0 && pos<r) { for(i=pos;i<r-1;i++) v[i]=v[i+1]; r--; exit=1; } else exit=0; return exit; }
Ho modificato:
- la condizione dell'if, scrivendo r-1>=0,perché posso cancellare un elemento anche se r=1: non potrei se fosse 0. Ottengo un vettore con riempimento r=0, ma non credo sia un problema.
- la condizione di terminazione del for, scrivendo i
Eppure non ottengo alcun errore a runtime, e in v[N-1] viene copiato 0 (sempre?)
Analogamente, se provo a scrivere su v[N] non ottengo alcun errore, né su v[N+1], ma solo per valori molto maggiori di N (circa N+150).
Le modifiche che ho fatto sono giuste?
P.S.: N è la cardinalità del vettore
Risposte
Direi che le correzioni sono corrette in entrambi i casi. Personalmente scriverei però alcune condizioni diversamente, per esempio \(r < N\) al posto di \(r + 1 \leq N\) e \(r \geq 1\) invece che \(r - 1 \geq 0\).
A questo punto i codici sono corretti, ma ho alcune note puramente stilistiche:
1. Non c'è alcuna ragione di dichiarare le variabili all'inizio della funzione e dichiarare tali variabili quando vengono utilizzate aumenta spesso la leggibilità del codice. Impedisce inoltre spesso di dimenticarsi di inizializzarle o di riutilizzarle (era una limitazione esistente in vecchie versioni del C e poi eliminata nello standard del 1999, ma non è mai stata presente in C++).
2. Si può avere più di un return nella tua funzione. La variabile exit è quindi del tutto inutile.
3. In C++ esiste il tipo bool per rappresentare valori che possono essere veri o falsi. Siccome il valore di ritorno della funzione può essere solo 0 e 1 avrebbe più senso usare questo tipo come valore di ritorno. Rende più chiaro il significato del valore restituito in quanto è immediatamente ovvio rappresenti il successo o meno della funzione. Un valore intero può invece avere altri significati, come la dimensione o il valore che è stato rimosso dall'array o altro.
4. Anche se il C++ permette di non mettere le parentesi credo sia sempre meglio farlo. Non è un grande sforzo da parte del programmatore ma può salvare da alcuni errori.
Avrei quindi insomma scritto i codici come segue:
A questo punto i codici sono corretti, ma ho alcune note puramente stilistiche:
1. Non c'è alcuna ragione di dichiarare le variabili all'inizio della funzione e dichiarare tali variabili quando vengono utilizzate aumenta spesso la leggibilità del codice. Impedisce inoltre spesso di dimenticarsi di inizializzarle o di riutilizzarle (era una limitazione esistente in vecchie versioni del C e poi eliminata nello standard del 1999, ma non è mai stata presente in C++).
2. Si può avere più di un return nella tua funzione. La variabile exit è quindi del tutto inutile.
3. In C++ esiste il tipo bool per rappresentare valori che possono essere veri o falsi. Siccome il valore di ritorno della funzione può essere solo 0 e 1 avrebbe più senso usare questo tipo come valore di ritorno. Rende più chiaro il significato del valore restituito in quanto è immediatamente ovvio rappresenti il successo o meno della funzione. Un valore intero può invece avere altri significati, come la dimensione o il valore che è stato rimosso dall'array o altro.
4. Anche se il C++ permette di non mettere le parentesi credo sia sempre meglio farlo. Non è un grande sforzo da parte del programmatore ma può salvare da alcuni errori.
Avrei quindi insomma scritto i codici come segue:
bool insertInVector(int v[N], int &size, int pos, int elem) { if (size < 0 || size >= N || pos < 0 || pos > size) { return false; } for (int i = size; i > pos; --i) { v[i] = v[i - 1]; } v[pos] = elem; size += 1; return true; } bool removeFromVector(int v[N], int &size, int pos) { if (size < 1 || pos < 0 || pos >= size) { return false; } for (int i = pos + 1; i < size; i++) { v[i - 1] = v[i]; } size -= 1; return true; }
Perfetto, grazie mille!
