Introduzione alla programmazione
Da Hacknowledge.
Indice |
[modifica] Algoritmi e Programmi
Prima di parlare della sintassi e semantica di qualsiasi linguaggio di programmazione, è opportuno e buona norma iniziare con alcuni concetti basilari e alcune premesse. In generale,prima di sviluppare un programma,un utente ha un problema da trasformare in algoritmo. Quindi,noi inizieremo proprio da questa triade :
Problema -> Algoritmo -> Programma
Definiamo il nostro problema quindi in:
- Dati iniziali( input )
- Dati intermedi( se necessari )
- Dati finali ( output )
- Definizione di un insieme di passi logici che trasformano i dati iniziali in dati finali.
Il risultato sarà un algoritmo.
[modifica] Algoritmi
Ma cos’è un algoritmo? Un algoritmo non interessa l’informatica sempre. Esso è un concetto a parte. Gli algoritmi nacquero intorno all’anno 1000 per merito degli arabi. Nel nostro caso,un algoritmo è un metodo per la risoluzione di un problema adatto però a essere implementato sotto forma di programma. Nello specifico, un algoritmo è un insieme finito di istruzioni che,se eseguite ordinatamente,sono in grado di risolvere un problema di partenza. Le proprietà di un algoritmo sono sostanzialmente 3 :
- Non ambiguità ( delle istruzioni )
- Eseguibilità ( delle istruzioni )
- Finitezza ( deve terminare )
Il nostro algoritmo dovrà essere specificato in un linguaggio che l’elaboratore è in grado di interpretare in modo corretto e contenere istruzioni che possono essere eseguite dal computer stesso. Un programma può quindi essere definito come un insieme di istruzioni espresse in un linguaggio formale ( sintassi e semantica ) chiamato linguaggio di programmazione. I computer però non sono in grado di capire nemmeno il linguaggio programmazione in quanto il microprocessore sa elaborare solo in linguaggio binario: ecco pertanto che i programmi dovranno essere ulteriormente tradotti da appositi applicazioni quali interpreti o compilatori. Abbiamo quindi l’interprete e il compilatore:
- L’interprete è un programma che traduce,istruzione per istruzione,il programma sorgente. Ogni istruzione è sottomessa alla cpu appena è stata tradotta. Anche se una istruzione è contenuta 10 volte in un programma verrà tradotta ogni volta che si presenterà al traduttore.
- Il compilatore invece traduce tutto il programma in una sola volta e poi lo sottomette alla cpu.
Se una stessa istruzione compare 10 volte,viene tradotta solo la prima volta e poi memorizzata in maniera tale che possa essere ripresa dal compilatore e inserita nelle restanti nove righe di programma. Possiamo riassumere le diverse fasi che portano dall’analisi del problema all’ottenimento di una soluzione:
- Analisi
- Formalizzazione
- Programmazione
- Traduzione
- Esecuzione
- Verifica
Non scendo nei dettagli per non addormentarvi troppo,anche perché le fasi sono facilmente intuibili sul loro contenuto.
[modifica] Linguaggi di Programmazione
Possiamo suddividere i linguaggi di programmazione in tre categorie :
[modifica] Linguaggi macchina
- Stringhe di numeri che danno istruzioni specifiche della macchina
- Esempio : +1300042774+1400593419+1200274027
[modifica] Linguaggio Assembly
- Abbreviazioni che rappresentano operazioni di calcolo elementari( tradotte via assemblatori )
- Esempio : LOAD BASEPAY >> ADD OVERPAY STORE GROSSPAY
[modifica] Linguaggi ad alto livello
- Simili all’inglese e usano notazioni matematiche ( tradotti via compilatori )
- Esempio : grossa = basePay + overTimepay;
Le fasi di programmazione di un programma C sono 6:
- Editing
- Preprocessing
- Compilazione
- Linking
- Caricamento
- Esecuzione
[modifica] Sintassi & Semantica
[modifica] Sintassi
- Specifica come costruire un programma nel linguaggio di programmazione. Volgarmente parlando,sono le regole per come si crea un programma.
- Esempio : <data>= cc/cc/cccc
[modifica] Semantica
- Specifica il significato del linguaggio
- Esempio : 01/02/2003 In italia -> 1° Febbraio 2003 Negli Usa -> 2° gennaio 2003
[modifica] Tipi di Dati
Un tipo di dati è un insieme di elementi omogenei e dei suoi operatori. Ad esempio il Tipo intero ammette l’operatore + , mentre il Tipo Boolenao non ammette l’operatore + . Esistono vari tipi di tipi di dati :
[modifica] Livello HW
- Supportati direttamente dalla macchina
- Elementari ( int,char,real,boolean )
[modifica] Livello linguaggio
- Supportati dal linguaggio
- Tipi strutturati(array,record,liste)
[modifica] Livello utente
- Definiti dall’utente usando le specifiche dell’LP
- Record,Grafi,Liste( alcuni potrebbero essere supportati da LP )
Il potere espressivo di un LP è strettamente collegato con i tipi di dato : più espressioni si possono rappresentare ( il c permette di rappresentare qualsiasi tipo ) più il linguaggio è espressivo. Immaginiamo i tipi di dato come una scatola . Possiamo classificare i tipi di dato in elementari e strutturati : gli elementari hanno come dominio elementi atomici ed omogenei ( interi,caratteri,reali,booleani, che coincidono con i TD primitivi ) e quindi sono detti scalari perché dotati di un solo elemento; gli strutturati hanno come dominio di elementi non atomici ed eterogenei come gli array,record,grafi e liste ( supportati da LP o definiti dall’utente ). Attenzione,i TP strutturati non sono composti da più elementi,ma da un elemento composto da più elementi( vettore ). Possiamo trovare anche elementi diversi tra loro ( Liste ). Un classico esempio di TP strutturato può essere il codice fiscale. Il concetto fondamentale è però quello riguardante l’astrazione dei dati,ovvero l’indipendenza dalla rappresentazione ( incapsulamento/implementation hiding) . L’astrazione è il concetto base della programmazione e sostanzialmente significa che possiamo interagire con un dato senza sapere come è stato concepito. La specifica astratta definisce il comportamento di un oggetto ( TD nel nostro caso ) indipendentemente dalla sua implementazione ( ciò che deve conoscere l’utente in sostanza ). La rappresentazione concreta definisce l’implementazione dell’oggetto,ovvero le linee di codice che servono per il software. L’astrazione del software consiste proprio in questo : fare in modo che il software venga usato dall’utente senza conoscere il codice; minore è l’iterazione con le linee di codice,migliore è il software. Un passo essenziale per usare un TD in qualsiasi programma è la sua dichiarazione. La dichiarazione colloca una variabile in memoria,quindi il nostro TD. Ricordo che il TD può già esistere o ce lo siamo creati ( vedremo nei prossimi capitoli quando parlerò delle strutture ;) ) . Con la dichiarazione quindi,si crea un’associazione permanente tra il TD,l’identificatore e l’indirizzo assegnato durante l’esecuzione del codice. Ciò che cambia ( eventualmente ) è il contenuto della locazione in sintonia con il concetto di variabile. Per concludere con i TD,dobbiamo solo ricordare l’overloading ( sovraccarico ) ovvero quando ad uno stesso operatore è assegnato una semantica differente a seconda del tipo a cui è applicato.
[modifica] Type Checking
Ovvero errori di tipo. Il controllo dei tipi garantisce che le operazioni di un programma siano applicate in modo proprio . Guardate il seguente esempio :
int pippo; /* ( dichiarazione ) */ float pluto = 2.3456; /* (dichiarazione + inizializzazione ) */ pippo = pluto; /* type checking error ( pippo=2) !!! */
Un programma sicuro rispetto ai tipi si dice safe. Ricordate che l’assegnamento va sempre da destra verso sinistra; in un operazione di assegnamento una variabile è sempre a sinistra. Se durante la compilazione trovate un Warning,il programma vi avvisa di un qualcosa ma non è un errore; vi avvisa solo che probabilmente qualcosa li può non andare. Il controllo dei tipi può avvenire in modo statico o dinamico. Il controllo statico avviene durante la traduzione del codice sorgente,quindi durante la compilazione. Uno dei suoi vantaggi è che da maggiore velocità n fase di esecuzione,ma un difetto può essere il debugging lento. Il controllo dinamico viene effettuato invece durante l’esecuzione del programma. In questo caso si posso controllare situazioni del tipo :
float pippo,pluto,topolino; …… Pippo = pluto/topolino; /* se topolino assume il valore 0 il programma va in crash */
Uno degli svantaggi del controllo dinamico è che il codice aggiuntivo consuma spazio e tempo,quindi l’esecuzione è meno efficace. Un particolare problema di tipo ( come quello illustrato poco sopra ) si può manifestare solo durante l’esecuzione.
[modifica] Astrazione Funzionale
Una puntualizzazione va fatta sulle funzioni e le procedure. Dal punto di vista sintattico sono analoghe ma mentre la funzione restituisce un valore all’interno dell’espressione dove è stata invocata,la procedura modifica il contenuto di locazioni di memoria. Per dirla ancora più semplice,la funzione restituisce un valore ( all’utente ),quindi restituisce un risultato mentre la procedura deposita il valore in memoria e non restituisce risultato. La dichiarazione di una procedura comprende :
- Il nome
- I parametri formali ( ciò che la funzione / procedura riceve )
- Il corpo,costituito da dichiarazioni locali e da sequenze di istruzioni
- Un tipo per il risultato.

