PDA

Visualizza la versione completa : [C] File header e regole di visibilità


ilmo lesto
22-06-2007, 13:29
premetto che ho già dato un'occhiata alle *pillole* stickate qui in alto sulla programmazione modulare, nonostante ciò non riesco a venire a capo del mio problema.
Vorrei capire come rendere il mio programma "modularizzato" al punto giusto... non sono molto pratico in materia visto che è la prima volta che mi si presenta questa esigenza, quindi siate comprensivi con me :D

parto dandovi qualche informazione utile riguardo al programma.

ho praticamente finito di scrivere il codice e vorrei capire come utilizzare il file header.h da me creato contenente i prototipi di funzione, la definizione di varie strutture a alcune direttive del preprocessore.

Ho suddiviso il programma in quattro file + un header file, ma non so se è la maniera giusta di procedere.

senza dilungarmi troppo su quello che fa il mio pragramma, vi basta sapere che il main chiama essenzialmente due funzioni dal nome: firstPass e secondPass.

All'interno del main ho inserito tutte le funzioni che hanno il compito di aprire file (uno in scrittura e uno in lettura) digitati da linea di comando dall'utente. Inoltre nel main è contenuta pure la funzione secondPass(in totale, il main è composto da circa 300 righe di codice).
una volta aperto il file in lettura viene chiamata la funzione firstPass.

Tale funzione è quella che fa praticamente tutto. è una funzione molto lunga e articolata, tanto che ho pensato di riservargli un file a parte. Per ora è composta da circa 800 righe, ma se aggiungo (come farò) nuove funzionalità le righe aumenteranno...

il compito della funzione firstPass è essenzialmente quello di analizzare le singole parole che compongo il file aperto in lettura e, dopo le opportune verifiche di validità della stringa, verranno chiamate da firstPass una serie di altre funzioni (tramite uno switch), in base al contenuto della stringa. le funzioni che possono essere chiamate sono sette.
accade però che due di queste funzioni ne chiamano altre che servono a completare il compito svolto dalla funzione in questione.

per esempio, una delle funzioni contenute in firstPass è quella per il calcolo di espressioni. Essa quindi si avvale di una serie di altre funzioni che implementano l'algoritmo per il calcolo in notazione polacca inversa. Ho pensato dunque di sistemare queste funzioni in un file a parte che ho chiamato polishcalc.c

stesso discorso vale per un'altra funzione in firstPass (con conseguente creazione di un altro file.c per contenere tutte le funzioni correlate.

ricapitolando... l'algoritmo del mio programma è (molto sinteticamente) il seguente:



apro il file di testo
finchè non raggiungo la fine del file
passo una riga del file alla funzione firstPass
scorro le parole contenute nella riga
in base al tipo di parola eseguo una delle seguenti funzioni
func1

func2 //questa è la mia funzione polishcalc
che accede ad un file
contenente le funzioni di cui ha bisogno

func3 //questa è un'altra
funzione che accede ad un file
appositamente creato per lei

func4
...ecc

verifico che il file sia stato totalmente letto
chiudo il file
apro un nuovo file in scrittura
eseguo la funzione secondPass
scrivo i risultati sul file aperto in scrittura
chiudo il file
fine del main



per la funzione func2 quindi ho creato un nuovo file contenente tutte le funzioni necessarie per il calcolo in notazione polacca.

il mio problema è come gestire tutti questi file seguendo delle corrette regole di visibilità.

per ora mi sono limitato ad inserire TUTTI i prototipi di funzione in un unico file header.h e ho incluso in ogni file del programma l'header.h. Ma se io volessi che le funzioni contenute nel file polishcalc fossero visibili solamente al file firstPass (visto che chi ne usufruisce è solamente lui) come dovrei procedere?

mi scuso in anticipo per questa lungaggine, e non vogliatemene se ho detto un sacco di cavolate o se non sono riuscito a spiegarmi... io cel'ho messa tutta :D

se avete anche qualche link di riferimento (io ho trovato ben poco) ve ne sarei grato :smack:

MItaly
22-06-2007, 13:34
Normalmente si associa ad ogni file .c un file .h che ne contiene i prototipi e che viene incluso dal suo .c e dagli altri .c che necessitano delle funzioni in esso definite. Spesso inoltre si aggiunge un .h che contiene le inclusioni degli header standard che devono essere inclusi in tutti i .c; pertanto di solito ogni .c inizia con


