I/O INTERATTIVO scanf: quello che è indispensabile sapere printf: quello che è utile sapere
Input da tastiera Funzioni disponibili (tra le altre): scanf getchar Schema di funzionamento
Tastiera Sistema Operativo Driver del periferico consolle Video Buffer di tastiera Stream stdin
L utente batte dei tasti: 1 2 3 123_ 1 2 3 Sistema Operativo Il S.O. li trasferisce nel buffer di tastiera e li invia al video per controllo (eco dei caratteri) I caratteri stazionano nel buffer (possono essere corretti) Stdin resta vuoto: una funzione di input è posta in wait
L utente batte <Invio> 123_ Sistema Operativo Il S.O. trasferisce il contenuto del buffer in stdin 1 2 3
L utente batte <Invio> 123 _ Sistema Operativo Il S.O. trasferisce il contenuto del buffer in stdin Il buffer si svuota 1 2 3 \n Stdin ora non è più vuoto: una funzione di input in wait diventa operativa.
Note: i tasti della tastiera vengono identificati dalla posizione (ad es. coordinate in una matrice di contatti) il driver di tastiera (S.O.) si occupa di convertire le posizioni in codici che rappresentano i caratteri (codifica ASCII? codifica UNICODE?) Per le funzioni di input (scanf, getchar, ecc.) conta quello che è presente in stdin, non quanto si vede sullo schermo!!!
Funzionamento della scanf La funzione scanf opera a partire dal format e dagli specificatori di formato Sono gli specificatori di formato a comandare la scanf. La scanf utilizza come sorgente lo stream stdin Si può immaginare che su stdin ci sia un cursore che punta al primo carattere ancora da trattare.
scanf( %c,&carat); Trasferisce il carattere su cui è posizionato il cursore in stdin nella cella carat, senza alcuna manipolazione Il cursore avanza di una posizione. F 3 \n stdin
Esempio applicativo: printf( Vuoi continuare? Rispondere S/N: ); scanf( %c, &risposta); Nota: l utente inserisce una lettera e poi <Invio> perché venga accettata. La scanf legge la lettera, ma in stdin resta pendente il carattere \n
scanf( %d, &dato_int); Opera in due passi: estrazione della sequenza di cifre (token) conversione da sequenza di caratteri a numero in complemento a 2. Nota: si definiscono blank characters i caratteri blank (spazio), new-line ( \n ), tab ( \t ).
Tokenizzazione I blank characters iniziali vengono saltati Il primo carattere non-blank deve essere un carattere compatibile con un numero intero (segno o cifra): viene immagazzinato Vengono immagazzinate tutte le cifre successive fino a un carattere non compatibile con un numero intero
Tokenizzazione (2) Lo standard prescrive che questo carattere finale sia un blank character, ma i compilatori attuali tollerano come terminatore qualsiasi carattere Il carattere terminatore non viene consumato. In caso di errore la cattura della sequenza si blocca, la scanf esce con errore, il carattere che ha dato errore e i successivi non vengono consumati.
Conversione La sequenza di cifre viene convertita in numero con l algoritmo del prodotto e somma. Viene controllata la correttezza della conversione (overflow) Viene tenuto conto del segno.
Conversione (2) Il risultato della conversione viene scritto nella variabile di destinazione, senza ulteriori controlli (attenzione: se la dimensione in byte della destinazione non è corretta, si potrebbero sporcare le celle vicine!) In caso di errori di conversione la scanf si blocca ed esce con errore. \n 0 \n stdin 1 0000000000001010 cella di memoria
Esempio applicativo: printf( Introduci un numero intero: ); scanf( %d, &dato_int); Nota: l utente inserisce ad esempio -123 e <Invio> perché venga accettato. La scanf legge il numero, ma in stdin resta pendente il carattere \n finale.
Il token individuato corrisponde alla sequenza -123. Si osservi la corrispondenza nella tabella ASCII: carattere codice - 45 1 49 2 50 3 51 Per calcolare il valore di una cifra, il codice interno effettua l operazione cifra 0
scanf( %f, &dato_float) Comportamento analogo al %d, ma in più viene accettato il. e la notazione scientifica (es. 12.7e-6, che corrisponde a 0.0000127). Valgono le stesse considerazioni riguardo il trasferimento del risultato nella variabile di destinazione.
scanf( %s, stringa) I blank characters iniziali vengono saltati Il primo carattere non-blank viene trasferito nella stringa. Vengono trasferiti tutti i caratteri successivi fino al primo carattere blank. Viene aggiunto il carattere terminatore di stringa ( \0 ). Il carattere terminatore non viene consumato. Non viene effettuato nessun controllo sulla lunghezza della sequenza trasferita: eventualmente vengono sovrascritte le variabili contigue in memoria alla stringa.
Problemi connessi all uso della scanf Tanti, se ne sottolinea uno in particolare. Se dopo aver letto un numero (specificatori %d o %f) o una stringa (specificatore %s) si vuole leggere un carattere (specificatore %c), bisogna essere sicuri che non ci siano caratteri residui in stdin. Soluzione. Dopo aver letto il numero o la stringa, inserire l istruzione: while(getchar()!= \n ); che può essere trasformata in una funzione di libreria personale: void readln(void) { while(getchar()!= \n ); return; }
Lo specificatore scanset Ha la forma %[<c1>,<c2>,,<cn>] oppure %[<c1>-<cn>], dove <ci> è un carattere La scanf con questo specificatore legge e memorizza i caratteri fintanto che appartengono al set definito, poi inserisce il carattere null (come %s, ma accettando solo caratteri definiti dal set). Spesso utilizzato nella forma negativa, come in %[^\n]: trasferisce finché non è incontrato il carattere newline.
Nota: se il format della scanf contiene caratteri che non siano specificatori di formato (es. blank tra specificatori), vengono trattati come scanset: Si sconsiglia di utilizzarli: il format della scanf dovrebbe contenere solo specificatori di formato.
Output su video Funzioni disponibili (tra le altre): printf putchar Funzionamento della printf: opera a partire dal format, in base alle regole che seguono
I caratteri presenti nel format vengono trasferiti al video senza manipolazione; Se è presente un %, è uno specificatore di formato, considera il carattere successivo (eccezione: %% ) Se il carattere successivo è c (%c), preleva il parametro corrispondente e lo tratta come un codice, inviandolo verso il video senza manipolazioni
Se il carattere successivo è d (%d) o f (%f), preleva il parametro (per un numero di byte corrispondenti al tipo), interpreta il pacchetto rispettivamente come intero o reale, effettua la corrispondente conversione da dato codificato a sequenza di caratteri, invia la sequenza di caratteri al video (il dato è rappresentato sul numero minimo di caratteri).
Se il carattere successivo è s (%s), a partire dall indirizzo iniziale del parametro, invia i caratteri verso il video e si ferma solo quando incontra un carattere null ( \0 ). Nota: il terminale video effettua in automatico l andare a capo, quando viene superato il limite di una riga, e lo scroll delle righe.
Output formattato Le direttive di format della printf sono in realtà più complesse: %[flag][min dim][.precisione][dimensione]<carattere> [flag]: Più usati - Giustificazione della stampa a sinistra + Premette sempre il segno 0 Leading zero (invece dei blank) [min dim]: Dimensione minima di stampa in caratteri [precisione]: Numero di cifre frazionarie (per numeri reali) [dimensione]: Uno tra: h argomento è short l argomento è long carattere: Visto in precedenza