Fondamenti di Informatica

Slides:



Advertisements
Presentazioni simili
Linguaggio C e C++.
Advertisements

C C++ &.
I Linguaggi di programmazione
Traduzione ed Interpretazione
Informatica Generale Marzia Buscemi
Il Software.
Software di base: Linguaggi di Programmazione
Dalla scrittura all’esecuzione
Evoluzione dei linguaggi di programmazione
I linguaggi di programmazione
Inizio… Linguaggi Linguaggi di programmazione Linguaggi di programmazione Linguaggi di programmazione Linguaggi di programmazione Linguaggi Formali Linguaggi.
Linguaggi di programmazione
Algoritmi e Programmazione
Informatica Generale Susanna Pelagatti
3. Programmazione strutturata (testo di riferimento: Bellini-Guidi)
3. Programmazione strutturata (testo di riferimento: Bellini-Guidi)
Dr. Francesco Fabozzi Corso di Informatica
Programmazione Procedurale in Linguaggio C++
Anno Accademico Corso di Informatica Informatica per Scienze Biologiche e Biotecnologie Anno Accademico
Informatica Problema Algoritmo Programma
Informatica di base A.A. 2003/2004 Algoritmi e programmi
Università degli Studi di Bergamo Facoltà di Lingue e Letterature Straniere Facoltà di Lettere e Filosofia A.A Informatica generale 1 Appunti.
Corso di Laurea in Biotecnologie Informatica (Programmazione)
Corso di Informatica (Programmazione)
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
Unità Didattica 2 I Linguaggi di Programmazione
Fondamenti di Informatica1 Linguaggi Classificati rispetto alle caratteristiche principali: –potere espressivo che influenza lo stile di programmazione.
INSIEMI NUMERABILI L’analisi matematica introduce il concetto di insieme numerabile come insieme i cui elementi possono essere “contati” ossia che possiede.
LINGUAGGI DI PROGRAMMAZIONE
Da Problema a Programmazione
INFORMATICA MATTEO CRISTANI.
PROGRAMMAZIONE: linguaggi
Introduzione al linguaggio assemby del microprocessore a parte
Lezione 1 Linguaggi di programmazione – Algoritmi –Istruzioni
Le basi della programmazione
CODIFICA Da flow-chart a C++.
PROBLEMA ALGORITMO PROGRAMMA LINGUAGGI di PROGRAMMAZIONE
Lo sviluppo del software e i linguaggi di programmazione
CONCETTI DI BASE 1.0 FONDAMENTI 1.1 HARDWARE 1.2 SOFTWARE 1.3 RETI
ECDL Patente europea del computer
Linguaggi per COMUNICARE
Programma di Informatica Classi Prime
IO E LA MATEMATICA PROCEDURALE
Linguaggi di programmazione dalla prima generazione alla quinta ed attuale.
Dal problema all’ algoritmo
la traduzione dei programmi
Rappresentazione degli algoritmi
Parte 3 Lo stato: variabili, espressioni ed assegnazioni
Informatica Lezione 5 Scienze e tecniche psicologiche dello sviluppo e dell'educazione (laurea triennale) Anno accademico:
Tecnologie Informatiche ed Elettroniche per le Produzioni Animali
Introduzione Laboratorio di Calcolo Corso di Laurea in Fisica Università degli Studi di Roma “La Sapienza”
Scrivere e compilare programmi
Programmazione Attività di progettazione ed implementazione di programmi I programmi permettono di realizzare funzioni complesse su un hardware in grado.
1 Sommario lez 1 Concetti principali, domande ed esercizi Concetti principali –algoritmo, programma –struttura di controllo: condizionale (if …), iterativa.
Algoritmi.
L’esecuzione dei programmi
Linguaggi Diversi tipi di linguaggi:
Concetti Fondamentali sulla Programmazione
1 Linguaggi: guardando la semantica §esistono un insieme di concetti semantici e di strutture di implementazione in termini dei quali si descrivono in.
Realizzazione software
Il software Claudia Raibulet
Esercizi.
Informatica e Informatica di Base
Problemi, algoritmi e programmazione
Programmazione dei Calcolatori Elettronici
I linguaggi di programmazione -GALBIATI ALBERTO -ESPOSITO MATTIA.
LINGUAGGI DI PROGRAMMAZIONE E' un linguaggio formale dotato di una sintassi ben definita che viene utilizzato per scrivere programmi che realizzano algoritmi.
Unità di apprendimento 6 Dal problema al programma.
Unità di apprendimento 6
ALGORITMI, LINGUAGGI E PROGRAMMI Facoltà di Lingue e Letterature Straniere Corso di laurea in Relazioni Pubbliche.
Transcript della presentazione:

Fondamenti di Informatica Programmi e Linguaggi di Programmazione Prof. Michele Amoretti Fondamenti di Informatica a.a. 2007/2008

Sommario Definizione di programma Modalità di esecuzione: compilazione VS interpretazione Linguaggi di programmazione Linguaggi a basso livello Linguaggi ad alto livello Programmazione strutturata Programmazione procedurale Programmazione a oggetti

Definizione di programma Se per risolvere un certo problema esiste un algoritmo, cioè un procedimento infallibile, che può essere descritto in modo non ambiguo fino ai dettagli, e conduce sempre all'obiettivo desiderato in un tempo finito allora esistono le condizioni per affidare questo compito a un computer, semplicemente descrivendo l'algoritmo in questione in un programma scritto in un opportuno linguaggio comprensibile alla macchina. La descrizione di un algoritmo per la soluzione di un problema P in un linguaggio di programmazione L, e cioè un programma in L, è costituito da una sequenza finita di istruzioni in L la cui esecuzione da parte del calcolatore porta (o dovrebbe portare) alla risoluzione di P.

Struttura di un programma Il codice sorgente (= testo) di un programma è tipicamente formato da: Una parte di dichiarazioni, che ha lo scopo di dichiarare tutte le variabili utilizzate dal programma, con il loro tipo, che specifica l’insieme dei valori che le variabili possono assumere e le operazioni che su di esse possono essere esguite. Una parte di istruzioni, che descrive l’implementazione dell’algoritmo risolutivo utilizzato. Es. in Java int a,b,t; // dichiarazione di 3 variabili di tipo int (4 byte) a = 10; // istruzioni di assegnamento b = 5;

Modalità di esecuzione: compilazione VS interpretazione La compilazione di un programma consiste nell’analisi delle istruzioni del codice sorgente (CS) da parte di un programma traduttore, il compilatore, al fine di generare l’equivalente (ottimizzato) programma in codice binario, detto programma oggetto (PO). La successiva fase di “linking” con altri programmi oggetto (es. librerie di funzioni) produce il programma eseguibile dalla macchina hardware. L’esecuzione di quest’ultimo necessita il caricamento dello stesso in memoria. CS PO LIB EXE Compilatore Editor Linker Loader Programma in memoria

Modalità di esecuzione: compilazione VS interpretazione L’interpretazione di un programma consiste nell’analisi e immediata esecuzione delle sue istruzioni, una alla volta in modo sequenziale, da parte di un programma apposito, l’interprete. Rispetto al compilatore, l’interprete genera codice macchina molto meno ottimizzato, perché non ha una visione globale del programma. Vengono compilati la maggior parte dei linguaggi di programmazione “convenzionali”, come ad esempio l’assembly, il Pascal, il C e il C++. Vengono interpretati, invece, i linguaggi “non convenzionali”, quali il Prolog e il LISP. Anche il linguaggio macchina, in un certo senso, è interpretato (dall’hardware del sistema di elaborazione). Esistono poi tecniche miste, per cui il programma sorgente viene tradotto in un linguaggio intermedio che viene poi interpretato. E’ il caso di Java.