#include "stdafx.h" /*file che contiene le inclusioni comuni a tutti i .c; il nome che uso qui è quello usato di default da MSVC++ per le intestazioni precompilate*/
#include "nomefilec.h" /*ad esempio, se questo file è "main.c" verrà incluso "main.h", che ne contiene tutti i prototipi*/
#include "altrofile.h" /*ad esempio, firstPass.h, se main.c richiamerà le funzioni di firstPass.c*/
.

ilmo lesto
22-06-2007, 15:31
un'altra cosa che non capisco in riferimento alla mini guida sulla programmazione modulare è la compilazione condizionale per ciò che concerne il file header.

riporto la parte che non mi è chiara



Per ogni modulo dobbiamo definire un file .h e un file .c

Il file .h inizierà sempre con una cosa del tipo



#ifndef _MIOFILE_H
#define _MIOFILE_H

.....


#endif



per evitare che venga incluso più di una volta durante la fase di compilazione.

nel file .h va inserita la definizione della struttura dati e il prototipo di tutte le funzioni pubbliche collegate alla struttura dati.


a che cosa si rifrerisce quel _MIOFILE_H?

che cosa vuol dire che in questo modo l'header.h non rischia di venire incluso più di una volta?

oregon
22-06-2007, 15:59
Quella e' una semplice costante. La sua definizione e il relativo controllo serve, appunto, a fare in modo che il codice venga preso in considerazione dal compilatore solamente una volta.

ilmo lesto
22-06-2007, 16:03
Originariamente inviato da oregon
Quella e' una semplice costante. La sua definizione e il relativo controllo serve, appunto, a fare in modo che il codice venga preso in considerazione dal compilatore solamente una volta.

ma quindi è buona norma iniziare ogni file di header in quel modo?

oregon
22-06-2007, 16:07

ilmo lesto
22-06-2007, 18:20
Originariamente inviato da MItaly
Normalmente si associa ad ogni file .c un file .h che ne contiene i prototipi e che viene incluso dal suo .c e dagli altri .c che necessitano delle funzioni in esso definite.

allora ho proceduto esattamente nel modo da te citato, ma non capisco una cosa.

diciamo che ho un main.c con il suo rispettivo main.h
un file1.c con file1.h

eccetera

in ciascun header sono contenuti i prototipi delle funzioni che vengono utilizzate all'interno del file.

ora mi domando: come mai riesco ad utilizzare ugualmente una funzione il cui prototipo è dichiarato per esempio in main.h (che includo in main.c) in un altro file che non centra nulla con la suddetta funzione? spero di essermi spiegato...

MItaly
22-06-2007, 18:25
in ciascun header sono contenuti i prototipi delle funzioni che vengono utilizzate all'interno del file.
Occhio... in ciascun header devi inserire i prototipi delle funzioni che vengono definite all'interno del file!

ilmo lesto
22-06-2007, 18:33
Originariamente inviato da MItaly
Occhio... in ciascun header devi inserire i prototipi delle funzioni che vengono definite all'interno del file!

:dhò: :dhò: immaginavo di aver fatto una ca*zata di questo tipo...
però non mi torna ugualmente una cosa.

io ho il main.c al cui interno viene chiamata una funzione definita in un altro file, poniamo file1.c... a questo punto come fa il main.c a conoscere tale funzione se il prototipo è dichiarato in file1.h?

MItaly
22-06-2007, 18:48
Infatti dal main.c puoi richiamare la funzione dichiarata in file1.h e definita in file1.c solo se in main.c includi file1.h. A questo punto il compilatore quando compila main.c conosce il numero e il tipo dei parametri accettati dalla funzione, senza però avere il codice della funzione stessa. Perciò con il prototipo effettua i vari controlli di sintassi e segna nel modulo oggetto (che sotto Windows ha estensione .obj) che c'è un link non risolto a quella funzione. Alla fine il linker, nel momento in cui deve mettere insieme i moduli oggetto, collega tutte le chiamate a quella funzione non risolte al codice di quella funzione che trova effettivamente nel modulo oggetto di file1.c (che si chiamerà probabilmente file1.obj).

Loading