Comunicare con l'utilizzatore

Contenuto del capitolo
Come richiedere all'utilizzatore di immettere i dati e come leggerli quando vengono immessi.
Mostreremo come leggere sia dati numerici che stringhe.
Vedremo anche come leggere i dati immessi come argomenti nella linea di comando.

I programmi visti fino ad ora hanno utilizzato dati statici. Dati che, se necessario, possiamo esaminare prima dell'esecuzione del programma e quindi addattare ad essi il programma stesso. La maggior parte dei programmi però non sono di questo tipo. La maggior parte dei programmi sono fatti per essere comandati da un utilizzatore, almeno per ottenere l'indicazione di quale file aprire, leggere, ecc. Altri richiedono all'utilizzatore di immettere dati al momento giusto. Prima di procedere vediamo come ciò può essere fatto.

>>> print raw_input("Scrivi qualcosa: ")

Come vedete raw_input semplicemente visualizza il prompt specificato e legge qualunque carattere immesso dall'utilizzatore in risposta. Print quindi visualizza la risposta immessa. In alternativa possiamo assegnare la risposta ad una variabile:

risp = raw_input("Come ti chiami? ")
print "Ciao, %s, piacere di conoscerti" % risp 

raw_input ha un cugino chiamato input. La differenza consiste nel fatto che raw_input raccoglie i caratteri immessi dall'utilizzatore e li presenta sotto forma di stringa, mentre input li raccorglie e cerca di interpretarli come numero. A esempio se l'utilizzatore scrive '1','2','3', la funzione input() leggerà i tre caratteri e li convertirà nel valore numerico 123.

Usiamo ora input per decidere quale tabellina visualizzare:

moltiplicatore = input("Quale moltiplicatore vuoi? Scegli un  numero ")
for j in range(1,13):
   print "%d x %d = %d" % (j, moltiplicatore, j * moltiplicatore)

Purtroppo c'è un grosso problema nell'uso di input. Infatti input non si limita a valutare i valori numerici ma piuttosto tratta qualunque stringa di caratteri immessa come una istruzione Python e cerca di eseguirla. Perciò un utilizzatore esperto e malizioso potrebbe immettere un comando Python che cancella un file dal vostro PC! Per questa ragione è preferibile usare raw_input e convertire la stringa nel tipo di dato opportuno usando la funzione di conversione specifica di Python. L'operazione è abbastanza semplice:

moltiplicatore = int(raw_input("Che moltiplicatore vuoi? Scegli un numero "))
for j in range(1,13):
   print "%d x %d = %d" % (j, moltiplicatore, j * moltiplicatore)

Come vedete abbiamo solo racchiuso la chiamata a raw_input in una chiamata ad int. Il risultato è lo stesso di usare input ma è assai meno pericoloso. Poiché esistono anche altre funzioni di conversione, potete convertire in un valore a "virgola mobile", ecc.

L'istruzione INPUT in BASIC

In BASIC l'istruzione INPUT legge i caratteri immessi dall'utilizzatore:

INPUT "Che moltiplicatore vuoi? Scegli un numero ";M
FOR J = 1 to 12
    PRINT M "x" J "= " M*J
NEXT J

Come vedete è assai simile alla versione Python tranne che per il fatto che la variabile si trova in fondo. Inoltre il BASIC usa INPUT sia per i numeri che per le stringhe. Di solito l'istruzione INPUT del BASIC ha anche altre caratteristiche aggiuntive. Verificate nella documentazione della vostra versione per i dettagli.

Immissione dei dati in Tcl

Anche il Tcl ha un meccanismo di lettura dei dati basato sul concetto di file (anche i dispositivi di ingresso e di uscita usuali sono considerati 'files') ed un comando chiamato gets. Il comando legge dati da un file specificato che nel nostro caso sarà stdin.
[ Nota: Il programma che segue non funziona lanciandolo dal 'prompt' standard di tclsh80 o wish80. Dovrete scriverlo dentro un file (ad esempio input.tcl) e lanciarlo nel modo seguente:

    C:\PROJECTS\Tcl>tclsh80 input.tcl
]

La versione Tcl del programma è la seguente:

puts -nonewline stdout "Che moltiplicatore vuoi? "
flush stdout
set molt [gets stdin]
for {set j 1} {$j <= 12} {incr j} {
    puts [format " %d x %d = %d" $j $molt [expr $molt * $j] ]
    }

L'opzione -nonewline dell'istruzione puts ha il solo scopo di evitare che il cursore vada a capo dopo che è stata visualizzata la stringa di richiesta. flush impone a stdout di scrivere il suo contenuto sullo schermo immediatamente, per essere sicuri che compaia. Il ciclo for è quasi identico a quello che abbiamo mostrato nel capitolo sui cicli.

Qualche parola su stdin e stdout

NOTA: stdin (abbreviazione di 'standard input', N.d.T.) è il termine di gergo informatico che indica il dispositivo di ingresso usuale (che è normalmente la tastiera). Viene trattato come se fosse un file (riparleremo in seguito di questa caratteristica) per coerenza con le funzioni di gestione dei files.

In Python risiede nel modulo sys e si chiama sys.stdin; raw_input() lo usa automaticamente. Tcl, usando gets (abbreviazione di getstring) può leggere da qualunque file. Lo stesso può avvenire in Python; il seguente programma:

import sys
print "Immetti un valore: ",  # la virgola impedisce l'andata a capo
valore = sys.stdin.readline()  # stdin viene usato esplicitamente
print valore

È quasi indentico a:

