INFORMATICA Altre Istruzioni di I/O. © Piero Demichelis 2 Funzioni di I/O Per la lettura e la...
-
Upload
celestino-abate -
Category
Documents
-
view
213 -
download
0
Transcript of INFORMATICA Altre Istruzioni di I/O. © Piero Demichelis 2 Funzioni di I/O Per la lettura e la...
INFORMATICA
Altre Istruzioni di I/O
2 © Piero Demichelis
Funzioni di I/O
• Per la lettura e la scrittura da videoterminale il C prevede numerose istruzioni tra cui scanf e printf che, come abbiamo già visto, agiscono su tutti i tipi di dato semplici.
• scanf e printf sono in realtà funzioni di tipo int e, come
tali, ritornano un valore intero attraverso il loro nome.
• La scanf restituisce il numero di parametri letti correttamente: se la si richiama con un unico parametro (si intende leggere un solo dato), il valore restituito è 1 se la lettura è andata a buon fine, 0 in caso di errore.
• La printf restituisce invece il numero di bytes che ha inviato in output, oppure 0 in caso di errore.
3 © Piero Demichelis
Funzioni di I/O
• Nel seguente frammento di programma:
int ndati, dato;.......ndati = scanf (“%d”, &dato);
in ndati verrebbe restituito il valore 1.
• Nella lettura di dati da tastiera non è previsto alcun codice particolare per segnalare il fatto che i dati in ingresso sono finiti.
• Generalmente per questo evento si una combinazione particolare di caratteri: ad esempio i tasti CTRL (control) e Z (che il Sistema Operativo interpreta come valore particolare chiamato EOF e definito internamente).
4 © Piero Demichelis
Esempio
• Programma che calcola il valor medio di un certo numero di dati reali (non noto a priori) terminanti con EOF, introdotti da terminale.
#include <stdio.h>
#define VERO 1#define FALSO 0
float numero, somma, media;int numdati, stato;int fine_lettura; main(){ fine_lettura = FALSO; /* inizializza flag,
*/
5 © Piero Demichelis
Esempio
somma = 0.0; /* accumulatore risultato */numdati = 0; /* contatore dei dati introdotti */
printf ("Introduci i dati (reali), CTRL+Z per finire:\n");while (!fine_lettura) /* continua fino al CTRL+Z */ { stato = scanf ("%f", &numero); /* in stato numero dati letti
*/ if (stato == 1) { somma += numero; /* accumula in somma */ numdati++; /* incrementa numdati (dati letti correttamente)
*/ } else fine_lettura = VERO; /* fine lettura */ } /* fine di while NOT fine_lettura */
6 © Piero Demichelis
Esempio
if (numdati == 0) printf ("Media non calcolabile\n");else { media = somma / numdati; printf ("La media su %d dati e': %f\n", numdati, media); }}
• Oltre alla scanf e alla printf il C possiede numerose altre funzioni di lettura e scrittura sia di caratteri sia di altri tipi di dato.
7 © Piero Demichelis
getchar()
• Lettura di un carattere da tastiera:
getchar();
• La funzione senza parametri getchar è definita in stdio.h di tipo intero (int) e restituisce un numero intero corrispondente al codice del tasto premuto.
• In caso di fine file fornisce il valore particolare EOF
(per la maggior parte dei sistemi vale -1) il quale è predefinito come simbolo in stdio.h.
• Se si esclude il caso dell'EOF è lecito assegnare il
valore fornito da questa funzione ad una variabile di tipo carattere (char).
8 © Piero Demichelis
Esempio
#include <stdio.h>
int carat; main(){ printf ("Inserisci dei caratteri, CTRL+Z per finire\n "); while ( ( carat = getchar() ) != EOF) printf ("%c", carat);}
• Nella condizione del while, prima è valutato l'assegnamento di getchar a carat, poi il risultato di questa operazione è confrontato con EOF.
9 © Piero Demichelis
Input di caratteri
• L'esecuzione di questo programma produce uno strano effetto: i caratteri appaiono sullo schermo man mano che sono introdotti; quando poi si preme <RETURN> (“invio”) viene visualizzata di nuovo tutta la riga.
• La giustificazione sta nel fatto che la gestione fisica
dell'input, è operata dal Sistema Operativo il quale legge i caratteri provenienti da tastiera, ne fa l'eco sul video e li immagazzina in un vettore interno (buffer di tastiera).
• I caratteri introdotti sono trasmessi al programma solo
dopo che è stato introdotto un carattere terminatore (come per esempio <RETURN>, ecc.).
10 © Piero Demichelis
Input di caratteri
• In questo modo si consente all'utente l'eventuale modifica della sequenza dei caratteri già introdotti fino a quando non invia un <RETURN>: questa funzionalità è nota col nome di editing di linea.
• I caratteri <RETURN>, <CONTROL>+ Z,
<CONTROL>+ C, <BREAK> costituiscono “eventi significativi ” di tastiera.
• Le procedure interne attivate da scanf e getchar
“aspettano ” che ci sia un “evento significativo ” prima di eseguire le operazioni alle quali sono preposte.
11 © Piero Demichelis
putchar()
• Visualizzazione di un carattere sul monitor:
putchar(<carattere>);
• La funzione di tipo intero putchar prevede un parametro di tipo char, quello appunto che si vuole inviare al video.
• In realtà la definizione in stdio.h rivela che il tipo
carattere del parametro viene internamente convertito ad intero.
• Il valore restituito da putchar coincide con il
carattere stesso se l'operazione di output ha successo, altrimenti vale EOF.
12 © Piero Demichelis
Esempio
#include <stdio.h>char carat; main(){printf ("Visualizzazione dei caratteri ASCII:\n ");carat = ‘ ’;while (carat <= ‘ ~ ’) { putchar (carat); carat++; }putchar(‘ \n ’); /* new-line finale
*/}
13 © Piero Demichelis
Confronto tra le istruzioni di I/O
• scanf e printf sono “costruite” a partire da getchar/putchar
• scanf/printf sono utili quando è noto il formato (tipo) del dato che viene letto.
• getchar/putchar sono utili quando non è noto il
formato, ad esempio: un testo in cui sono presenti spazi e punteggiatura e che pertanto non è trattabile con semplicità da scanf e printf.
14 © Piero Demichelis
Input di testi
• Se si deve leggere un testo (inclusi spazi e punteggiatura) la scanf non è utilizzabile e la getchar è scomoda da usare.
• Per introdurre testi il C fornisce un’apposita istruzione, la
gets (<stringa>);
che legge da tastiera una riga intera, compresi spazi e punteggiatura, fino all’introduzione di <RETURN> (INVIO);
• la sequenza di caratteri letti viene trasmessa al programma sottoforma di stringa in <stringa>, senza il carattere ‘\n’.
15 © Piero Demichelis
Input di testi
• Poiché come al solito non ci sono controlli sugli indici, la stringa deve essere dimensionata opportunamente.
• Non è tuttavia possibile limitare il numero di caratteri che l’utente introduce e pertanto si è esposti a eventuali danni causati dal travalicamento dei limiti.
• La <stringa> così introdotta è una stringa a tutti gli effetti: infatti la gets inserisce il carattere di fine stringa NULL (ovvero ‘\0’).
• Pertanto <stringa> può essere normalmente elaborata.
16 © Piero Demichelis
Output di testi
• Anche per visualizzare testi il C fornisce un’apposita istruzione, la
puts ( <stringa> );
che visualizza sul monitor <stringa>, aggiungendo alla fine della stringa un ‘\n’.
• L’istruzione puts (stringa);
produce lo stesso output di
printf (“%s\n”, stringa);
17 © Piero Demichelis
I/O di testi - Esempio
#include <stdio.h>
main(){
char riga[80];
printf (“Introduci una riga di testo:\n”);gets (riga);printf (“Hai scritto:\n”);puts (riga);
}
18 © Piero Demichelis
sprintf e sscanf
• Importanti sono anche le due funzioni sprintf e sscanf, che operano come la printf e la scanf, effettuando una conversione pilotata da un format; la differenza sta nel riferimento: stringa invece di stream (tastiera o monitor).
• La sintassi di sprintf è:
sprintf (<stringa>, <format>, <lista variabili>); • Genera in <stringa> la stessa sequenza di caratteri
che genererebbe la printf sul monitor. Alla fine chiude la stringa appena generata col carattere ‘\0’ (NULL).
19 © Piero Demichelis
sprintf e sscanf
• Ad esempio, eseguendo il seguente frammento di programma:
int giorno, mese, anno;char data[80];………giorno = 12;mese = 2;anno = 2005;sprintf(data,"Torino %2d-%2d-%4d", giorno, mese, anno);
• La stringa data sarà formata dalla seguente sequenza di caratteri:
“Torino 12- 2-2005\0”.
20 © Piero Demichelis
sprintf e sscanf
La sintassi di sscanf è:
sscanf (<stringa>, <format>, <lista variabili>);
• Le variabili della lista vengono lette interpretando i caratteri contenuti in <stringa> secondo le modalità fissate dagli specificatori di formato contenuti nel format.
Esempio:
int giorno, mese, anno;char data[10] = {‘2’, ‘0’, ‘ ’, ‘7’, ‘ ’, ‘2’, ‘0’, ‘0’, ‘5’, ‘\0’}……..;sscanf (data,”%d%d%d”, &giorno, &mese, &anno);
• giorno vale 20, mese vale 7 e anno vale 2005.
21 © Piero Demichelis
Dati sulla linea di comando
• Abbiamo già avuto occasione di osservare come il main sia in realtà una funzione.
• Come le altre funzioni il main è in grado di ricevere dei parametri che devono essere indicati tra le parentesi tonde che devono seguire la parola chiave main.
• Questi parametri vanno scritti di seguito al nome del programma sulla linea di comando e separati tra loro dallo spazio.
• Si tratta evidentemente di un’utile alternativa all’introduzione dei dati da tastiera.
• Esempio:
bmi 72.60 175
22 © Piero Demichelis
Dati sulla linea di comando
• I parametri così indicati vengono passati dal sistema operativo al main tramite la seguente coppia di parametri:
int argc argument counter char *argv[] argument vector
• argc è una variabile intera che contiene il numero di parametri contenuti nel vettore di stringhe argv.
• argv è un vettore di stringhe.
• Queste due variabili devono essere dichiarate come parametri della funzione main:
int main (int argc, char *argv[])
23 © Piero Demichelis
Dati sulla linea di comando
• argc indica il numero di parametri presenti sulla riga di comando, incluso il nome del programma (pertanto vale sempre almeno 1).
• il vettore argv[ ] (in realtà è una matrice di caratteri) contiene i parametri veri e propri sottoforma di stringhe di caratteri secondo il seguente formato:
argv[0] è il nome del programma;
argv[n] è la stringa che rappresenta l’ennesimo parametro dopo il nome del programma.
• I parametri pertanto sono sempre delle stringhe: per trasformarli in rappresentazioni numeriche occorre usare le funzioni approppriate (atoi, atol, atof) o la sscanf.
24 © Piero Demichelis
Dati sulla linea di comando
• Struttura Esempio: c:\> programma.exe 3 pippo.dat 3.2
argc = 4
argv[0]
argv[1]argv[2]
argv[3]
“programma.exe\0”
“3\0”
“pippo.dat\0”
“3.2\0”
25 © Piero Demichelis
Dati sulla linea di comando
• Scrivere un programma che legga sulla linea di comando due interi N e D, e visualizzi tutti i numeri minori di N che sono divisibili per D.
• Il programma dovrà pertanto essere eseguito con il seguente comando:
myprog N D
dove myprog è il nome del programma, N e D sono i due valori richiesti per il funzionamento del programma.
26 © Piero Demichelis
Dati sulla linea di comando
#include <stdio.h>
int main(int argc, char *argv[]) {
int N, D, i;
if (argc != 3) { printf (”Numero argomenti errato\nSintassi: myprog N
D”); return 1;
} N = atoi (argv[1]); /* converte N */ D = atoi (argv[2]); /* converte D */
for (i = 1; i < N; i++) if ((i % D) == 0) printf (”%d\n”, i);
}
Test per verificare chel’utente ha introdotto ilnumero esatto di dati