Applicazioni di programmazione strutturata

OBIETTIVO DELLA LEZIONE
  1. Comprendere il significato della programmazione strutturata ed il suo utilizzo per creare programmi riusabili, facilmente comprensibili e correggibili;
  2. Webserver generatore di pagine dinamiche:
    essere in grado di realizzare un programma per la generazione automatica di pagine HTML;
  3. Analisi automatica dei file di log di un server APACHE (Profiling):
    programmi per la scansione automatica di file formattati e l'estrazione automatica di informazioni da un file testuale di un log di un server.
.:. LUCIDI DELLA LEZIONE .:.
.:. NOTE DELLA LEZIONE parte A .:.
.:. NOTE DELLA LEZIONE parte B .:.

Note

Nozioni base di html

Solo alcuni concetti HTML verranno usati in questo corso:

In questo corso non ci soffermiamo su argomenti come l'uso dei colori e dei font.
La nostra di filosofia nella creazione nel file di testo con estensione .html o .htm (che per brevita' viene chiamato pagina) è quella di separare il contenuto informativo dagli aspetti grafici.

Tutti gli aspetti grafici della pagina mia opinione che debbano essere contenuti in un altro file chiamato Cascading Style Sheets (vedi CSS).

Un esempio riassuntivo

Dopo aver seguito con attenzione le pagine sull'HTML suggerite avendo posto attenzione alle nozioni richieste non ci saranno problemi ad immaginare cosa eseguira' questo codice html nel file paginaRiassuntiva.htm.

Una pagina semplicissima

<HTML>
<HEAD>
<TITLE>La mia prima pagina web!</TITLE>
</HEAD>
<BODY>


</BODY>
</HTML>

Una pagina già utile a noi

codice

che diventa nel browser

Vista

Uso dei CSS

Se modifico leggermente SOLO l'intestazione del nostro file di testo e salvo nella stessa directory un file di tipo .CSS l'aspetto della visualizzazione può radicalmente cambiare (cambiando una sola riga di codice e riusando un file .css gia' scritto in precedenza)

<HTML>
<HEAD>
<TITLE>La mia prima pagina web!</TITLE>
</HEAD>
<BODY>

...

</BODY>
</HTML>

Facendolo diventare cosi':

<HTML>
<HEAD>
<TITLE>La mia prima pagina web!</TITLE>

<link rel="STYLESHEET" type="text/css" href="ccsFabioSicurezza.css" />

</HEAD>
<BODY>

...

</BODY>
</HTML>

Viene visualizzata così:

Vista CSS

Vi sono molte altre cose da considerare per scrivere correttamente pagine html, ma per il nostro corso bastano queste.

Immagini

Richiamo solo come includere una immagine:

	<img src="img/paginaRiassuntoVistaCSS.gif"   />
	

Come creare funzioni che scrivono in un file aperto nel main()


Perché una funzione possa scrivere in un file ha bisogno solo di due cose:

  1. Che il file sia stato aperto correttamente
  2. Che si abbia a disposizione il puntatore a file (che va immaginato come un indice che dice a quale dei file aperto la printf deve "puntare")
Pertanto se abbiamo una funzione che stampa a video qualche cosa come la seguente:
void stampaTabella(int base ){
    int i;
    for (i=1;i<11;i++)
    {	
        printf( "  %3d  ---> %3d \n", i , i * base );
    }
}
e volessimo invece farla stampare su un file allora dovremmo modificare il codice in questo modo:
  1. Nel main dichiaro la variabile puntatore (Fp1) e apro il file in scrittura/creo il file.
    int main()
    {
    	char nomefile[]="TABELLA.TXT"	;
    	FILE *          Fp1 ;
     	
    	// Apro il file in modalita' write il file di testo
    	Fp1 = fopen(nomefile, "w");
    	if (Fp1==NULL){
    		printf("File %s not found\n", nomefile);
    		exit(-1); 
    	}
    	...
    		
    
  2. Modifico la funzione nel seguente modo.
    void stampaTabella(int base  , FILE *  Fp1 ){
        int i;
        for (i=1;i<11;i++)
        {	
            fprintf(Fp1,  "   %3d    ---> %3d \n", i, i * base );
        }
    }
    		
    
  3. A questo punto modifico la definizione della funzione e la sua chiamata in
    	stampaTabella( base,  Fp1 );
    
    Ecco la soluzione completa:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void stampaTabella(int Base, FILE *  Fp1 );
    
    int main()
    {
    	int base;
    	
        char nomefile[]="TABELLA.TXT"	;
    	FILE *          Fp1 ;
     	
    	// Apro il file in modalita' write il file di testo
    	Fp1 = fopen(nomefile, "w");
    	if (Fp1==NULL){
    		printf("File %s not found\n", nomefile);
    		exit(-1); 
    	}
    		
    	scanf("%d", &base);
    	stampaTabella( base,  Fp1 );
    	
    	close (Fp1);
     	exit(0);
    }  // main
    
    void stampaTabella(int base  , FILE *  Fp1 ){
        int i;
        for (i=1;i<11;i++)
        {	
            fprintf(Fp1,  "   %3d    ---> %3d \n", i, i * base );
        }
    }
    
    
  4. A questo punto la procedura void stampaTabella(int Base, FILE * Fp1 ); ci permette di stampare quello che vogliamo in un qualunque file di testo di cui passiamo il puntatore.

    Lab

    Prima di iniziare

    Rileggi velocemente il riassunto della lezione di stamattina che trovi in questa pagina (sezione Note). I costrutti presentati saranno molto utili per risolvere gli esercizi di oggi.

    Esercizio 1: Programma che genera una tabella in un file di testo .htm
    Crea il programma CreaFileHtml1.c che salvi su disco il file index1.html contenente:
    1. un titolo (usa il TAGHTML <h1> );
    2. un paragrafo (usa il TAGHTML <p>) contenente una tabella con le prime 4 righe della tabellina (tavola pitagorica) del 9 seguita da un tuo breve commento.


    soluzione.
    Esercizio 2: Programma per creazione di una tabella delle potenze di 2
    Scrivi il programma CreaFileHtml2.c che crea il file index2.html concatenando delle stringhe costanti.
    Le fasi devono essere le seguenti:
    1. stampa nel file l'HEADER;
    2. stampa il primo pezzo del BODY;
    3. stampa le parti iniziali di una tabella con due colonne;
    4. stampa con un ciclo gli elementi di una riga per 10 volte (indice, potenza di 2, potenza di 3);
    5. chiude la tabella;
    6. chiude BODY;
    7. chiude HEADER.
    Suggerimento
    Ad esempio per stampare la prima riga della tabella potresti usare del codice simile al seguente:
    fprintf(Fp1, "\n\
    <td></td>\n\
    <td>2</td>\n\
    <td>3</td>\n\
    </tr>\n");
    
    Il carattere ' \' serve per far andare a capo una stringa e renderla leggibile.
    Il tuo file index2.html, aperto con un browser, dovrebbe essere visualizzato nel seguente modo:



    soluzione.
    Esercizio 3: Includere testi in un file HTML automaticamente
    Per lo svolgimento di questo esercizio è necessario il file prima.htm. Effettua il download del file prima.htm (1 KB).

    Usando NOTEPAD o un equivalente editor di testo (ma non il browser!) apri il file prima.htm e salvalo in tre file di testo disgiunti aventi le seguenti caratteristiche:
    1. parteHeader.inc dal primo carattere di prima.htm fino alla dichiarazione della tabella con <TABLE> NON inclusa
    2. tabella.inc la parte fra i TAG della tabella (TAG inclusi)
    3. footer.inc da dopo l'ultimo tag della tabella alla fine del file
    Utilizzando la traccia di codice sotto riportato crea il programma assembla.c che legge i tre file in sequenza e crea un file di testo primatabellaC.htm con la concatenazione dei tre file .inc. Fai attenzione alla gestione del file:
    • se i tre file .inc non esistono il programma deve riportare un errore "file %s non trovato" ;
    • se il file primaC.htm è già esistente deve essere sovrascritto.
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main()
    {
    	
    	char c;        // buffer temporaneo per il carattere letto
    	
    	char nomefile1[]="parteHeader.inc"	;
    	char nomefile2[]="tabella.inc"	;
    	char nomefile3[]="footer.inc"	;
    	char nomefileMerge[]="primatabellaC.htm"	;
    	FILE *          Fp1 ;
     	FILE *          Fp2 ;
     	FILE *          Fp3 ;
     	FILE *          FpMerge ;
     	
     	/* proseguire
     	.....    */
    	
     	exit(0);
    }  // main
    

    Suggerimento
    Se hai programmato correttamente apri il file creato dal tuo programma e controlla cosa vedi. Apri la prima volta il file sempre con l'editor di testo e con il browser solo le successive volte, altrimenti corri il rischio di non individuare gli errori: molti browser correggono automaticamente gli errori presenti nelle pagine pur di visualizzarli (tag non chiusi, ecc..).

    soluzione.
    Esercizio 4: Scansione di un file di log di un server APACHE - parte I
    Per lo svolgimento di questo esercizio è necessario il file t2anonimizzato.txt. Effettua il download del file t2anonimizzato.log (1 KB).

    Partendo dal programma scansioneLog.c sotto riportato, salva il log con il nome t2anonimizzato.txt e sviluppa le seguenti attività:
    1. visualizza l'ip delle persone collegate;
    2. visualizza la pagina richiesta dall'utente.
    //scansioneLog.c
    #include <stdio.h>
    #include <string.h>
    
    
    int main()
    {
    	int base;
    	char c;
    	
    	int ip1, ip2, ip3, ip4 ;
     	char data[256];
     	char operation[256];
     	char page[256];
       	 	
           char nomefile[]="t2.log";
    	FILE *  Fp1;
     	
    	// Apro il file in modalita' read il file di testo
    	Fp1 = fopen(nomefile, "r");
    	if (Fp1==NULL){
    		printf("File %s not found\n", nomefile);
    		exit(-1); 
    	}
    
        	while ( fscanf(Fp1, "%d.", &ip1  ) > 0 )
        	{ 
    
            	// approccio non molto raffinato ... esiste il tipo
            	// di dato per rappresentare correttamente un IP in C   
    
            	fscanf(Fp1, "%d.%d.%d",  &ip2, &ip3, &ip4 );
            	fscanf(Fp1, " - - [%s +0200] %s", data , operation);
            	fscanf(Fp1, " %s HTTP/1.1", page);
                  
            	printf(  "%d.%d.%d.%d \n", ip1, ip2, ip3, ip4 );
            	printf(  "  data:      %s  \n", data  );
            	printf(  "  operation: %s  \n", operation  );
            	printf(  "  page:      %s  \n", page  );
            
     	       // per adesso vado elegantemente fino in fondo alla riga.... ma non e' cosi'....
           		while ( fscanf(Fp1, "%c", &c ) > 0 )
            	{
                		if (c ==  '\n' )  break;
           //    printf("%c" , c);  Se volessi vedere il contenuto restante del log ...
            	}           
                
            	printf( " \n\n\n" );
        	}
    
    	getchar();
    	fclose (Fp1);
     	exit(0);
    }  // main
    




    Suggerimento:
    Se hai programmato correttamente l'uscita del programma, a monitor dovresti avere una situazione simile al seguente esempio:

    84.11.41.177
      page:      /~liberali/anybrowser3.jpg
    


    soluzione.
    Esercizio 5: Scansione di un file di log di un server APACHE - parte II
    Per lo svolgimento di questo esercizio è necessario il file t2anonimizzato.log. Effettua il download del file t2anonimizzato.txt (1 KB).

    Partendo dal programma scansioneLog.c sotto riportato, salva il log con il nome t2.log e sviluppa le seguenti attività: Con riferimento al programma scansioneLog2.c sottoriportato esegui una scansione riga per riga dell'elenco contenuto nel file di log t2.log ed estrai le seguenti informazioni:
    1. conta il numero di elementi che sono stati richiesti al server come pagine, immagini, ecc... (cioè il numero di righe) ;
    2. conta il numero di utenti connessi (successione semplice) nel modo seguente:
      159.149.67.22     Conta = 1 
      159.149.67.22     Conta = 1 (non e' cambiato dal precedente)
      159.149.67.22     Conta = 1 (non e' cambiato dal precedente)
      151.42.178.106    Conta = 2
      151.42.178.106    Conta = 2 (non e' cambiato dal precedente)
      151.42.178.106    Conta = 2 (non e' cambiato dal precedente)
      151.42.178.106    Conta = 2 (non e' cambiato dal precedente)
      159.149.67.22     Conta = 3 
      151.42.178.106    Conta = 4 
      159.149.67.22     Conta = 5 
      
    3. conta quante volte sono richieste nel file di log t2.log
      - le pagine php
      - le pagine htm o html
      - le immagini png
      - la pagina home /

    4. conta il numero medio di oggetti richiesti dagli utenti come il rapporto fra il numero di righe (calcolato al punto b) ed il numero di utenti (calcolato al punto a)

      Codice del programma da usare come traccia:
      //scansioneLog2.c
      #include <stdio.h>
      #include <string.h>
      
      
      int main()
      {
      int base;
      char c;
      
      int ip1, ip2, ip3, ip4 ;
      	char data[256];
      	char operation[256];
      	char page[256];
        	 	
        	char nomefile[]="t2.log";
      FILE * Fp1 ;
      	
      // Apro il file in modalita' read il file di testo
      Fp1 = fopen(nomefile, "r");
      if (Fp1==NULL){
      	printf("File %s not found\n", nomefile);
      	exit(-1); 
      }
      	
      
      
        	 while ( fscanf(Fp1, "%d.", &ip1  ) > 0 )
         	{ 
      
            		// approccio non molto raffinato ... esiste il tipo
             	// di dato per rappresentare correttamente un IP in C   
      
          	fscanf(Fp1, "%d.%d.%d",  &ip2, &ip3, &ip4 );
            		fscanf(Fp1, " - - [%s +0200] %s", data , operation);
             	fscanf(Fp1, " %s HTTP/1.1", page);
                  
            // l'esercizio inizia qui
             
       	       	printf(  "%d.%d.%d.%d \n", ip1, ip2, ip3, ip4 );
               	printf(  "  data:      %s  \n", data  );
             	printf(  "  operation: %s  \n", operation  );
             	printf(  "  page:      %s  \n", page  );
             
             	// per adesso vado elegantemente fino in fondo alla riga.... ma non e' cosi'....
            while ( fscanf(Fp1, "%c", &c ) > 0 )
                   {
                 		if (c ==  '\n' )  break;
                 		printf("%c" , c);
                   }           
                 
             	printf( " \n\n\n" );
         	}
      
      getchar();
      fclose (Fp1);
      	exit(0);
      }  // main
      


    Suggerimento
    La struttura del codice va già bene. Sostituisci con opportuno codice il codice presente nella traccia del ciclo WHILE posto sotto il commento
    // per adesso vado elegantemente fino in fondo alla riga.... ma non e' cosi'....
    
    

    soluzione.
    Esercizio 6: Scansione di un file di log di un server APACHE - parte III
    Per lo svolgimento di questo esercizio è necessario il file t2anonimizzato.log. Effettua il download del file t2anonimizzato.txt (1 KB). Salva il log con il nome t2.log

    Dal file di log t2.log scrivi il programma profiling1.c che individua tutte le pagine richieste e la data/ora che l'utente 84.11.41.177 ha richiesto al server (l' IP è inventato, ma se dovesse corrispondere realmente ad una macchina trattasi di una circostanza non voluta).
    Le informazioni devono essere salvate in un file di nome 84_11_41_177.txt nel seguente formato:
    Pagine navigate dall'utente 84.11.41.177
    02/Apr/2004:10:39:52 +0200  pagina: / 
    02/Apr/2004:10:39:52 +0200  pagina: /css/dtiweb.css 
    02/Apr/2004:10:39:52 +0200  pagina: /js/menu.php 
    02/Apr/2004:10:39:53 +0200  pagina: /js/cerca.php 
    02/Apr/2004:10:39:53 +0200  pagina: /js/pos.js 
    02/Apr/2004:10:39:54 +0200  pagina: /img/titolo1.png 
    02/Apr/2004:10:39:54 +0200  pagina: /img/titolo2.png 
    02/Apr/2004:10:39:55 +0200  pagina: /img/fronte.jpg 
    02/Apr/2004:10:39:59 +0200  pagina: /listapersone.php?z=0;gruppo=Docenti 
    02/Apr/2004:10:39:59 +0200  pagina: /js/menu.php 
    02/Apr/2004:10:40:00 +0200  pagina: /js/cerca.php 
    ecc..
    


    Suggerimento
    Dopo aver aperto il file t2.log è sufficiente scandirlo con una fscanf fino a trovare una richiesta dell'utente 84.11.41.177.
    Copia nel file 84_11_41_177.txt tutta la riga: procedi fino alla fine del file, iterando la scansione e copiando le righe individuate.

    soluzione.
    Esercizio 7: Stampa di una tabella (TAVOLA PITAGORICA)
    Realizzare una procedura void stampaTabella(int Base) che stampa a monitor la tabellina di ordine 10 (tavola pitagorica) relativa al numero intero passato. Il numero passato deve essere maggiore di zero e minore di 100.
    Per controllare il corretto funzionamento della funzione scrivi un breve programma tabellaMonitor.c che chiede all'utente il parametro da passare alla funzione.
    Di seguito è riportato un esempio dell'uscita del programma quando sia stata invocata la funzione stampatabella (9);
    --------------------
    | tabellina del 9  |
    --------------------
    |  1     |   9     |
    |  2     |   18    |
    
    .... ecc
    


    Suggerimento
    Leggi attentamente la traccia di codice di seguito riportata che può supportarti nello svolgimento di questo esercizio:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void stampaTabella(int Base);
    
    int main()
    {
    	/* proseguire
     	.....    */
    	
     	exit(0);
    }  // main
    
    void stampaTabella(int Base){
    	/* proseguire
     	.....    */
    }
    


    soluzione.
    Esercizio 8: Stampa di una tabella IN UN FILE (TAVOLA PITAGORICA)
    Modifica il programma sotto riportato e salvalo come tabellaMonitor2.c perchè stampi la tabella (tavola pitagorica) calcolata su un file di nome TABELLA.TXT.
    //tabellaMonitor2.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void stampaTabella(int Base);
    
    int main()
    {
    	
    	
     	/* proseguire
     	.....    */
    	
     	exit(0);
    }  // main
    
    
    void stampaTabella(int Base ){
    	
    	char nomefile[]="TABELLA.TXT"	;
    	FILE *          Fp1 ;
     	
    .....................................
    .....................................
    .....................................
    
    }
    

    Suggerimento
    Per svolgere questo esercizio può esserti utile ripensare a come hai svolto il precedente esercizio.
    E' sufficiente aprire il file "TABELLA.TXT", inoltre nella funzione void stampaTabella(int Base) sostituisci le printf con delle fprintf, passando alla funzione fprintf anche puntatore al file "TABELLA.TXT" .

    soluzione.
    Esercizio 9: Stampa di una tabella IN UN FILE (TAVOLA PITAGORICA) parte II
    Modifica la traccia di codice tabellaMonitor3.c sotto riportata e salvala con il nome tabellaMonitor3.c perché stampi la tabella (tavola pitagorica) su un file di nome TABELLA.TXT. Presta attenzione al nome del file: nella traccia di codice è dichiarato all'interno della funzione stampatabella(). Riscrivi la funzione affinché il nome del file possa essere passato dal main attraverso un puntatore a file.
    //tabellaMonitor3.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void stampaTabella(int Base, ...);
    
    int main()
    {
    	
    	
     	/* proseguire
     	.....    */
    	
     	exit(0);
    }  // main
    
    void stampaTabella(int Base, ...){
    	
    	char nomefile[]="TABELLA.TXT"	;
    	FILE *	Fp1 ;
     	
    .....................................
    .....................................
    .....................................
    
    }
    





    Soluzione
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    void stampaTabella(int Base, FILE *  Fp1 ); // passo il puntatore
    
    int main()
    {
    	int base;
    	
    	char nomefile[]="TABELLA.TXT"	;
    	FILE * Fp1 ;
     	
     	/* proseguire
     	.....    */
    	
     	exit(0);
    }  // main
    
    /*  scrivere qui la procedura che stampa la tabellina */
    
    


    soluzione.




    Informazioni sul sito