PDA

Visualizza la versione completa : [C++] Puntatori ad array


djanthony93
01-02-2013, 14:08
char ultimaLettera(stringa s)
{
while(*s++);
return *(s);
}


stringa è un array di caratteri, la s che gli passo è un nome, quello che vorrei fare è ritornare l'ultima lettera del nome, ma naturalmente non funziona, cosa c'è di sbagliato?

EDIT:



char ultimaLettera(stringa s)
{
return *(s+(strlen(s)-1));
}


così mi ritorna l'ultima lettera, il problema è che ho una serie di nomi... c'è un modo senza usare lo strlen?

MItaly
01-02-2013, 15:07
char ultimaLettera(stringa s)
{
while(*s++);
return s[-2];
}

... a te capire perché funziona. :)

djanthony93
01-02-2013, 15:49
non riesco a capire quando finisce di incrementare il puntatore :S
scusa non finisce di incrementare il puntatore quando trova '\0'?

MItaly
01-02-2013, 16:17
Supponiamo di chiamare ultimaLettera sulla stringa "parola".


s --+
V
+---+---+---+---+---+---+----+ · · ·
| p | a | r | o | l | a | \0 | ·
+---+---+---+---+---+---+----+ · · ·

finché s punta ad una lettera valida non succede nulla di che.
Ora esaminiamo il caso in cui s sia arrivato al \0:


s ---------------------------+
V
+---+---+---+---+---+---+----+ · · · · ·
| p | a | r | o | l | a | \0 | · ·
+---+---+---+---+---+---+----+ · · · · ·

qui viene valutata l'espressione


*s++

che restituisce 0 (facendo terminare il while) ma incrementa s; per cui, all'uscita del while la situazione è la seguente:


s -------------------------------+
V
+---+---+---+---+---+---+----+ · · · · ·
| p | a | r | o | l | a | \0 | · ·
+---+---+---+---+---+---+----+ · · · · ·

ovvero, s punta alla "posizione fantasma" immediatamente dopo il carattere di fine stringa†.

A questo punto, per tornare all'ultimo carattere "vero" bisogna tornare indietro di due posizioni


s -------------------------------+
|
s-2 --------------------+ |
V V
+---+---+---+---+---+---+----+ · · · · ·
| p | a | r | o | l | a | \0 | · ·
+---+---+---+---+---+---+----+ · · · · ·

da cui:


return s[-2];

(per chiarezza: s[-2] è uguale per definizione a *(s-2))

Nota comunque che questo codice non considera il caso speciale di una stringa vuota (ovvero, contenente solo il terminatore); in tal caso, si restituirebbe un puntatore non valido; per ovviare a questo problema, si può aggiungere un caso speciale all'inizio:


char ultimaLettera(stringa s)
{
if(!*s)
return 0;
while(*s++);
return s[-2];
}


-----

† nota che questo è ammesso dallo standard - si garantisce che l'aritmetica dei puntatori funzioni correttamente fino ad un elemento dopo l'ultimo, in modo da poter esprimere i range come intervalli semiaperti [inizio, fine).

djanthony93
01-02-2013, 16:42
!*s cosa vuol dire?

Grazie infinite, chiarissimo!

MItaly
01-02-2013, 17:51
Originariamente inviato da djanthony93
!*s cosa vuol dire?
*s dereferenzia s, ottenendone il primo carattere; ! è l'operatore di not booleano - quanto segue viene convertito in un bool (0=>false; tutto il resto=>true) e negato.
Quindi, if(!*s) è come dire if(s[0]==0).

djanthony93
01-02-2013, 19:01
Ok capito, ma nel while se avessimo fatto semplicemente "s++"?

MItaly
01-02-2013, 19:11
Originariamente inviato da djanthony93
Ok capito, ma nel while se avessimo fatto semplicemente "s++"?
Eh? :confused:

oregon
01-02-2013, 19:24
Originariamente inviato da djanthony93
Ok capito, ma nel while se avessimo fatto semplicemente "s++"?

Questo

while(*s++);

con il carattere * controlla il contenuto della locazione puntata dal puntatore, mentre così

while(s++);

controlli il valore del puntatore e non dei caratteri della stringa ...

Capito la differenza?

djanthony93
01-02-2013, 21:41
Sì, sto facendo un po' di confusione, alla fine sia "*s" che "s" non sono due puntatori? La differenza è che uno punta al contenuto e l'altro all'allocazione in memoria? Cioè l'indirizzo?

Loading