Linguaggi di programmazione Un linguaggio di programmazione è un formalismo per scrivere programmi per calcolatori. Come tutti i linguaggi è definito da una grammatica, cioè una raccolta di regole che definiscono il lessico (vocabolario del linguaggio) la morfologia (classificazione degli elementi lessicali) la sintassi (struttura delle istruzioni) la semantica (significato delle istruzioni) del linguaggio. Essendo i linguaggi di programmazione molto semplici e le istruzioni inequivocabili, dato che devono essere eseguite da una macchina, non si parla di pragmatica (influenza del contesto sull’interpretazione dei significati).

Linguaggi di programmazione Dal punto di vista lessicale, i linguaggi di programmazione presentano tipicamente un insieme di “parole riservate”, che non possono essere utilizzate dal programmatore come nomi di variabili, perché hanno uno scopo ben preciso (stabilito dalla morfologia del linguaggio). Tutte le combinizioni di caratteri (consentiti) che non sono parole riservate, possono essere usate come nomi di variabili. Es. in Java non posso chiamare una variabile “for” perché quell’elemento lessicale è una parola riservata che definisce un comando ben preciso (iterazione)

Linguaggi di programmazione Dal punto di vista morfologico, i linguaggi di programmazione usano tre categorie di parole: le variabili gli operatori i comandi che unite fra di loro secondo certe regole sintattiche formano le istruzioni.

Linguaggi di programmazione La sintassi di un linguaggio di programmazione stabilisce le sequenze accettabili delle parole del linguaggio. La notazione più ampiamente utilizzata per rappresentare la sintassi di un linguaggio di programmazione è detta BNF (Backus-Naur Form), dal nome dei suoi progettisti John Backus e Peter Naur. Generica regola BNF: lato sinistro ::= definizione Dove il lato sinistro è il nome di una singola categoria grammaticale. Es. <intero con segno> ::= <segno> <numero> <segno> ::= +|-|Λ <numero> ::= <cifra>|<cifra><numero> <cifra> ::= 0|1|2|3|4|5|6|7|8|9

Linguaggi di programmazione Le regole semantiche di un linguaggio sono quelle per cui, ad esempio, la frase “i gatti abbaiano” viene considerata sbagliata, anche se lessicalmente e sintatticamente corretta. Quali sono le istruzioni semanticamente errate nei linguaggi di programmazione? Es. char a; float b; int somma; somma = a + b; // sto sommando variabili di tipo diverso e pretendo // di ottenere un risultato di tipo ancora diverso

Linguaggi di programmazione Attenzione! La semantica di un linguaggio di programmazione è facilmente formalizzabile (anche se spesso ci si limita alle spiegazioni in linguaggio naturale). E’ difficile invece formalizzare la semantica di un programma (= il significato delle operazioni svolte dal programma). La macchina non capisce il senso dei programmi, si limita ad eseguire istruzioni che gli vengono presentate (dopo compilazione o interpretazione) in forma di sequenze di bit. Se la macchina capisse il senso di quello che deve fare, potrebbe ad esempio cercare di ottimizzare un programma da sola, o magari cercare in Internet un programma analogo ma che ha prestazioni migliori!

Linguaggi a basso livello Sono strettamente dipendenti da una specifica macchina hardware (in particolare dalla CPU). Il più “semplice” in termini di sintassi è il linguaggio macchina, le cui istruzioni sono scritte direttamente in notazione binaria (sequenze di 0 e 1) e sono quindi molto lontane dal linguaggio naturale e molto complesse da utilizzare per il programmatore. Le istruzioni in linguaggio macchina sono lette ed eseguite (“interpretate”) direttamente dalla macchina hardware. Generalmente per ogni linguaggio macchina esiste anche una versione simbolica, detta linguaggio assembly. I comandi sono espressi da codici mnemonici (= facili da ricordare). E’ più immediato da utilizzare del linguaggio macchina, ma il codice sorgente risulta comunque complesso e non è portabile tra famiglie di processori diverse.