print raw_input('Immetti un valore: ')

Il vantaggio di usare la versione esplicita consiste nel fatto che è possibile fare strane cose, come ad esempio fare sí che stdin punti ad un vero file; cosí facendo lo stesso programma può leggere i dati da un file anziché dalla tastiera e questo può essere utile nelle le lunghe fasi di prova in cui invece di passare il tempo digitando tutti i dati di ingresso possiamo farli leggere da un file. [A questo vantaggio si aggiunge il fatto che possiamo ripetere la stessa prova più volte con la certezza che i dati di ingresso siano ogni volta gli stessi, il che dovrebbe produrre, sperabilmente anche gli stessi risultati in uscita. Questa tecnica di ripetere la stessa prova per accertarsi di non aver fatto modifiche distruttive viene chiamata dai programmatori prova di regressione].

Infine c'è anche un 'file' sys.stdout che a sua volta può essere reindirizzato ad un vero file. print è equivalente a:

sys.stdout.write("Ciao a tutti\n") # \n = a capo

Naturalmente se stdout non corrisponde allo schermo l'uscita verrebbe scritta in un file. Questo è quello che accade all'nterno del sistema operativo quando utilizziamo il reindirizzamento dell'output di un comando:

C:> dir
C:> dir > dir.txt

Il primo comando visualizza la lista della directory sullo schermo. Il secondo la scrive in un file. Usando il segno '>' indichiamo al programma di reindirizzare stdout al file dir.txt.

Argomenti dei comandi

Un altro tipo di input è quello derivato dalla linea di comando. Ad esempio, quando usate un editor di testi come segue:

EDIT Foo.txt

Come può il programma edit leggere il nome del file?

La maggior parte dei linguaggi di programmazione mettono a disposizione un vettore o una lista di stringhe che contengono le parole che compaiono nella linea di comando. Quindi il primo elemento conterrà il comando stesso, il secondo elemento conterrà il primo argomento, ecc. di solito c'è anche qualche tipo di magica variabile che contiene il numero di elementi nella lista. In Python la lista è contenuta nel modulo sys e si chiama argv (ovvero: 'argument values'). Possiamo estrarre gli elementi della lista usando gli indici o iterando sulla lista, come ad esempio:

import sys
for item in sys.argv:
    print item
    
print "Il primo argomento è:", sys.argv[1]

Notate che questo funziona solo se scrivete il programma in un file (ad esempio args.py) e lo eseguite dalla linea di comando del sistema operativo:

C:\Python\PROJECTS> python args.py 1 23 fred
args.py
1
23
fred
Il primo argomento è: 1
C:\PYTHON\PROJECTS>

La linea di comando in Tcl

Tcl ha uno schema simile, con tre variabili:

  • argv0 - il nome del comando
  • argv - una stringa che contiene il resto della linea di comando
  • argc - il numero di parole contenute in argv

    Un esempio di accesso agli argomenti della linea di comando in Tcl è il seguente:

    puts "il comando e': $argv0"
    puts "Il primo argomento e':  [lindex $argv 0]"
    

    Anche questa volta il programma deve essere eseguito come 'script' dalla linea di comando del sistema operativo fornendo anche gli argomenti.

    La linea di comando in BASIC

    Mentre Tcl non ha un equivalente di 'input', il BASIC non ha un equivalente di argv, anche se si possono usare caratteristiche specifiche del sistema operativo per accedere agli argomenti. Ad esempio nel sistema operativo DOS questi sono memorizzati in una variabile di ambiente ed è quindi possibile usare la funzione GETENV. Questa tecnica è troppo avanzata per questo corso e quindi raccomandiamo che nei programmi BASIC i valori da immettere vengano richiesti esplicitamente all'utilizzatore.

    In questo corso non approfondiremo ulteriormente l'argomento dell'immissione dei dati. Quanto mostrato è assai primitivo, ma è sufficiente a scrivere programmi utilizzabili. Nei primi anni di Unix e dei PC questa era l'unica forma di interazione disponibile. Python, Tcl e BASIC (nella sua versione 'Visual') sono tutti in grado di realizzare sofisticate interfacce grafiche con finestre di dialogo, ecc. Ma tutto ciò è un po' troppo avanzato per questo corso. Comunque l'esempio completo che vedremo mostra un semplice caso di immissione di dati in Python tramite un'interfaccia grafica, ma non daremo molte spiegazioni sul suo funzionamento. Sono disponibili in rete manuali introduttivi alle tecniche grafiche utili quando avrete buone basi sugli aspetti essenziali; alcuni di essi sono elencati nella bibliografia.

    Promemoria
    • Usate input per leggere numeri, raw_input per leggere stringhe di caratteri.
    • Sia input che raw_input possono visualizzare una stringa di richiesta.
    • L'istruzione INPUT del BASIC può essere usata per leggere qualunque tipo di dato.
    • In Python gli argomenti della linea di comando possono essere trovati nella lista argv importata dal modulo sys, ed il primo elemento è il nome del programma.
    • TCL usa una lista con lo stesso nome, argv per i dati dalla linea di comando, ma il nome del programma si trova in una variabile separata, argv0:
    • Alla variabile __name__ viene assegnato il valore "__main__" se il modulo è stato eseguito dalla linea di comando (o con il doppio clic sull'icona in windows).

    Precedente  Successivo  Indice


    Se avete domande o suggerimenti relativi a questa pagina mandate un e-mail all'autore: alan.gauld@yahoo.co.uk o al traduttore italiano: lfini@arcetri.astro.it