PDA

View Full Version : [C] Spiegazione porzione di codice


Peppyno89
09-02-2015, 09:51
Salve a tutti, avrei bisogno di una lucidazione su questa porzione di codice:



do
{
chiave = strstr(&testo[i], sottostringa1);
if(chiave != 0)
{
occorrenze[j] = (int)(chiave - &testo[0]);
j++;
i = (int)(chiave - &testo[0] + NS1);
}
} while (i < Ntesto && chiave != 0);



La funzione cerca una sottostringa all'interno di una stringa. Con la funzione strstr() so che si cerca la prima occorrenza di una pattern all'interno di un testo ma non ho capito bene cosa ritorna!
Ho letto che ritorna la porzione di testo, inizializzandola dalla posizione dell'occorrenza trovata... Se pure avessi capito bene, cmq restano dubbi su quello che poi avviene dopo :muro: :muro: :muro:

GRAZIE!!!:help:

ps. NS1è la dimensione della sottostringa :D

sottovento
09-02-2015, 10:47
strstr() ritorna il puntatore alla sottostringa trovata, se appunto viene trovata; altrimenti ritorna NULL (i.e. 0 nel tuo codice).

Si suppone che la variabile i sia inizializzata, anche se qui l'inizializzazione non c'e'. La variabile i va inizializzata all'indice di partenza della ricerca: se vuoi ricercare lungo tutta la stringa, deve essere messo a zero.
Ovviamente chiave e' di tipo char *.
occorrenze e' un vettore di interi, dove vengono memorizzati gli indici delle sottostringhe trovate. Immagino quindi che anche j sia inizializzato a 0 e che "occorrenze" sia grande a sufficienza, perche' questo codice non controlla assolutamente se c'e' abbastanza spazio per memorizzare.



do
{
// Cerca la prossima occorrenza di sottostringa1 a partire dall'indice i
chiave = strstr(&testo[i], sottostringa1);
if(chiave != 0) // Se ho trovato qualcosa
{
// Siccome chiave e' il puntatore all'inizio delle stringa trovata
// all'interno del testo e testo e' il puntatore al primo elemento,
// la loro differenza da' ovviamente l'indice di partenza dell'elemento
// trovato.
occorrenze[j] = (int)(chiave - &testo[0]);
// NOTA - questa e' ovviamente equivalente a:
occorrenze[j] = (int)(chiave - testo);
// ma scritta cosi' e' troppo semplice, quindi si corre il rischio che sia
// comprensibile. Meglio complicare le cose. ;)

j++; // Passa al prossimo elemento di occorrenze, dove mettere
// il prossimo valore

i = (int)(chiave - &testo[0] + NS1); // Siccome ho gia' trovato questo elemento, il punto di partenza viene spostato avanti per la ricerca successiva.
// Anche in questo caso avrebbe potuto scrivere:
i = (int)(chiave - testo + NS1);
// oppure
i = occorrenze[j-1] + NS1; // magari se la si sposta prima di j++ si evita il -1

}
} while (i < Ntesto && chiave != 0); // Ripete fino a quando non arriviamo a fine testo o quando non e' piu' trovato nulla



NOTA - nel testo e' scritto &testo[0] per avere l'indirizzo del primo elemento della stringa. Siccome la stringa in C e' definita come puntatore al primo elemento dell'area di memoria, questa e' equivalente a testo.

Vista la proprieta' commutativa dell'addizione (siamo in un gruppo abeliano, quindi a + b = b + a) e sapendo che l'indicizzazione viene risolta con un'addizione, e' chiaro che

testo[0] == testo + 0
per la proprieta' commutativa:
testo + 0 = 0 + testo, quindi ritraducendolo:
0[testo] = testo[0].
Ovviamente 0 e' uno scalare, ma posso sempre farne il cast:

((char *)0)[testo], quindi prenderne l'indirizzo e metterlo nel codice:


occorrenze[j] = (int)(chiave - &((char *)0)[testo]);


Ad un'occhiata veloce, un possibile manutentore del codice sara' perplesso, quindi puo' andar bene :D

Scherzavo. Tutto questo per dire che si, il codice va bene ma certi giochi con i puntatori e' sempre meglio evitarli, se non sono strettamente necessari