[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!