Linguaggi a basso livello Tra le istruzioni in linguaggio assembly e quelle in linguaggio macchina c’è un mapping 1-a-1. Il compilatore che traduce da assembly a linguaggio macchina è detto assembler. Es. Istruzione in linguaggio Assembly 8086: MOV AH, 11 Istruzione in linguaggio macchina: 1011 0 100 00001011 i primi 4 bit rappresentano l’Operation Code, che identifica il tipo di istruzione; il bit W vale 1 se l’operando è su 16 bit, 0 se è su 8 bit: nel caso in esame W = 0; i 3 bit Reg indicano il registro destinazione, secondo la tabella indicata: nel caso in esame Reg = 100; gli 8 bit di dato contengono l’operando: nel caso in esame 11(10) = 00001011(2).

Linguaggi ad alto livello Nascondono, in modo più o meno completo, le caratteristiche proprie delle diverse macchine hardware ed offrono al programmatore una sintassi molto più vicina al linguaggio naturale rispetto ai linguaggi a basso livello. Consentono di descrivere il problema in modo intuitivo ed espressivo. Permettono di trattare con facilità: formule matematiche operazioni di I/O strutture dati complesse Mettono a disposizione strutture dati e costrutti logici (ad es. per il controllo del flusso). Il codice sorgente risulta più leggibile e documentabile.

Linguaggi ad alto livello Hanno caratteristiche diverse: offrono forme espressive appropriate per alcuni problemi specifici. Es. FORTRAN (problemi scientifici) COBOL (problemi commerciali) BASIC, Pascal (problemi generici non troppo complessi) C, C++ (controllo di dispositivi elettronici, automazione) Java, C# (GUI, applicazioni distribuite) LISP (intelligenza artificiale) PROLOG (dimostrazione automatica di teoremi) I linguaggi più diffusi hanno il compilatore per quasi tutti i sistemi operativi e calcolatori presenti sul mercato.

Linguaggi ad alto livello Linguaggi imperativi Sono linguaggi convenzionali, basati sulla nozione di istruzione di macchina e di memorizzazione di valori in celle di memoria (quindi “vedono” il calcolatore come da modello di Von Neumann). Es. BASIC, FORTRAN, C, JAVA, ecc. Linguaggi funzionali Sono linguaggi non convenzionali, basati sul concetto di funzione. Le funzioni vengono definite anche in modo ricorsivo, e utilizzando costrutti per il controllo di flusso. Es. LISP Linguaggi dichiarativi basati sulla logica Sono linguaggi non convenzionali, basati sui concetti di asserzione condizionata e interrogazione. Es. PROLOG

Programmazione strutturata Le idee chiave della programmazione strutturata si possono ricondurre alla critica della struttura di controllo del salto incondizionato (o GOTO, "vai a"), che rappresentava, negli anni '60, lo strumento fondamentale per la scrittura di programmi complessi. In un celebre articolo del 1968, “Goto statement considered harmful”, Edsger Dijkstra discusse approfonditamente gli effetti deleteri del goto sulla qualità del software, e in particolare sulla sua leggibilità e modificabilità (il cosiddetto problema dello spaghetti code).

Programmazione strutturata Un'altra celebre pubblicazione che risultò fondamentale all'affermarsi della programmazione strutturata fu “Flow Diagrams, Turing Machines, and Languages with Only Two Formation Rules”, in cui Corrado Böhm e Giuseppe Jacopini dimostrarono il loro celebre teorema. Teorema di Jacopini-Bohm Qualsiasi programma scritto usando il GOTO può essere riscritto senza, a patto di avere a disposizione altri tre tipi di strutture di controllo: sequenza, alternativa e iterazione.

Programmazione strutturata Sequenza:

