Istruzioni di selezione ed uso delle funzioni Nell'ultima lezione era stato preparato un codice C per la lettura dei caratteri inseriti dall'utente mediante la tastiera e per la loro analisi (v. sotto). #include <stdio.h> int main() char lettura; printf("\n Inserisci almeno 3 caratteri (e poi premi ENTER o INVIO): "); // prelevo il primo carattere putchar('\n'); putchar('\n'); printf("\n ecco il primo carattere del buffer : %c",lettura); printf("\n e\' una lettera minuscola se visualizzo 1 -> %d", (lettura>=97) && (lettura<=122) ); printf("\n non e\' una minuscola se visualizzo 1 -> %d", (lettura < 97) (lettura > 122) ); printf("\n ecco il secondo carattere del buffer : %c (codice ASCII %d)", lettura,lettura); printf("\n e\' una lettera minuscola se visualizzo 1 -> %d", (lettura>=97) && (lettura<=122) ); printf("\n non e\' una minuscola se visualizzo 1 -> %d", (lettura < 97) (lettura > 122) ); printf("\n ecco il terzo carattere del buffer : %c (codice ASCII %d)",lettura,lettura); printf("\n e\' una lettera minuscola se visualizzo 1 -> %d", (lettura>=97) && (lettura<=122) ); printf("\n non e\' una minuscola se visualizzo 1 -> %d", (lettura < 97) (lettura > 122) ); printf("\n ecco il quarto carattere del buffer : %c (codice ASCII %d)",lettura,lettura); printf("\n e\' una lettera minuscola se visualizzo 1 -> %d", (lettura>=97) && (lettura<=122) ); printf("\n non e\' una minuscola se visualizzo 1 -> %d", (lettura < 97) (lettura > 122) ); printf("\n se l'ultimo carattere letto e\' LF visualizzo 1: -> %d", lettura == 10 );
/* fine codice */ Problemi connessi con l'esempio riportato sopra: 1. 2. Entrambe le frasi vengono sempre visualizzate, a prescindere dal tipo di carattere Il medesimo blocco di codice è ripetuto per quattro volte; modificarne le caratteristiche implica modificare 4 distinte porzioni di codice (con il conseguente rischio di errori) Cerchiamo di migliorare il codice iniziando dal modificare la parte che serve ad analizzare il valore del singolo carattere; l'obiettivo da raggiungere è il seguente: far riconoscere al programma il valore del carattere inserito e fargli poi visualizzare solo la frase che indica a quale gruppo appartenga tale valore (lettere maiuscole, numeri, etc. etc.). Dovendo far eseguire solo una istruzione (quella che visualizza il messaggio corrispondente al tipo di carattere inserito) tra tutte quelle possibili si rende necessario gestire il flusso del programma mediante una o più istruzione di selezione. if(condizione)... // codice Nel caso in cui si intenda far eseguire delle istruzioni anche nel caso in cui la condizione non sia verificata si può ricorrere al costrutto. if(condizione)... // codice... // codice
Utilizzando l'istruzione di selezione possiamo riscrivere l'istruzione printf("\n e\' una lettera minuscola se visualizzo 1 -> %d", (lettura>=97) && (lettura<=122) ); in questo modo if((lettura>=97) && (lettura<=122)) printf("\n il carattere %c e\' una lettera minuscola\n",lettura); Con questa metodologia il codice può essere adattato alle varie situazioni che si possono presentare (lettere minuscole, maiuscole, numeri, segni di punteggiatura,...). Ad esempio: if( (lettura >= 97) && (lettura <= 122) ) printf("\n il carattere %c e\' una lettera minuscola\n",lettura) ; if( (lettura >= 65) && (lettura <= 90) ) printf("\n il carattere %c e\' una lettera maiuscola\n",lettura) ; if( (lettura >= 48) && (lettura <= 57) ) printf("\n il carattere %c e\' un numero\n",lettura) ; if( (lettura >= 0) && (lettura <= 31) ) printf("\n il carattere %d e\' un carattere di controllo\n",lettura) ; Domanda:
come mai sono stati sufficienti solo degli if() e non ho utilizzato il costrutto if -? Per poter specializzare ulteriormente la parte di codice che si occupa del riconoscimento, oltre che per visualizzare messaggi relativi ai segni di punteggiatura, simboli matematici potrei, ad esempio, usare questo schema: determino se il carattere appartenga alla tabella estesa se vi appartiene visualizzo un messaggio se non vi appartiene determino se il carattere appartenga ad una delle categorie utilizzate sopra (lettere maiuscole, minuscole, numeri e caratteri di controllo) se il carattere vi appartiene allora visualizzo il messaggio opportuno se il carattere non vi appartiene determino se si tratta di un operatore matematico se il carattere è un operatore matematico visualizzo il messaggio opportuno se non lo è esso rappresenta un segno di punteggiatura Utilizzando questo schema tutti e 256 i caratteri (della Tabella ASCII standard e di quella estesa) vengono considerati. Traduciamo questo schema in linguaggio C (la tabella dei caratteri standard contiene solo codici ASCII compresi tra 0 e 127)... char lettura; int minusc,maiusc,numero,controllo,operatore_m;... if(! ((lettura >= 0) && (lettura <= 127)) ) printf("\n il carattere %c appartiene alla tabella estesa",lettura); // utilizziamo le condizioni viste prima minusc = (lettura >= 97) && (lettura<= 122);
maiusc = (lettura>= 65) && (lettura<= 90); numero = (lettura>= 48) && (lettura<= 57); controllo = (lettura>= 0) && (lettura<= 31); // appartiene = minusc maiusc numero controllo; if(appartiene) if(minusc) printf("\n il carattere %c e\' una lettera minuscola",lettura); if(maiusc) printf("\n il carattere %c e\' una lettera maiuscola",lettura); if(numero) printf("\n il carattere %c e\' un numero",lettura); if(controllo) printf("\n il carattere %d e\' un carattere di controllo",lettura); operatore_m = (lettura==42) (lettura==43) (lettura==45) (lettura==47); if( operatore_m ) printf("\n il carattere %c e\' un operatore matematico",lettura); printf("\n il carattere %c e\' un segno di punteggiatura",lettura); NOTE: 1. usate uno stile di scrittura che renda il codice più leggibile e che permetta di evidenziare in quali blocchi sia stato scomposto il codice 2.... da un semplice printf() siamo passati a più di 30 righe di codice... ripeterle tutte ogni volta rende il codice illeggibile (e soprattutto poco maneggevole...). 3. Soluzione: il codice appena preparato può essere scorporato dal programma principale, in quanto esso, per funzionare, necessita solo del valore del carattere, lettura
Per poter utilizzare una funzione in C è necessario: 1. 2. stabilire il prototipo della funzione, ovvero il suo nome, quanti siano i parametri, di che tipo essi siano e di che tipo sia il valore restituito dalla funzione implementare la funzione, ovvero indicare quali funzioni devono essere eseguite una volta che la funzione stessa venga richiamata 1. 2. stabiliamo il prototipo l'unico valore necessario alla funzione è quello del carattere da analizzare; una volta effettuata l'analisi non si rende necessario restituire alcun valore. Per analogia con il prototipo di getchar() e putchar() possiamo, però, far restituire alla funzione il valore del carattere analizzato. per l'implementazione ci possiamo rifare al codice visto sopra char analisi_carattere(char); char analisi_carattere(char car) int minusc,maiusc,numero,controllo,operatore_m; if(! ((car>= 0) && (car<= 127)) ) printf("\n il carattere %c appartiene alla tabella estesa",car); minusc = (car >= 97) && (car<= 122); maiusc = (car>= 65) && (car<= 90); numero = (car>= 48) && (car<= 57); controllo = (car>= 0) && (car<= 31); appartiene = minusc maiusc numero controllo; if(appartiene) if(minusc) printf("\n il carattere %c e\' una lettera minuscola",car); if(maiusc) printf("\n il carattere %c e\' una lettera maiuscola",car); if(numero) printf("\n il carattere %c e\' un numero",car); if(controllo) printf("\n il carattere %d e\' un carattere di controllo",car); operatore_m = (car==42) (car==43) (car==45) (car==47);
if( operatore_m ) printf("\n il carattere %c e\' un operatore matematico",car); printf("\n il carattere %c e\' un segno di punteggiatura",car); return car; Utilizzando questa funzione, il codice iniziale diventa: // inizio del codice per l'analisi dei caratteri #include <stdio.h> char analisi_carattere(char); int main() char lettura; printf("\n Inserisci almeno 3 caratteri (e poi premi ENTER o INVIO): "); // prelevo il primo carattere putchar('\n'); putchar('\n'); printf("\n ecco il primo carattere del buffer : %c",lettura); analisi_carattere(lettura); printf("\n ecco il secondo carattere del buffer : %c (codice ASCII %d)", lettura,lettura); analisi_carattere(lettura); printf("\n ecco il terzo carattere del buffer : %c (codice ASCII %d)",lettura,lettura); analisi_carattere(lettura); printf("\n ecco il quarto carattere del buffer : %c (codice ASCII %d)",lettura,lettura); analisi_carattere(lettura);
return 0; char analisi_carattere(char car) int minusc,maiusc,numero,controllo,operatore_m; if(! ((car>= 0) && (car<= 127)) ) printf("\n il carattere %c appartiene alla tabella estesa",car); minusc = (car >= 97) && (car<= 122); maiusc = (car>= 65) && (car<= 90); numero = (car>= 48) && (car<= 57); controllo = (car>= 0) && (car<= 31); appartiene = minusc maiusc numero controllo; if(appartiene) if(minusc) printf("\n il carattere %c e\' una lettera minuscola",car); if(maiusc) printf("\n il carattere %c e\' una lettera maiuscola",car); if(numero) printf("\n il carattere %c e\' un numero",car); if(controllo) printf("\n il carattere %d e\' un carattere di controllo",car); operatore_m = (car==42) (car==43) (car==45) (car==47); if( operatore_m ) printf("\n il carattere %c e\' un operatore matematico",car); printf("\n il carattere %c e\' un segno di punteggiatura",car); return car; /* fine codice */
La libreria standard ( ctype.h ) contiene alcune funzioni che rendono l'implementazione della funzione un po' più snella. int isdigit(int) restituisce un intero positivo se il carattere che riceve come parametro è un carattere numerico, 0 altrimenti int islower(int) restituisce un intero positivo se il carattere che riceve come parametro è una lettera minuscola, 0 altrimenti int isupper(int) restituisce un intero positivo se il carattere che riceve come parametro è una lettera maiuscola, 0 altrimenti int isalpha(int) restituisce un intero positivo se il carattere che riceve come parametro è una lettera minuscola o una lettera maiuscola, 0 altrimenti int iscntrl(int) restituisce un intero positivo se il carattere che riceve come parametro è un carattere di controllo, 0 altrimenti Per sapere quali siano le altre funzioni accessibili grazie a ctype.h seguire il link "Le funzioni della libreria standard" nella sezione "Link utili" Con le funzioni appena mostrate il codice diventa: // inizio codice #include <stdio.h> #include <ctype.h>... // tutto il resto rimane uguale a prima char analisi_carattere(char car) int operatore_m; if(! ((car>= 0) && (car<= 127)) ) printf("\n il carattere %c appartiene alla tabella estesa",car); if( isalpha(car) isdigit(car) iscntrl(car)) if(islower(car)) printf("\n il carattere %c e\' una lettera minuscola",car); if(isupper(car)) printf("\n il carattere %c e\' una lettera maiuscola",car); if(isdigit(car))
printf("\n il carattere %c e\' un numero",car); if(iscntrl(car)) printf("\n il carattere %d e\' un carattere di controllo",car); operatore_m = (car==42) (car==43) (car==45) (car==47); if( operatore_m ) printf("\n il carattere %c e\' un operatore matematico",car); printf("\n il carattere %c e\' un segno di punteggiatura",car); return car; Esercizio: basandosi sullo schema qui sotto riportato, implementare una funzione per l'analisi dei caratteri determinare se il carattere appartenga alla tabella estesa se vi appartiene visualizzo un messaggio se non vi appartiene determinare se il carattere appartenga ad una delle seguenti categorie: lettere maiuscole, minuscole, numeri e caratteri di controllo se il carattere vi appartiene allora visualizzo il messaggio opportuno se il carattere non vi appartiene, determinare se si tratti di un operatore matematico se il carattere è un operatore matematico visualizzo il messaggio opportuno se non lo è, determinare se esso sia una parentesi di qualche tipo se il carattere è un tipo di parentesi, allora visualizzare il messaggio opportuno se non lo è, allora esso è un segno di punteggiatura NOTA: controllate se il carattere sia o meno un operatore matematico implementando una opportuna funzione. Come prototipo utilizzate, rifacendoci alle funzioni della libreria standard, int isoperator(int)