LABORATORIO DI ALGORITMI
E STRUTTURE DATI A-L
Ingegneria e scienze informatiche – Cesena
A.A: 2016/2017
Docente: Greta Sasso
Presentazione
Docente:
Greta Sasso
greta.sasso2@unibo.it
Orario e luogo delle lezioni:
Laboratorio Vela, Giovedì dalle 10 alle 13
Ricevimento :
Prima della lezione in laboratorio
Sito del corso: http://labasd1617.altervista.org/
Il corso
Obiettivi:
Sviluppare le capacità di base per lo sviluppo di
algoritmi efficienti per la risoluzione di problemi su
strutture dati complesse
Prerequisiti:
Conoscenza del linguaggio ANSI C
Descrizione progetto
È prevista una prova di laboratorio. Per poter accedere alla
prova scritta e necessario aver superato la prova di
laboratorio.
La prova di laboratorio consiste nello sviluppo di un progetto,
da realizzare in linguaggio ANSI C, con relativa relazione
scritta.
Il progetto deve essere consegnato obbligatoriamente entro
una settimana prima della prova scritta.
Una volta consegnato e corretto, il progetto resta valido per
tutte le prove scritte seguenti (per i successivi due anni solari).
Esempio di legenda per lo
pseudocodice
Strutture di controllo iterative (ciclo da 1 a n, incluso):
for espressione do
...//corpo
end for
while espr do
...//corpo
end while
if espr then
...//corpo
else
...//corpo
end if
Tempo di calcolo in secondi
Numero di istruzioni eseguite
Ripasso
Passaggio dei parametri - Indirizzo
Nel passaggio di parametri per riferimento/ indirizzo alla
funzione viene passato l’indirizzo e non il valore
dell’argomento.
Fornisce la possibilità di avere più valori di ritorno modificando
direttamente delle variabili esterne alla funzione ( passate non
per copia ma per indirizzo )
Per poter passare un indirizzo in fase di chiamata della
funzione occorrerà utilizzare dei parametri di tipo puntatore
void sum(int a , int b, int*ris){
*ris= a+b;
}
//chiamata
int a=4;
int ris;
sum(a,3, &ris);
printf(“%d\n“, ris);
//valore stampato: 7
Ripasso: Gli Array
Gli array/ vettori sono strutture dati in grado di memorizzare lo stesso
tipo di dati in modo sequenziale, accessibile con un unico nome
Statici: la dimensione è conosciuta sin dall’inizio e non può essere
modificata
Dinamici: Si può creare l’array in qualsiasi momento allocando
memoria nell’heap, e si ha la possibilità di modificare la dimensione.
Malloc: funzione che alloca un quantitativo di byte (parametro in input) e
restituisce l’indirizzo dell’area allocata ( della prima cella del vettore )
Realloc : funzione che realloca un’area di memoria con la possibilità che venga
cambiato completamente l’indirizzo di memoria precedente
Entrambe le funzioni possono fallire e in questo caso restituiscono NULL ( Controllo!)
Free : funzione utilizzata per deallocare un’area di memoria dato un indirizzo
Ripasso: I File
I file sono strutture sequenziali
Ogni riga termina con un carattere di newline ‘\n’. Al termine del
file si ottiene EOF
Per poter accedere ad un file occorre avere un collegamento ad
un file, quindi utilizzeremo i puntatori a FILE
Per aprire un file si utilizza la funzione fopen che vuole in ingresso il
nome del file ( stringa) e una stringa rappresentante la modalità di
apertura.
Per chiudere un file si utilizza la funzione fclose
I file: lettura
Modalità di apertura, read "r"
Nel caso in cui il file non esista o per altri problemi di I/O la funzione
fopen ritornerà il valore NULL ( Ricordarsi di controllare l’eventualità)
La lettura di un file corrisponde all’intenzione di ottenere dei dati in
input da una sorgente esterna. Con la funzione scanf siamo abituati a
ottenere dei dati in input da tastiera e a memorizzarlo nel nostro
programma. Per i file è la stessa cosa: si utilizza la funzione fscanf , fgets,
…
//apertura file in lettura
Esempio.txt
1 2 5 8 3
4 12 456 8
FILE* ptr;
int a;
Ptr = fopen("esempio.txt" , "r");
if ( ptr==NULL ) return (-1);
fscanf (ptr , “%d“, &a);
printf(“%d\n“, a);
//stampa del primo numero contenuto nel file: 1
Controllare la fine del file
• La funzione fscanf ritorna il valore EOF nel caso in cui si è
tentato di leggere qualcosa da un file, ma il file è stato già letto
tutto
• Int feof(FILE* f) : questa funzione accetta come parametro in
input il puntatore al file e come valore di ritorno 0 se non
raggiunto L’EOF, altrimenti un numero diverso da 0
I file: scrittura
Modalità di apertura, write " w" .
Se il file non esiste, questo sarà creato in automatico. Per problemi di I/O
la funzione fopen ritornerà il valore NULL ( Ricordarsi di controllare
l’eventualità).
La scrittura di un file corrisponde all’intenzione di ottenere dei dati in
output l mio programma verso il file. Con la funzione printf siamo abituati
stampare a video (output) dei dati . Per i file è la stessa cosa: si utilizza la
funzione fprintf, fputs,…
//apertura file in scrittura
FILE* ptr;
int a=5;
ptr = fopen("nuovo.txt" , "r");
if( ptr == NULL) return (-1);
fprintf(ptr,“ciao a tutti %d \n“, &a);
nuovo.txt
Ciao a tutti 5
IDE – Visual Studio
Visual Studio è un ambiente di sviluppo integrato (Integrated
development environment o IDE) sviluppato da Microsoft
Supporta diversi tipi di linguaggio: C, C++, C#, F#, Visual Basic
.Net, Html e JavaScript, … e che permette la realizzazione di
applicazioni, siti web, applicazioni web e servizi web
Esistono le versioni a pagamento ma anche le versioni gratuite
( Visual Studio Express) che presentano le funzionalità di base
Potenti strumenti a disposizione per il Debug dei programmi
Alternative : Code::Blocks, Devc++, …
Visual Studio – Nuovo progetto
File -> Nuovo Progetto ->
Visual c++ -> Progetto
Win32 Console
Application
Specificare il nome del
progetto
Confermare
o Next
o Selezionare il tipo di
applicazione «applicazione
console»
o Selezionare Progetto Vuoto
o Fine
o Una volta fatto questo il progetto sarà creato vuoto.
o Create quindi un file main.c all’interno della cartella File di Origine
o Cliccate col tasto destro -> aggiungi -> nuovo elemento
o Esecuzione di un programma:
Esecuzione di un programma:
Disabilitare Warnings di visual studio
A volte potrebbe capitare con l’utilizzo delle funzioni scanf, printf, fscanf, … di ottenere un errore del tipo
” This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use
_CRT_SECURE_NO_WARNINGS. See online help for details”
Per eliminare questi warnings andare nelle proprietà del progetto
Inserire la stringa
_CRT_SECURE_NO_WARNINGS
E confermare le modifiche
NB: Per modificare questa voce occorre aver
Creato prima almeno un file .c / .cpp
1) Leggere da un file di testo 10 numeri interi, memorizzarli
all’interno di un vettore e calcolare la somma degli elementi.
- Solo in questo step si dia per scontato che il file contenga almeno 10
numeri interi
- Il file lo potete creare e inserire nella cartella del vostro progetto. Ad
esempio :
..Studio 2015\Projects\Esercizio1\Esercizio1 oppure da
visual studio nella cartella resource ( risorse) del progetto
2° step: Preso in input da tastiera un numero positivo leggere da
un file quel quantitativo di numeri memorizzandoli all’interno di un
vettore, e calcolare il valore medio.
[ Esercizi Proposti – 1.1 ]
L’esercizio sembra semplice, ma occorre considerare alcuni casi
che si potrebbero verificare portando a situazioni impreviste, ad
errori o a interruzione del programma:
Cosa succede se l’utente inserisce un numero negativo come
dimensione?
Cosa succede se l’utente inserisce un carattere e non un intero?
Cosa succede se nel file non sono presenti abbastanza numeri?
Cosa succede se il file non esiste o se non è più disponibile
memoria nel programma?
Analisi del problema
Testing dei programmi
Obiettivo di eliminare eventuali
malfunzionamenti tramite l’esecuzione del
codice stesso
Progettazione di test: selezionare dei casi
significativi di input e verificare porzioni di
codice critiche e output finali
Debugging : per localizzare e rimuovere i
problemi che causano i malfunzionamenti
Debugging con visual studio
Stampa di messaggi a video per monitorare
l’esecuzione
Debug
• Per aggiungere un punto di interruzione ( breakpoint) cliccare in
corrispondenza della linea di codice di cui si vuole fermare
l’esecuzione, comparirà un pallino rosso.
• Per avviare il debug basta cliccare sul pulsante di avvio del
programma visto in precedenza.
Utility – Numeri Pseudo Casuali
//srand( 550 ); // inizializzazione
srand( time( NULL )); // inizializza con orologio(casuale)
printf("%d\n", rand() % (max+1));
double x=((double)rand()/(double)RAND_MAX); // compreso in
[0.0,1.0]
int a = rand()%100; // compreso in [0,100]
int b = rand()%100+50; // compreso in [50,150]
Utility – Stringa casuale
/*Generazione di una parola di una dimensione data. I
caratteri generati sono da a-z ( carattere minuscoli) */
char* randomWord( int dim) {
int i;
char* string = (char*)malloc((1 + dim) * sizeof(char));
if (string == NULL) return "random";
for (i = 0; i < dim; i++)
string[i] = rand() % 25 + 97; // ASCII code
string[i] = '\0';
return string;
}
Prima di iniziare
Con il crescere della complessità degli argomenti e degli
esercizi, gli algoritmi risolutivi non saranno immediati.
1) Analisi del problema: input output.
o È utile individuare esempi di input significativi per il problema
o Di grande aiuto è la decisione dei test già in questa fase
2) Progettazione dell’algoritmo
3) Implementazione
4) Testing e verifica
2) 3° step: Data la sequenza di numeri letta dal file, calcolare in
modo iterativo Il valore massimo, e il valore minimo, tramite
apposite funzioni.
Test significativi
Cosa succede se la sequenza è formata dal medesimo numero?
Cosa succede se la sequenza è formata da soli numeri negativi?
Calcolare il tempo di esecuzione e il numero di istruzioni eseguite per i cicli
utilizzati nella ricerca del massimo e nella somma.
Come varia l’algoritmo se l’insieme degli elementi è ordinato in ordine
crescente? Quanto costa?
[ Esercizi Proposti – 1.2 ]
2) 5° step: Aggiungere la ricerca di un elemento sviluppando
una funzione che ritorni 1 o 0 nel caso in cui l’elemento sia
presente o meno all’interno del vettore.
[ Esercizi Proposti – 1.3 ]
Dati a e n numeri interi calcolare an usando un
algoritmo iterativo
[ Esercizi Proposti – 1.4 ]
Domande e discussione
Domande?