A partire dalle prossime lezioni cominceremo ad occuparci di PHP,
un linguaggio di scripting integrato nell'HTML e
particolarmente adatto allo sviluppo di applicazioni Web.
Per poter partecipare alle esercitazioni occorre avere un account sulla macchina
server.
Vi suggeriamo di richiederlo al più presto in WEBLAB (Lab. Von Neumann).
Per informazioni:
http://php.weblab.crema.unimi.it
OBIETTIVI DELLA LEZIONE
In questa lezione:
- comprenderemo con più precisione le direttive al preprocessore #include e #define
- impareremo ad operare con i files
- vedremo come passare delle informazioni ad un programma dalla linea di comando
In molti esercizi visti nelle scorse lezioni abbiamo trovato comandi del tipo
#define LUN 10
(ad esempio nel file massimoCompito.c), oppure
#include <stdio.h>
(ad esempio nel file
MassimoFunzionale2Compito.c).
Nella prima lezione avevamo accennato come queste "direttive" siano
indirizzate al preprocessore.
#include <stdio.h> #define LUN 3 int calcolaMassimo(int numeri[]); int main() { int num, i, massimo; int numeri[LUN]; for (i = 0; i < LUN; i++) scanf("%d", &numeri[i]); massimo = calcolaMassimo(numeri); printf("massimo=%d\n", massimo); fflush(stdin); getc(stdin); } int calcolaMassimo(int numeri[]) { int massimo, i; massimo = numeri[0]; for (i = 1; i < LUN; i++) if (massimo < numeri[i]) massimo = numeri[i]; return massimo; }Potrebbe essere sostituito dai due files:
#include "TrovaMassimo2.h" int main() { int num, i, massimo; int numeri[LUN]; for (i = 0; i < LUN; i++) scanf("%d", &numeri[i]); massimo = calcolaMassimo(numeri); printf("massimo=%d\n", massimo); fflush(stdin); getc(stdin); }e
#include <stdio.h> #define LUN 3 int calcolaMassimo(int numeri[]); int calcolaMassimo(int numeri[]) { int massimo, i; massimo = numeri[0]; for (i = 1; i < LUN; i++) if (massimo < numeri[i]) massimo = numeri[i]; return massimo; }Notate che quando vogliamo includere un file standard (ad esempio stdio.h) il nome va racchiuso tra parentesi angolari (<nomefile.h>), mentre se è un file creato da noi (ed è contenuto nella stessa cartella del file che stiamo editando) va racchiuso tra doppi apici (" nomefile.h "). Altrimenti dobbiamo specificare il percorso completo.
#include "TrovaMassimo3.h" int main() { int num, i, massimo; int numeri[LUN]; for (i = 0; i < LUN; i++) scanf("%d", &numeri[i]); massimo = calcolaMassimo(numeri); printf("massimo=%d\n", massimo); TIENI_APERTA_FINESTRA }e
#include <stdio.h> #define LUN 3 #define TIENI_APERTA_FINESTRA {fflush(stdin); \ getc(stdin);} int calcolaMassimo(int numeri[]); int calcolaMassimo(int numeri[]) { int massimo, i; massimo = numeri[0]; for (i = 1; i < LUN; i++) if (massimo < numeri[i]) massimo = numeri[i]; return massimo; }
Come utilizzare le funzioni contenute nelle librerie standard?
L'elenco delle funzioni è molto lungo. E' utile però avere un'idea di cosa ci sia di già pronto. Per questo vi suggeriamo di scorrere un file di help e sfogliare un buon manuale (insostituibile).
Iniziamo considerando un file su disco. Operare con un file significa:
// scriviconsole.c scrive in un file tutto quello che // viene digitato da console #include <stdio.h> #include <stdlib.h> #define NOME_FILE "console.txt" main() { FILE *file_out; char c; file_out = fopen(NOME_FILE, "w"); if(file_out == NULL) { printf( "Non trovo il file.\n" ); exit(-1); } printf("(Per terminare premi @)\n\n"); c=getchar(); while(c != '@') { fputc(c, file_out); c=getchar(); } fclose(file_out); }
r | sola lettura. Se il file non esiste ritorna NULL. |
w | scrittura. Se manca il file viene creato, altrimenti il contenuto viene distrutto. |
a | scrittura dalla fine del file. Se manca il file viene creato. |
r+ | lettura e scrittura. Se il file non esiste ritorna NULL. |
w+ | lettura e scrittura. Se manca il file viene creato, altrimenti il contenuto viene distrutto. |
a+ | lettura e scrittura dalla fine del file. Se manca il file viene creato. |
Si sta come d'autunno sugli alberi le foglie.
// contacaratteri.c conta i caratteri contenuti in un file #include <stdio.h> #include <stdlib.h> #define NOME_FILE "soldati.txt" main() { FILE *file_in; unsigned long numero_caratteri; file_in = fopen(NOME_FILE, "rt"); if(file_in == NULL) { printf( "Non trovo il file.\n" ); exit(-1); } numero_caratteri=0; while(fgetc(file_in) != EOF) numero_caratteri++; printf("[testo]: Il file e' composto da %u caratteri\n", numero_caratteri); fclose(file_in); file_in = fopen(NOME_FILE, "rb"); if(file_in == NULL) { printf( "Non trovo il file.\n" ); exit(-1); } numero_caratteri=0; while(fgetc(file_in) != EOF) numero_caratteri++; printf("[binaria]: Il file e' composto da %u caratteri\n", numero_caratteri); fclose(file_in); }
C:\>contacaratteri.exe [testo]: Il file e' composto da 46 caratteri [binaria]: Il file e' composto da 50 caratteriIn modalita' testo i caratteri prima di essere posti nel buffer vengono interpretati. Ad esempio il fineriga (composto dai due caratteri LF [Line Feed: 10 o '\n'] e CR [Carriage Return: 13 o '\r']) viene trasformato in LF. In modalità binaria non viene operata nessuna trasformazione.
// stampablocco.c stampa un blocco di caratteri #include <stdio.h> #include <stdlib.h> #define NOME_FILE "soldati.txt" #define PRIMO_CARATTERE 10 #define ULTIMO_CARATTERE 30 main() { FILE *file_in; unsigned long numero_caratteri_stampati, numero_caratteri_da_stampare; int carattere_letto; // Apro il file file_in = fopen(NOME_FILE, "rt"); if(file_in == NULL) { printf( "Non trovo il file.\n" ); exit(-1); } // Salto al PRIMO_CARATTERE if( fseek(file_in, PRIMO_CARATTERE-1, SEEK_SET) != 0 ) { printf( "Non riesco a posizionarmi.\n" ); exit(-1); } numero_caratteri_stampati=0; numero_caratteri_da_stampare=ULTIMO_CARATTERE-PRIMO_CARATTERE+1; while( ((carattere_letto=fgetc(file_in)) != EOF) && (numero_caratteri_stampati<numero_caratteri_da_stampare) ) { numero_caratteri_stampati++; printf("%c",(char) carattere_letto); } // Avverto se non ho potuto stampare tutto if(numero_caratteri_stampati<numero_caratteri_da_stampare) printf("Attenzione, EOF raggiunto. Stampati solo %d caratteri", numero_caratteri_stampati); // Chiudo il file fclose(file_in); }Attenzione che se devo leggere il 10 carattere devo saltare di 9 (non 10) caratteri! E' come se il file fosse un array e la numerazione partisse da 0. Le possibili posizioni da cui spostarsi sono:
SEEK_SET | Inizio del file |
SEEK_CUR | Posizione corrente |
SEEK_END | Fine del file |
// questo programma vi fa famigliarizzare con le // strutture dati dei FILE (cosa e' un puntatore a file) // scrive in un file in modalita' append // legge da un file dall'inizio fino all'ultima sua stringa #include <stdio.h> #include <stdlib.h> int main() { char nome[256], cognome[256], tel[256]; char finito; char nomefile[]="rubrica.txt" ; FILE *Fp1; // Apro il file in modalita' append testo Fp1 = fopen(nomefile, "a"); if (Fp1==NULL){ printf("File %s not found\n", nomefile); exit(-1); } printf("Il puntatore (*Fp) al file %s e' %d\n\n", nomefile, Fp1); finito='n'; while((finito=='n') || (finito=='N')) { printf("Inserire Nome: "); scanf("%s", nome); printf("Inserire Cognome: "); scanf("%s", cognome); printf("Inserire TEL: "); scanf("%s", tel); fprintf(Fp1, "%s\t%s\t%s\n", nome, cognome, tel); fflush(stdin); printf("Finito? S(i) oppure N(o) --> "); scanf("%c", &finito); } // chiudo il file e lo riapro in lettura testo fclose(Fp1); Fp1 = fopen(nomefile, "r"); if (Fp1==NULL){ printf("File %s not found\n", nomefile); exit(-1); } // il puntatore della posizione corrente del file e' all'inizio // (il file e' stato appena aperto), quindi lo leggeremo dall'inizio // IDEA: continuo a leggere con la stessa maschera con cui ho // scritto fino a che la fscanf assegna il numero di campi corretto printf("\n\nRubrica:\n"); while ( fscanf(Fp1, "%s\t%s\t%s\n", nome, cognome, tel) == 3 ) { printf("%s %s, %s\n", nome, cognome, tel); } fclose(Fp1); // mi ricordo di chiudere il file fflush(stdin); getchar(); }
C:\>EsaminaFiles1.exe Il puntatore (*Fp) al file rubrica.txt e' 2013505264 Inserire Nome: Mario Inserire Cognome: Rossi Inserire TEL: 037235467 Finito? S(i) oppure N(o) --> n Inserire Nome: Valeria Inserire Cognome: Bianchi Inserire TEL: 0373123456 Finito? S(i) oppure N(o) --> s Rubrica: Mario Rossi, 037235467 Valeria Bianchi, 0373123456
Anche la funzione main() ha i suoi argomenti e restituisce al sistema operativo un valore.
main( int argc, char *argv[ ]) { ... }argc è un intero che contiene il numero elementi presenti sulla linea di comando (elementi = numero di stringhe separate da spazi; quindi "Gestione risorse" sono due argomenti). Il valore minimo è 1 perché il nome del programma (ovviamente presente sulla linea di comando) viene contato.
#include <stdio.h> // Elenca gli argomenti forniti al programma sulla linea di comando. // PER SEMPLICITA', VA INVOCATO DAL PROMPT DEI COMANDI main(int argc, char *argv[ ]) { int i; printf("\nHai passato al programma %d argomenti\nIn ordine:\n", argc); for(i=0; i<argc; i++) printf("[%d] : %s\n", i, argv[i]); }Otteniamo
C:\>ElencaArgomenti 12 "Esplora risorse" laboratorio di informatica Hai passato al programma 6 argomenti In ordine: [0] : ElencaArgomenti [1] : 12 [2] : Esplora risorse [3] : laboratorio [4] : di [5] : informatica
Esercizio 1:
Dato il file Media.c, che avevamo visto nella quarta lezione, scorporare il codice che calcola la media in una funzione. Mettere la funzione e le eventuali costanti in un file .h. Suggerimento: introducete una costante che limiti il numero massimo di interi a 100.
Esercizio 2:
Partendo dall'esempio EsaminaFiles1.c, modificarlo opportunamente in modo che il file rubrica.txt venga aperto una volta sola in lettura/scrittura. Salvarlo con il nome EsaminaFiles2.c. Suggerimento: per evitare la seconda apertura, riposizionare la testina di lettura all'inizio del file con fseek().
Esercizio 3:
Sullo schema di EsaminaFiles2.c, che avete costruito nell'esercizio precedente, scrivete il programma scrivitabella.c che crei il file "temperature.txt" in cui su ogni riga ci sia il nome di una città e la temperatura separati da una tabulazione. Città e temperature vengono immesse dall'utente.
Esercizio 4:
Scrivere il programma mostra.c che invocato nel seguente modo:C:\>mostra nomefile.txtstampa a video il contenuto del file di testo nomefile.txt. Provatelo su questa poesia di Ungaretti: sanmartino.txt.
Esercizio 5:
Scrivere un programma che conti quante volte compare la lettera 'r' (maiuscolo o minuscolo non importa) nella costituzione della repubblica italiana. Il testo lo trovate in questo file: costituz.txt.
©2003 Roberto Sassi