LABORATORIO DI ALGORITMI E STRUTTURE DATI A-L Ingegneria e scienze informatiche – Cesena A.A: 2016/2017 Docente: Greta Sasso Presentazione Docente: Greta Sasso [email protected] 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?