Programmazione strutturata Alternativa:

Programmazione strutturata Iterazione:

Programmazione strutturata Il seguente programma è un esempio banale di spaghetti code in BASIC, che stampa su schermo la sequenza di numeri da 1 a 10 e il loro quadrato. 10 DIM i 20 i = 0 30 i = i + 1 40 IF i <> 10 then GOTO 70 50 PRINT "Programma terminato." 60 END 70 PRINT i & " al quadrato = " & i * i 80 GOTO 30 Si noti come le istruzioni di GOTO introducano una dipendenza dai numeri di riga del programma, e come il flusso di esecuzione salti in maniera impredicibile da una zona all'altra.

Programmazione strutturata Ecco un esempio di codice equivalente scritto con uno stile di programmazione strutturato: DIM i FOR i = 1 to 10 PRINT i & " al quadrato = " & i*i NEXT PRINT "Programma terminato." Il costrutto “for” evita di dover usare il GOTO.

Programmazione strutturata In C il GOTO si può usare (purtroppo!): // ciclo che stampa gli interi da 10 a 1 int n=10; loop: cout << n << ", "; n--; if (n>0) goto loop; Usando però il costrutto sintattico iterativo “for”: for (int n=10; n>0; n--) il codice è molto più sintetico e leggibile!

Programmazione strutturata In Java l’istruzione GOTO esiste come “parola riservata” del linguaggio, ma non è più implementata perché considerata strumento di cattiva programmazione. Ci sono comunque dei meccanismi (assolutamente “legali”) che producono l’effetto del GOTO, ad esempio: l’istruzione break Es. for (i = 0; i < arrayOfInts.length; i++) { if (arrayOfInts[i] == searchFor) break; } l’istruzione continue Es. for (int i = 0; i < max; i++) { if (searchMe.charAt(i) != 'p') continue; numPs++;

Programmazione procedurale Nella programmazione procedurale si adotta la metodologia di suddivisione del problema in sottoproblemi detta “divide et impera”. Dividendo un problema in porzioni più piccole è possibile governare la complessità che altrimenti ci sovrasterebbe se si guardasse il problema nella sua interezza. Adottando questa tecnica, il codice del programma risulta diviso in moduli, detti sottoprogrammi o anche procedure o funzioni, ciascuno dei quali svolge una precisa porzione del compito complessivo. nome + tipo dei parametri  signature della procedura Vantaggi: - maggiore leggibilità dei programmi - possibilità di riuso del codice.

Programmazione procedurale In genere c’è una procedura principale (main) che ha il compito di invocare ciascun sottoprogramma ogni volta che si deve affrontare il compito cui questo è proposto. Es. in linguaggio C #include <stdio.h> int main() { printf("Hello world\n"); return 0; }

Programmazione orientata agli oggetti (OOP) E’ un paradigma di programmazione in cui: un'unica entità (detta classe) raggruppa i dati (detti attributi) le procedure (dette metodi) che operano sui dati. Una classe definisce un tipo complesso. Una variabile il cui tipo è definito da una classe è detta istanza della classe, o più brevemente oggetto. E’ l’evoluzione della programmazione procedurale. La modularità di un programma viene realizzata progettando e realizzando il codice sotto forma di classi che interagiscono tra di loro. Il programma ideale, realizzato applicando i criteri dell'OOP, è completamente costituito da oggetti che interagiscono gli uni con gli altri.

Oggetti Sono astrazioni che descrivono • oggetti fisici, • concetti astratti che fanno parte del problema (o della soluzione). Caratterizzati da • uno stato, • un insieme di servizi che offrono agli altri oggetti. I valori degli attributi determinano lo stato. I metodi (che non sono solo di tipo get e set!) rappresentano i servizi offerti. Es. un telefono cellulare • stato: carica della batteria, potenza del segnale, … • servizi: chiama un numero, rispondi alla chiamata, …

Oggetti Es. in linguaggio Java attributi (variabili di stato) public class CellularPhone { private int field = 0; private int battery = 0; public void answer() { … } public void call(String number) { public class Caller { public static void main(String args[]) { CellularPhone cellPhone = new CellularPhone(); cellPhone.call(“0039123456789”); attributi (variabili di stato) metodi (servizi offerti) classe principale: solo lei contiene il metodo main() oggetto di tipo CellularPhone

Storia dell’OOP - 1967: Simula (1967) - anni '70: Smalltalk e varie estensioni del Lisp - anni '80: C++, Objective C, Object Pascal, ecc. - anni '90: Eiffel, Java Oggi i linguaggi più usati sono quelli che supportano anche ma non solo il paradigma di programmazione orientata agli oggetti, come C++, Java, Delphi, Python, C#, Visual Basic .NET. Un linguaggio di programmazione per poter essere definito ad oggetti deve possedere le tre proprietà seguenti: Incapsulamento Ereditarietà Polimorfismo

Incapsulamento L'incapsulamento è la proprietà per cui un oggetto contiene ("incapsula") al suo interno gli attributi (dati) e i metodi (procedure) che accedono ai dati stessi. Gestito in maniera intelligente, l'incapsulamento permette di vedere l'oggetto come una black-box, cioè una scatola nera di cui, attraverso l‘interfaccia sappiamo cosa fa e come interagisce con l'esterno ma non come lo fa. E’ buona pratica definire tutti gli attributi come private; quelli che si vogliono esporre vengono resi accessibili solo attraverso metodi public di tipo get e set.

Ereditarietà Meccanismo molto importante che permette di derivare nuove classi a partire da classi già definite. Le classi derivate possono aggiungere nuovi membri rispetto alla superclasse, oppure modificare il comportamento dei metodi della superclasse (ridefinendone il codice).

Ereditarietà Se un oggetto di una sottoclasse può essere utilizzato al posto di un'istanza della superclasse, il tipo della classe derivata è detto sottotipo (in questo caso l’operazione di subclassing corrisponde a quella di subtyping). Una sottoclasse che voglia definire un sottotipo può ridefinire (= implementare diversamente) i metodi della superclasse (vedi Polimorfismo), ma non può eliminarli sintatticamente nè modificare le loro signature. In alcuni linguaggi una sottoclasse può eliminare o cambiare le proprietà di accesso ad un metodo della superclasse, il che fa sì che l'operazione di subclassing non sia corrispondente a quella di subtyping.

Polimorfismo E’ il meccanismo per cui classi derivate possono implementare in modo differente i metodi e le proprietà delle proprie superclassi, rendendo possibile che gli oggetti appartenenti a delle sottoclassi di una stessa classe rispondano diversamente alle stesse istruzioni. Es. In una gerarchia in cui le classi Cane e Gatto discendono dalla super-classe Animale potremmo avere il metodo cosaMangia() che restituisce la stringa "osso" se eseguito sulla classe Cane e "pesce" se eseguito sulla classe Gatto. Buona regola di programmazione: quando una classe derivata ridefinisce un metodo, il nuovo metodo deve avere la stessa semantica di quello ridefinito, dal punto di vista degli utenti della classe.

Polimorfismo Il polimorfismo è particolarmente utile quando la versione del metodo da eseguire viene scelta sulla base del tipo di oggetto effettivamente assegnato a una variabile a runtime (invece che al momento della compilazione). Questa funzionalità è detta binding dinamico (o late-binding). In Java: - interface (definisce solo le signature dei metodi pubblici; non ha costruttore; non può essere istanziata perché i metodi non sono implementati) - class (definisce e implementa metodi pubblici e privati) Una class puà implementare diverse interface, ma estendere una sola classe. Una interface può estendere una sola interface. Una classe o singoli metodi possono essere dichiarati abstract per obbligare i programmatori a ridefinirli nelle classi derivate.