


























































Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Appunti completi di programmazione in linguaggio C e Java. Contiene concetti come automi, algoritmi, variabili, puntatori, funzioni, gestione della memoria. Inoltre presenta anche approfondimenti su tecniche di programmazione, paradigmi fondamentali, astrazione, polimorfismo, ereditarietà, eccezioni in Java, ambiti di visibilità ecc Materia: Informatica Anno scolastico: 2024/2025
Tipologia: Appunti
1 / 66
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!



























































La programmazione definisce un programma di lavoro da seguire. Ogni programma è adatto ad uno scopo e non funziona bene per altri scopi. Le macchine programmabili seguono un programma di lavoro migliore versatilità rispetto agli strumenti regolabili.
Sono macchine programmabili per fare calcoli. Primo approccio storico: un modello di calcolatore diverso per ciascuno dei calcoli che erano di volta in volta richiesti. Molto presto si intraprese a progettare dei calcolatori general purpose.
Il software è generalmente più complesso dell' hardware. Programmare : sequenza ordinata di istruzioni da compiere. Il programmatore è coinvolto in tutte le fasi: scelta della soluzione, test e implementazione, utilizzando metodologie agili, che risultano più efficaci. Un lavoro di team è strutturato in vari modi:
Linguaggio : si intende la capacità d’uso e l’uso stesso di un qualunque sistema di simboli adatti a comunicare. Linguaggio scritto : sequenza finita di simboli preso da un insieme finito prefissato di simboli (non tutte le sequenze sono parte del linguaggio). La linguistica ha come obiettivo quello di dare una rigorosa descrizione di un linguaggio scritto, specificando quali frasi sono formate correttamente. Tre livelli di analisi : Sintattico : come sono combinati i segni. Semantico : significato associato a ciascun segno. Pragmatico : conseguenze di un enunciato.
Alfabeto : insieme finito di elementi (lettere o simboli). Stringa : sequenza finita di simboli appartenenti all'alfabeto. Cardinalità di una stringa : numero di simboli che la compongono (può essere vuota o avere un numero finito di elementi).
Chiusura di Kleene : insieme di tutte le possibili stringhe su un alfabeto ∑. Σ* : tutte le possibili parole, inclusa la parola vuota. Σ+ : tutte le possibili parole non vuote. Concatenazione : Consideriamo due stringhe a e b la loro concatenazione è la stringa ab. Sottostringa : Consideriamo la stringa s, una sottostringa di s è una qualsiasi parte di simboli consecutivi della stringa s.
Un linguaggio formale è un insieme di parole su un alfabeto esempio: linguaggio di programmazione. Simboli o token : elementi costitutivi di un linguaggio. Ogni linguaggio è sotteso da delle regole.
Cardinalità : numero di stringhe che lo compongono. Concatenazione : linguaggio Lc = L1L2.
possibili ripetizioni. Chiusura L* : linguaggio costituito dall'unione di tutte le potenze di L (inclusa la parola vuota). Chiusura positiva L+ : unione di tutte le potenze di L con n > 0.
Codice : un linguaggio L in cui ogni parola in L+ è univocamente decomponibile (decifrabile) come prodotto di parole di L, senza che alcuna parola sia prefisso di un'altra (ha un unico significato).
Data una parola (stringa o frase) w ∈ Σ*, ci sono due possibilità :
Approccio riconoscitivo : per ogni parola in Σ*, determina se appartiene al linguaggio con "si" o "no" (linguaggi ricorsivi o decidibili). Esempio : automi a stati finiti (famiglia di riconoscitori per linguaggi regolari). Approccio generativo : genera la parola seguendo delle regole (se la genero, appartiene al linguaggio), ed è in grado di generare tutte le parole w di L, una dopo l’altra. Esempio : grammatica. Lezione 4 - Automi a Stati Finiti Automa a stati finiti : è un modello matematico di un sistema con ingressi e uscite discreti. In un certo istante il sistema può trovarsi in uno stato scelto tra un numero finito di stati possibili. Il passaggio tra stati è detto transizione.
Un automa M su un alfabeto è definito come una quintupla ⟨K, Σ, δ,q0, F⟩. K è un insieme finito e non vuoto di stati in cui si può trovare M Σ è un alfabeto finito di simboli di ingresso δ: K × Σ → K è la funzione di transizione di stato
Permette di analizzare e definire il concetto di algoritmo. Possiede un nastro potenzialmente infinito , composto da celle dove una testina può muoversi in entrambe le direzioni. Scrittura o lettura di un simbolo nella cella sotto la testina (sostituendo il contenuto precedente). L’automa definisce quello che si chiama dispositivo di controllo. Può leggere e scrivere in ogni cella sul nastro. Le celle possono essere vuote.
Funziona come un calcolatore di funzioni. È rappresentata come una quintupla di elementi. s: lo stato della macchina all’istante presente i: il simbolo letto all’istante presente S(s,i): lo stato della macchina all’istante successivo I(s, i): il simbolo scritto dalla macchina all’istante successivo V(s, i): il verso del movimento della macchina (destra o sinistra) Prevede uno stato finale.
0/- (legge zero e scrive nulla), ?/0 (legge? e scrive zero). Le quintuple MdT costituiscono effettivamente il programma (il codice della MdT), descrivendo un automa a stati.
La MdT è una macchina teorica capace di eseguire qualsiasi algoritmo ( algoritmo procedura per risolvere «meccanicamente» una classe di problemi predefiniti).
Tesi di Church : non esiste un formalismo né una macchina concreta che possa calcolare una funzione F non calcolabile secondo Turing. Modello teorico di macchina potente. Qualsiasi cosa calcolabile secondo la MdT può essere verificata per altri modelli teorici. Esistono problemi non Turing risolvibili (es. problema dell'arresto : "non è possibile determinare se un programma terminerà o meno").
In grado di imitare la MdT. È un modello astratto degli attuali elaboratori. La MdT Universale non è in grado di decidere il problema dell’arresto (Turing- indecidibile). Legge quintuple sul nastro e le esegue (esegue altre MdT). Il nastro funge da RAM ; i programmi sono eseguibili solo in RAM. Tratta programmi e dati in modo analogo. Lezione 6 – Architettura di un elaboratore
È un calcolatore universale , mentre la MdT è un concetto teorico (oggetto concettuale). La potenza computazionale è la medesima tra MdT e macchina di von Neumann.
CPU : è in grado di acquisire, interpretare ed eseguire le istruzioni di un programma (corrisponde alla macchina a stati della MdT). Memoria centrale : è il dispositivo dove si trovano le informazioni necessarie all’esecuzione di un programma, ossia istruzioni e dati (equivalente al nastro della MdT). Dispositivi I/O o periferiche : permettono di trasferire informazioni tra memoria centrale e/o CPU e l’ambiente esterno (analoghi alla testina della MdT). Bus di sistema : collega tra loro i vari componenti.
Una MdT è specifica per un problema, mentre la MdTU è generica per ogni problema (esegue una MdT specifica indicata come programma) Come l’ architettura di Von Neumann Programmi e dati memorizzati nello stesso modo Carica la descrizione della MdT da eseguire in memoria Crea la sua macchina stati e la esegue Lezione 1 – Sintassi e Semantica (lezione 2)
(^) Sintassi : descrive come viene scritta una frase (specificata in termini di token o terminatori). Può essere definita da una grammatica. (^) Semantica : descrive il significato di ciò che è scritto. (^) Un linguaggio di programmazione è quasi sempre descritto da una sintassi formale e da una semantica informale. (^) Lessico : riguarda la costruzione delle parole.
(^) Diverse notazioni: prefissa (+ a b), postfissa (a b +), infissa (a + b). (^) Prefissa e postfissa non richiedono parentesi per l'esecuzione corretta. (^) L' arità di un operatore è il numero di operandi che richiede.
(^) È una modalità grafica ad albero per evidenziare i componenti significativi di un linguaggio. (^) Mostra la struttura sintattica ed è indipendente dalla notazione e dalla grammatica. (^) Esercizio AST : viene rappresentato solo un albero perché il concetto è solo uno.
(^) Versione specifica dell'AST per una data grammatica. (^) Esempio : Un ciclo for ha lo stesso concetto in tutti i linguaggi, ma la scrittura varia.
(^) Rappresenta la corrispondenza tra una rappresentazione scritta del linguaggio e i token della grammatica del linguaggio. (^) Determina come una sequenza di caratteri venga suddivisa in lessemi e come questi vengano catalogati rispetto alla grammatica. Esempio :
Tipo 3 (regolari ): grammatica regolare, componenti sintattici più elementari. Es: Automi a Stati Finiti.
Formato standard per rappresentare le regole di grammatica di un linguaggio. → delle regole viene sostituita da ::= (viene letto come “può essere”) Simboli non terminali racchiusi tra <>. Simboli terminali (token) racchiusi tra virgolette. Il simbolo / viene letto come “oppure”
Possibilità di elementi opzionali (racchiusi tra parentesi tonde o quadre) e ripetuti zero o più volte (racchiusi tra parentesi graffe) È una versione più espressiva e compatta.
Se una stringa ha più di un parse tree, allora la grammatica associata è ambigua. Un linguaggio di programmazione non deve avere una grammatica ambigua.
Espressioni regolari : rappresentazione sintetica di una grammatica regolare. Utilizzano operazioni tipiche di un linguaggio formale: alfabeto, unione, concatenazione.
Sono dei diagrammi che esprimono le regole di una grammatica in forma grafica (un diagramma per ciascun simbolo non terminale). Sono un altro modo per descrivere le BNF. In una carta sintattica : i rettangoli indicano simboli non terminali, gli ovali indicano simboli terminali, le frecce indicano la sequenza dei simboli e ogni biforcazione indica un’alternativa. Lezione 1 – nozione di algoritmo (lezione 2)
Algoritmo : sequenza finita di operazioni elementari per risolvere una classe di problemi (più di un problema, non uno solo), seguendo regole non ambigue. Istruzioni : insieme ordinato e finito di operazioni da eseguire. Ogni istruzione è univoca e deve essere comprensibile per l'esecutore.
Eseguibilità : l'algoritmo deve essere eseguibile. Non ambiguità : deve essere chiaro e preciso. Definito : ogni passaggio deve essere specificato. Correttezza : deve fare ciò per cui è stato progettato. Efficienza : misura delle istruzioni e variabili necessarie per risolvere il problema. Finitezza : deve terminare in un tempo finito.
Relazione : Algoritmo (soluzione) → Programma (rappresentazione) → Esecutore (chi esegue). A seconda dell’esecutore, lo stesso algoritmo può essere espresso in linguaggi differenti.
Esecutore (calcolatore) : è general purpose e esegue ogni programma come un automa, spostandosi tra stati, eseguendo poche istruzioni elementari ma rapidamente e con precisione. Programma : sequenza di istruzioni elementari che un calcolatore è in grado di comprendere ed eseguire. Programmazione : attività che consiste nell’organizzare istruzioni elementari, direttamente comprensibili dall’esecutore, in strutture complesse (programmi) al fine di svolgere determinati compiti Lezione 2- problema-algoritmo
Definizione dei dati e dei risultati che si vogliono ottenere (a partire dai dati). Processo di formulazione di un problema:
Trovare un algoritmo è più difficile; trovare l'istanza è più semplice. Lezione 3 - flusso di un algoritmo
Algoritmo : sequenza di passi. Flusso : ordine di esecuzione della sequenza di passi (quando dobbiamo verificare un algoritmo bisogna controllare il flusso). Tipi di esecuzione : Sequenziale : uno dopo l'altro. Non sequenziale : flusso controllato.
Variabile : qualcosa che esiste concretamente nella memoria di un calcolatore ed occupa uno spazio fisico. È assimilabile all’incognita matematica (l’ incognita matematica e siste solo nella mente del matematico). Architettura di Von Newman : la variabile risiede in memoria RAM ed ha una dimensione e ha associato un identificatore.
Assegnamento : assegna a una variabile il valore risultato di un’operazione. Esempio: r x (assegna a r il valore di x). Decisione : specifica la condizione che deve essere valutata in termini di predicato di verità (biforcazione: vero o falso). Esempio: Operatore ternario "se allora altrimenti". Salto : spostamento del flusso esecutivo (decisione e salto determinano il flusso). Ripetizione : combinazione di decisione e salto (ripete una serie di istruzioni fino a che la decisione non assume un valore di verità specifico).
Lezione 2- programmazione non strutturata
Strumento per procedure sequenziali. Ha poche e semplici istruzioni. Accesso alla memoria simile ad accesso a celle dei nastri indicando posto tra [].
Il flusso è codificato in strutture specifiche. Il problema prevalente è sui salti incondizionati (salto avanti, indietro ecc…). Un salto condizionato è più facile da comprendere per via della condizione che lo genera.
Lascia la massima libertà sul flusso , quindi, usa i salti incondizionati problema poiché non c'è una struttura dei flussi. Esempio linguaggio non procedurale: HTML, SQL, XML.
Linguaggio imperativo : programmazione intuitiva in cui si ordina all'esecutore di compiere delle azioni (richieste esplicite) fa parte della macro-famiglia del paradigma procedurale. Gli elementi caratterizzanti sono: dinamicità delle esecuzioni (cambiano durante il programma) e staticità delle istruzioni. Lezione 3-variabili e assegnamenti
Variabili : paragonabili alle incognite matematiche. Si definiscono in termini di: Nome : identificatore (a cui fare riferimento). Tipo : insieme dei possibili valori che possono essere assunti e operazioni che possono essere fatte. Valore : assunto dalla variabile.
L’identificatore è il nome dell'oggetto e corrisponde a un’area di memoria che contiene il valore dell’oggetto. Il rapporto tra identificatore e valore è dinamico, mentre tra identificatore e area di memoria è statico.
Variabile : è un contenitore di valori che possono variare durante il tempo di esecuzione. è una locazione di memoria che ha una dimensione associata. è riferibile attraverso l’identificatore. si può variarne il contenuto attraverso un assegnamento. Assegnamento : assegna un valore a una variabile: variabile espressione (il valore di destra va nella cella di sinistra)
Il tipo di una variabile specifica: l'insieme dei valori che può assumere (naturali, reali, ecc). la dimensione che occupa in memoria. l’insieme delle operazioni che possono essere effettuare su di essa.
Il concetto di variabile è un'astrazione del concetto di locazione di memoria. La variabile è il riferimento mnemonico all’indirizzo della locazione di memoria. L’assegnamento di un valore a una variabile è un’astrazione dell’operazione STORE di un ipotetico linguaggio macchina.
La tipizzazione delle variabili permette di mantenere il controllo sulla correttezza nello sviluppo del programma. La nozione di tipo fornisce un’astrazione rispetto alla rappresentazione effettiva dei dati. Il programmatore quindi può utilizzare variabili di tipi differenti, senza necessità di conoscerne l’effettiva rappresentazione.
Dichiarazione : un enunciato di linguaggio di programmazione che definisce un identificatore e l'informazione a questo correlata. Esiste la dichiarazione esplicita e implicita (al primo uso). Vantaggi nella dichiarazione : accresce la leggibilità dei programmi, diminuisce la possibilità di errori, e facilita la traduzione efficiente in linguaggio macchina.
Costante : un valore che non cambia per il lasso di tempo in cui viene usato. In programmazione è un modificatore di tipo che indica che una variabile non potrà mai cambiare valore. Sono state create per evitare che il programmatore sbagli. Lezione 4-programmazione strutturata (lezione 4)
Nasce dalla critica del costrutto del salto incondizionato , che rappresentava, lo strumento fondamentale per la definizione di algoritmi complessi. Il salto è ottenuto attraverso le istruzioni “go to” (salto non condizionato quando non è associato a una decisione, per andare dove voglio io nel flusso). Un flusso ordinato di istruzioni dall’inizio alla fine avviene attraverso regole che portano all’esecuzione sequenziale di operazioni. Ogni struttura di controllo ha un solo punto di ingresso e un solo punto d’uscita blocco strutturato (un blocco è come se fosse un’unica istruzione). Un programma è una sequenza di blocchi. Costrutto : dispositivo sintattico che permette di combinare tra loro istruzioni elementari creando blocchi strutturati.
Ci sono tre costrutti fondamentali: Sequenza : le istruzioni vengono eseguite una dopo l’altra a seconda dell’ordine in cui sono scritte. Selezione : permette di gestire una scelta (che è la decisione). Iterazione : l’esecuzione di una o più istruzioni viene ripetuta in base al valore di una condizione (il salto viene sostituito dall'iterazione e viene associato alla selezione). Iterazione post condizionata : chiamato anche ciclo repeat-until. Iterazione pre-condizionata : il blocco 1 deve modificare la condizione sennò il ciclo diventa infinito.
Nella quinta immagine, tra A e Z c’è un punto di taglio Quinta immagine: non è né un ciclo post né pre-condizionato (non è programmazione strutturata).
In realtà i 3 costrutti possono essere ridotti solo a sequenza e iterazione per codificare qualsiasi algoritmo. È possibile rappresentare una selezione come un costrutto iterativo inserendo una variabile booleana in aggiunta.
Invarianti : asserzione (condizione) sempre vera in qualunque momento della esecuzione del programma (in maniera indipendente). Sono associati ad un punto del programma ma ci danno delle indicazioni circa le proprietà della sua computazione. Una asserzione è una condizione vera o falsa circa lo stato della computazione. Lezione 5 –Introduzione al Linguaggio C (lezione 5)
Un programma è come una funzione che prende degli ingressi (x) e ritorna delle uscite (y) ovvero y f(x) La funziona principale , quella che ‘‘contiene’’ tutto il programma si chiama main. Le funzioni ritornano un output. Fisicamente un programma risiede su uno o più file di testo chiamati file sorgenti. Prima di eseguire il programma, i file sorgenti vengono riuniti in un’unica entità che poi viene tradotta nel codice eseguibile questo processo si chiama compilazione. Il linguaggio del calcolatore è il linguaggio macchina.
La dichiarazione prevede di esprimere il tipo, il nome ed un eventuale valore di inizializzazione attraverso un assegnamento. In C le variabili vanno dichiarate prima di essere usate.
Overflow : quando si sfora il massimo numero rappresentabile da una determinata quantità di bit.
Undeflow : è l'incapacità di rappresentare un valore reale troppo piccolo, che viene quindi rappresentato come zero. Lezione 5 – Programmazione in Linguaggio C (lezione 5) Variabile Ha esistenza limitata. Inizia ad esistere dalla sua dichiarazione e cessa alla chiusura del blocco in cui è stata dichiarata. Scope : è l'ambito di visibilità, cioè dove la variabile può essere usata all'interno del programma (in quale blocco visibile si può usare).
Il valore di un'espressione cambia in base a: Costante : il suo valore. Variabile : il suo valore corrente, cioè l'ultimo valore assegnatole. Funzione : il valore restituito, cioè il risultato della funzione. Espressione composta : il valore ottenuto eseguendo l'operazione indicata dall'operatore sui valori degli operandi.
L’operatore modulo % è definito solo tra operandi di tipo intero. L’operatore divisione intera / denota la divisione intera se ha operandi interi, la divisione reale se almeno uno degli operandi è un float o double.
I tipi di dato possono essere in relazione gerarchica tra di loro. In caso di ambiguità ci sono delle promozioni implicite. Per esempio, in C esiste una gerarchia tra char che è contenuto in int e sappiamo che int è contenuto in float , che è contenuto in double.
Regole di conversione implicite e operatori espliciti di conversione. La conversione implicita avviene quando: un'espressione composta ha operandi di tipo diverso. un assegnamento ha tipo r-value e l-value diversi. una chiamata a funzione ha argomenti di tipo diverso dai parametri corrispondenti. un'istruzione return è seguita da un'espressione di tipo diverso dal tipo del risultato della funzione. La regola di conversione è che si converte al tipo più ampio.
Variabili (e costanti) hanno associato un tipo. La dichiarazione dei tipi delle variabili serve per riservare preventivamente in memoria lo spazio giusto alla variabile e per dirimere la grammatica tramite informazioni addizionali. Tipi elementari : informazioni composte da un solo valore (numeri, caratteri). Tipi strutturati : informazioni composte da più valori concettualmente legati (aggregazioni di più valori che sono concettualmente legati tra di loro anche se sono di tipi diversi vengono definiti dall'utente).
Numeri interi (short, int e long).
Le variabili dichiarate all’interno di una funzione in generale si chiamano variabili locali o automatiche , mentre quelle dichiarate fuori sono globali. Una variabile va dichiarata prima di usarla. Quando dichiaro una variabile dichiaro il tipo e il suo nome che si chiama anche identificatore.
Un identificatore è un elemento lessicale della grammatica del C che può essere definito a piacere dal programmatore ma deve rispettare delle regole. Oltre che come nomi delle variabili, può essere usato come nome di funzioni. La definizione di un identificatore può essere qualunque cosa che non è una keyword, non deve iniziare con numeri e non deve avere spazi. Sono case sensitive.
È un operatore e quindi ha un valore. È associativo destro. Ha un effetto secondario (side effect) ovvero modifica il valore dell'operando a sinistra. Si materializza dopo la valutazione del valore di “=” prima prende il valore di destra e poi lo mette in una variabile che sta a sinistra. isdigit è una funzione che controlla se una variabile è una cifra (ctype.h). L’assegnamento si può comporre con gli altri operatori aritmetici (+=, -=, *=, /=). Esempio : variabile += espressione, equivale a variabile = variabile + (espressione).
L'operatore ++ (incremento) incrementa di 1 una variabile intera L'operatore -- (decremento) decrementa di 1 una variabile intera Si possono usare prefissi (++i e --i) o postfissi (i++ e i- -). Se prefissi , eseguono l'operazione subito, se postfissi la eseguono per ultima prima dell'istruzione seguente. Lezione 6 – Programmazione in Linguaggio C (lezione 6)
%[*][width][modifiers] [] : indicano elementi opzionali. ***** : terminatore, serve per ignorare quello che viene letto nel formato che segue. Width : numero di caratteri da leggere. Modifiers : modificatore di dimensioni (di tipo). Type : come solito d, c, e, f, g, s(stringa), u (unsigned int), o (intero ottale), x (intero esadecimale) Primo parametro : specificatore di formato del secondo parametro. Esempio : scanf ("%d", &numero); Il primo parametro è la stringa "%d" mentre il secondo parametro è &numero.
Scanf legge il tipo e come deve interpretare quello che noi scriviamo su tastiera. Ritorna un intero.
L’input da tastiere resta in un buffer fino a che qualcuno non lo rimuove. Scanf cerca nel buffer un pattern (numeri, caratteri, ecc) e si prende quello che riconosce (elimina di solito gli spazi bianchi prima).
Operatore ternario (espressione1? espressione2 : espressione3 ). Si valuta espressione1, se vera si valuta espressione2, altrimenti si valuta espressione3. Posso anche assegnare il valore dell’operatore ternario ad una variabile. L'operatore ternario produce un valore.
Ogni else si riferisce all'if più vicino non ancora accoppiato. Non produce valore e genera biforcazione di flusso poiché decide quale blocco di codice eseguire in base alla condizione dell'if.
L'istruzione switch consente di separare blocchi alternativi che corrispondono ai singoli valori possibili per un'espressione. Si usa se ho tante alternative. Il blocco default corrisponde ai casi non elencati esplicitamente, cioè all'ultimo else. Può mancare. Funzionamento si valuta l'espressione, si cerca la costante di valore uguale all'espressione e se c'è, si eseguono le istruzioni associate alla costante e quelle associate a tutte le costanti successive, altrimenti si eseguono le istruzioni associate a default. Per eseguire le istruzioni associate a una sola costante, occorre terminarle con l'istruzione break che fa uscire dal costrutto (break salto incondizionato).
for (<espr-iniz>; <espr-cond>; <espr-incr>)
Ha un valore e combina più espressioni singole in un'unica sola. Ha la priorità più bassa Si valutano le espressioni da sinistra a destra. Il suo valore è il valore dell'ultima espressione.
L'istruzione continue provoca il passaggio all'iterazione successiva, ignorando il resto del corpo.
Si può dare un nuovo nome ai tipi di dato esistenti (predefiniti) allo scopo di chiarire il significato di un dato e facilitarne le modifiche. La definizione di tipo se inserita in un blocco vale solo nel blocco cui appartiene, altrimenti se inserita fra le direttive (fuori da tutto) vale per l'intero file (dichiarazioni globali).
Vettori mono o pluridimensionali (o array e matrici): valori omogenei associati a oggetti diversi identificati da uno o più indici. Strutture (o record): valori eterogenei associati a uno stesso identificati da nomi simbolici. Applicando sizeof a una variabile di tipo vettore o struttura si ottiene la memoria occupata dall'intero vettore o struttura.
Vettori : struttura (locazione consecutiva) contenente un dato numero di oggetti dello stesso tipo detti elementi. Hanno un unico nome e posso accedervi attraverso la loro posizione. Sono dati dal tipo e dal numero di elementi. È un tipo strutturato che finisce in memoria e ha un indirizzo (che è il primo elemento del vettore). I vettori vengono allocati in modo contigu o in memoria.
Accesso diretto : si specifica il vettore e l'indice dell'elemento è una caratteristica del vettore (è possibile farlo dato che sono contigui in memoria). L'indice di un vettore di N elementi va da 0 a N-1. In C non c‘è controllo che l'indice cada entro l'intervallo dichiarato quindi si può scrivere/leggere in aree di memoria incontrollate (tipica causa di errori ).
Un vettore può avere qualsiasi numero di dimensioni. Matrice : vettore a due o più dimensioni.
Allocazione di un array : alloca n posizioni di memoria consecutive ciascuna atta a contenere un dato di tipo indicato. L’allocazione non inizializza le posizioni di memoria allocate. I vettori multidimensionali sono memorizzati ordinati per righe. Per scandire tutta la matrice utilizzo due cicli (uno per le righe e uno per le colonne).
Stringa : è un vettore di caratteri terminato da terminatore di stringa quindi vettore + terminatore. Il terminatore è un carattere speciale ‘ \0’ e definisce un oggetto di stringa. Serve per sapere quando una stringa è finita ed è utile quando è necessario eseguire elaborazioni sulle stringhe.
Per la dichiarazione della stringa dovrò prevedere il posto del terminatore la dichiaro lunga un carattere in più. Una stringa termina col primo '\0' che contiene , anche se dichiarata di lunghezza superiore (se il terminatore è tra due parole, legge solo la prima perché poi termina). In C non c‘è controllo che una stringa contenga effettivamente il carattere '\0‘.
La stringa vuota contiene solo un carattere, cioè il terminatore nella posizione di indice
Esempio char str[5] = ‘‘Ciao’’; GIUSTO Esempio char str[4] = ‘‘Ciao’’; SBAGLIATO (perché ciao ha 4 caratteri + terminatore 1 carattere)
Dovremo predisporre un array di char di grandezza sufficiente a memorizzare la stringa digitata dall’utente. Si può dimensionare questo array usando la costante simbolica BUFSIZ (buffer size) definita in stdio.h la dimensione predefinita del buffer utilizzata per le operazioni di input/output è di 1024 byte
Scanf : legge la successione di caratteri proveniente dal terminale fino al primo carattere di spaziatura, di tabulazione o di ritorno a capo senza includere tale carattere nella stringa memorizzata. Fgets : legge la successione di caratteri proveniente dal terminale fino al primo carattere di ritorno a capo, includendo tale carattere nella stringa memorizzata. Include anche spazi e tabulazioni nella stringa letta. Entrambi aggiungono il terminatore in automatico alla fine.
&Str[0] è l'indirizzo del primo elemento del vettore. Stdin : indica che il buffer da cui dobbiamo leggere è la tastiera (standard input) lo gestisce il sistema operativo. Di base è la tastiera ma si può cambiare. fgets(str, BUFSIZ, stdin); in ingresso ha str, quanto grosso è il buffer da considerare, stdin che legge caratteri da un buffer qualsiasi.
La libreria string.h fornisce molte funzioni per gestire stringhe:
Main() : funzione principale. Le funzioni si possono comporre e i programmi possono invocare altre funzioni al fine di eseguire la computazione richiesta.
Sottoprogrammi : brani di codice abbastanza importanti da avere un nome, dei dati e nel caso dei risultati.