Laboratorio di programmazione

Motore di ricerca 1

Motore di ricerca1

Analizziamo questo programma, ovvero un motore di ricerca locale per file di testo interamente scritto in C. Nel file esterno elenco.txt , è stato scritto l' elenco dei file da indicizzare.

Vi è poi il file dizionaro.txt che contiene l' elenco di tutte le parole che non vogliamo indicizzare

All' inizio del programma vengono inserite con la direttiva include le librerie standard e la libreria utente libre.h, nella quale sono inserite le definizioni delle funzioni , costanti ecc…

Analizziamo meglio la libreria utente libre.h. Troviamo inizialmente la dichiarazione di alcune costanti:

E' poi definita una struttura, utilizzata per creare gli elementi di una lista.

Dopodiché vi sono le dichiarazioni delle funzioni che verranno utilizzate nel programma. Per esempio la funzione n_parole che conta quante parole ci sono in un file di testo, la funzione testo_riga che restituisce l'ennesima parola contenuta in un file di testo, ecc… Torniamo al listato principale, e dopo aver incontrato i prototipi delle funzioni citate sopra,

entriamo nel main del nostro programma.

Viene dichiarato un array di puntatori (argv). Ogni puntatore punterà ad una parola del nostro testo da indicizzare. Quindi il nostro testo potrà contenere al massimo 10024 parole (costante MAX_NUM_TOKEN). Vengono poi dichiarati alcuni array, delle variabili, degli oggetti file e infine un array di puntatori a strutture di tipo elemento. Vengono in questo modo create 53 liste. Con il ciclo for successivo, inizializiamo queste liste a null in modo da ottenere 53 liste vuote. Per capire bene questo passaggio guarda l' esercizio10. Inizia poi la fase di indicizzazione.

Apriamo il file elenco.txt in lettura, è logico che se questo file non esistesse, il programma non avrebbe motivo di esistere. Viene comunque verificato che il file d' elenco esista. Se non dovesse esistere il programma si interromperebbe stampando il messaggio indicato sopra. Viene poi aperto un grosso ciclo for:

In questo ciclo for c'è tutto quanto verrà eseguito su ogni file indicato in elenco (file1, file2 ecc……..) durante la fase di indicizzazione. Compare inizialmente la funzione n_parole, definita in libre.h, che restituisce il numero di parole lette in elenco.txt, e quindi il numero di file da indicizzare. Questo numero indica la condizione di uscita dal ciclo, e quindi quando l' indice i sarà uguale al numero di file da indicizzare, significa che tutti i file indicati nell' elenco sono stati interamente indicizzati. Il contatore indica quanti cicli vengono compiuti in questo ciclo for e quindi quante pagine sono state indicizzate. Proseguendo leggo con la funzione fscanf la prima riga del file elenco.txt, e quindi "file1.txt" e assegno questa stringa all' array buff. Viene poi aperto il file sito.txt in scrittura, e viene verificato che non ci siamo stati errori nel creare il file. Scrivo nel file appena creato l' intero testo del file indicato da buff. Attualmente in buff è memorizzata la stringa file1.txt.

Viene utilizzata la funzione testostringa, una funzione che legge il contenuto di un file di testo e lo inserisce interamente su una stringa. Quindi l' intero contenuto di file1.txt (file1.txt è la stringa attualmente memorizzata in buff) viene stampato nel file sito.txt. Il file sito.txt viene poi chiuso e ne viene verificata la correttezza in chiusura. A questo punto vengono chiamate tre funzioni da libreria utente.

La prima funzione, la parser, manipolata (con l'utilizzo della funzione strtok) la stringa acquisita dal file di testo sito.txt, in modo da separarla in parole. Questa funzione come si può vedere dal prototipo , ha come argomento un array di puntatori. Le viene infatti passato l'array di puntatori argv. Il testo contenuto in sito.txt viene diviso in parole, e ogni puntatore dell' array, punterà ad una e solo una di queste parole. Grazie alla funzione strtok viene anche eliminata la punteggiatura. La seconda funzione , make_dictionary, confronta le parole (tramite l' array di puntatori creato in precedenza) con quelle contenute nel dizionario.txt. Se trova una parola uguale ad una parola contenuta nel dizionario scala l' array di una posizione e pone l' ultimo puntatore a null. Infine la funzione confronta, confronta tra di loro le parole indicizzate, per mezzo dell' array di puntatori ottenuto dalla precedente funzione. Se trova due parole uguali scala l' array di una posizione e pone l' ultimo puntatore a null. Facendo cosi vengono eliminate tutte le ripetizioni e non vi saranno parole uguali indicizzate due volte. Tutte queste funzioni restituiscono il numero di parole indicizzate. Ricapitolando, queste tre funzioni prendono il testo scritto in sito.txt, lo dividono in parole, ne eliminano le parole "inutili" e le ripetizioni. Quello che otteniamo è quindi un elenco di parole chiave. Ora dobbiamo allocare da qualche parte in memoria queste parole chiave.

In questo ciclo for, prendo ogni parola, ne faccio la somma, modulo 53, dei codici ASCII dei caratteri che compongo la parola. Il numero che ottengo mi indica in quale lista devo aggiungere la parola indicizzata. (vedi esercizio10 sulle liste). La funzione aggiugicotatto, richiede la lista nella quale voglio aggiungere la parola, una variabile intera e un puntatore. L' intero che gli passiamo è il contatore che poi nel corpo della funzione viene assegnato alla variabile inf ( all' interno della struttura della lista) ed indica il numero della pagina in cui è stata letta la parola. Il puntatore che gli passiamo è invece proprio quello che punta alla parola indicizzata, e questo viene assegnato sempre nella struttura della lista, al puntatore denominato "parola". Facciamo un esempio pratico, prendiamo la parola "molto". La sum_of_ascii restituisce il numero 25. Quindi nella lista[25] verrà creato un nuovo elemento. In questo nuovo elemento verrà assegnato alla variabile inf, il numero 1 (l' attuale valore del contatore), mentre il puntatore parola verrà fatto puntare alla stringa "molto". Siamo cosi arrivati alla fine del ciclo for aperto inizialmente. Si ritorna all' inizio e se le condizioni d' uscita dal ciclo non sono verificate, viene nuovamente incrementato il contatore, e viene memorizzata su buff, la seconda riga contenuta nell' elenco.txt (file2.txt) e cosi via….. Una volta indicizzati tutti i file si passa alla fase di ricerca.

La fase di ricerca è molto più semplice. Si richiede la parola da ricercare, che viene poi inserita tra gli argomenti nella funzione ricercaContatto. Della parola da ricercare inserita dall' utente, ne verrà fatta la somma dei codici ASCII e poi il modulo, ottenendo cosi la lista in cui andare a cercare la parola. Molto più veloce che confrontare la parola inserita dall' utente con tutte quelle indicizzate.























































Tutto quanto riportato in questa pagina è a puro scopo informativo personale. Se non ti trovi in accordo con quanto riportato nella pagina, vuoi fare delle precisazioni, vuoi fare delle aggiunte o hai delle proposte e dei consigli da dare, puoi farlo mandando un email. Ogni indicazione è fondamentale per la continua crescita del sito.