Software in pratica

 ☗   ◀   ☰   ▶ 

OPERAZIONI CON LE STRINGHE

Se finora avete pensato che le stringhe servissero solo a scrivere brevi messaggi o poco più, preparatevi a molti concetti nuovi. Avete già visto che dalle stringhe si possono ottenere i valori numerici rappresentati dai loro caratteri con le funzioni int e float, ma si possono effettuare molte altre operazioni simboliche, concatenazioni, estrazione di parti o di singoli caratteri ed altro ancora...


CONVERSIONI DI TIPO

Avrete sicuramente intuito che se scrivete delle cifre in una stringa il computer non ne considera il loro valore numerico, ma le tratta come singoli caratteri allo stesso modo delle lettere dell'alfabeto e degli altri simboli. Questo effettivamente è ciò che accade normalmente, ma il corso degli eventi può essere modificato usando le funzioni int e float, che ottengono da una stringa il valore numerico rappresentato dai suoi caratteri. Quindi un programmino del tipo:

b = "1324"
a = int(b)
assegna alla variabile 'a' il valore numerico intero 1324. Mentre:
b = "0.0177"
ro = float(b)

assegna alla variabile 'ro' il valore numerico floating point 0.0177
E' anche possibile compiere l'operazione inversa, si può cioè ottenere una stringa partendo da un valore numerico tramite la funzione str.

a = 85.443
b = str(a)

LUNGHEZZA

La funzione len permette di sapere quanto è lunga una stringa, cioè di quanti caratteri è formata (la lunghezza può anche essere zero in caso di stringa vuota):

a = input("IMMETTERE UNA PAROLA: ")
b = len(a)
print("LUNGHEZZA =", b)

CONCATENAMENTO E RIPETIZIONE

Le stringhe si possono sommare (concatenare):
a = "CA"
b = "SA"
print(a + b)     # stampa la scritta CASA
Le stringhe si possono ripetere:
a = "*"
b = 50
print(a * b)     # stampa una riga di 50 asterischi

SOTTOSTRINGHE

Le stringhe sono sequenze di caratteri, e tramite una parentesi quadra potete accedere ad ogni singolo carattere di essa tramite un indice numerico. Il primo carattere ha indice 0, l'ultimo ha indice len("stringa")-1

s = "PIPPO"
a = len(s)
print(s[1])      # stampa I
print(s[a-1])    # stampa O
Vediamo un esempio che riassume alcune delle cose appena dette:
s = input("QUAL'E' IL TUO NOME? ")
i = len(s)
b = ""              # predispone stringa vuota
while i > 0:
    b = b + s[i-1]  # aggiunge un carattere
    print(b)
    i = i - 1
print("PIACIUTA? :)")

Il programma può apparire insignificante, ma fatelo girare scrivendo parole diverse e vedrete che otterrete piacevoli risultati. Come sempre se il suo funzionamento non è chiaro conviene provare a simularlo con carta e penna facendo finta di essere il computer che lo deve eseguire, e annotandosi in ogni momento i valori delle variabili.

Potete anche accedere ad un intero gruppo di caratteri (sottostringa) all'interno di una stringa, questa operazione nel linguaggio Python si chiama sezionamento (affettamento, slicing) e si ottiene specificando due indici nella parentesi quadra separati dal simbolo : e tenendo a mente questo schema:




s = "STRINGA"
b = s[2 : 5]  # "RIN"      tutti i caratteri compresi tra gli indici 2 e 5
b = s[ : 4]   # "STRI"     tutto fino all'indice 4 (i primi 4 caratteri)
b = s[2 : ]   # "RINGA"    dall'indice 2 in poi (tutto meno i primi 2)
b = s[ : ]    # "STRINGA"  tutta la stringa

Se nella parentesi quadra manca l'indice di sinistra si sottointende "dall'inizio", se manca quello di destra si sottointende "fino alla fine". Gli indici possono anche essere negativi, in tal caso si considerano riferiti alla fine della stringa:



b = s[ : -2]  # "STRIN"   tutto meno gli ultimi due caratteri
b = s[-4 : ]  # "INGA"    dall'indice -4 in poi (gli ultimi 4 caratteri)

CODICE UNICODE E ASCII

Premettendo che ogni carattere di una stringa è rappresentato nella memoria del computer tramite un valore numerico, e che questa rappresentazione in Python è il codice unicode, un'altra utile funzione per la manipolazione a "basso livello" delle stringhe è ord, che fornisce appunto il codice numerico del carattere passato tra parentesi. Ad esempio il carattere A maiuscola è rappresentato con il valore 65 (e di seguito le altre lettere dell'alfabeto):

a = ord("C")
print(a)            # stampa 67

Sicuramente avrete anche sentito parlare di codice ASCII, questo è un altro tipo di codifica dei caratteri, nato 30 anni prima dell' unicode, e di fatto i primi valori numerici da 0 a 127 dell'unicode rappresentano esattamente gli stessi caratteri della codifica ASCII (cioè anche in ASCII la A maiuscola si codifica con il valore numerico 65)

La funzione inversa di ord è chr, che fornisce il carattere corrispondente ad un certo codice. Provate a digitare il seguente programmino:

c = 32
while c <= 127:
    print(chr(c), end="")
    c = c + 1

e vedrete sulla console tutto il set di lettere, simboli particolari e quisquilie varie disponibili con la codifica ASCII standard.

Il motivo per cui sono partito da 32 e ho terminato con 127 è che i codici al di sotto del 32 sono caratteri di controllo speciali non visualizzabili (retaggio di quando i caratteri servivano per controllare direttamente le funzioni di semplici terminali seriali e stampanti), mentre quelli superiori al 127 non fanno appunto parte dell'ASCII standard, ma se volete potete provare a stampare anche sequenze di caratteri con codici superiori (se il vostro sistema operativo ne supporta la visualizzazione), ad esempio il carattere euro € si ottiene con:

print(chr(8364))

Nota: in Python 2.x la gestione e codifica interna delle stringhe è diversa, tuttavia per gli esempi del testo non cambia niente, a parte quest'ultimo che andrebbe sostituito con print unichr(8364)


ALIENS

Il seguente programma vi sarà di aiuto se siete scrittori di fantascienza con poca fantasia per i nomi degli alieni. I nomi vengono costruiti carattere per carattere in un ciclo interno, e i singoli caratteri vengono generati estraendo a caso i codici delle lettere compresi tra ord("A") e ord("Z"). Potete concatenare stringhe e caratteri, perché i caratteri sono semplicemente stringhe di lunghezza 1

#------ PROGRAMMA ALIENS

import random
MINL = 3           # lunghezza minima nome
MAXL = 8           # lunghezza massima nome
n = int(input("QUANTI NOMI DI ALIENI VUOI? "))
while n > 0:
    b = ""         # predispone nuovo nome vuoto
    lunghezza = random.randint(MINL, MAXL)
    while lunghezza > 0:
        b = b + chr( random.randint(ord("A"), ord("Z")) )
        lunghezza = lunghezza - 1
    print(b)        # stampa il nome
    n = n - 1
Risultato:
QUANTI NOMI DI ALIENI VUOI? 4
DXTVOQHT
SJEH
PERFBR
GDEIRX

CRAPS

Il programma che segue è invece una simulazione del gioco craps molto in voga negli USA, le cui regole sono descritte con il seguente diagramma (che non è strettamente un diagramma di flusso delle singole istruzioni, ma piuttosto del procedimento di gioco, quando i programmi diventano più lunghi è infatti conveniente descriverne la logica di funzionamento in un modo un po' più astratto):



#------ PROGRAMMA CRAPS

import random

#---------------------------------------------------------------------

def dadini(n):
    if n == 1: return "     " + "  o  " + "     "
    if n == 2: return "    o" + "     " + "o    "
    if n == 3: return "    o" + "  o  " + "o    "
    if n == 4: return "o   o" + "     " + "o   o"
    if n == 5: return "o   o" + "  o  " + "o   o"
    if n == 6: return "o   o" + "o   o" + "o   o"

#---------------------------------------------------------------------

def lancio():   # Lancia e stampa due dadi
    d1 = random.randint(1, 6)
    d2 = random.randint(1, 6)
    s1 = dadini(d1)
    s2 = dadini(d2)
    print(s1[0:5]  + "     " + s2[0:5])
    print(s1[5:10] + "     " + s2[5:10])
    print(s1[10:]  + "     " + s2[10:])
    print("-" * 15)
    return d1 + d2

#---------------------------------------------------------------------

def vinto():    # Esegue procedura di gioco
    print("-" * 15)
    b = lancio()
    if b == 7 or b == 11: return True
    if b == 2 or b == 3 or b == 12: return False
    print("IL NUMERO USCITO E' IL TUO PUNTEGGIO")
    print("-" * 15)
    punto = b
    while True:
        b = lancio()
        if b == 7: return False
        if b == punto: return True      

#---------------------------------------------------------------------

def puntata():
    a = int(input("QUANTO VUOI PUNTARE (0 PER FINIRE)? "))
    while a > cap:
        print("HAI A DISPOSIZIONE SOLO", cap, "$!")
        a = int(input("QUANTO VUOI PUNTARE? "))
    return a

#---------------------------------------------------------------------

print("CRAPS")
cap = 100
print("BONUS INIZIALE", cap, "$")
while True:
    punt = puntata()
    if punt == 0: break
    if vinto():
        print("HAI VINTO!!!!")
        cap = cap + punt
    else:
        print("HAI PERSO!")
        cap = cap - punt
    print("HAI A DISPOSIZIONE", cap, "$")
    if cap == 0:
        print("HAI PERSO TUTTO!")
        break
Risultato:
CRAPS
BONUS INIZIALE 100 $
QUANTO VUOI PUNTARE (0 PER FINIRE)? 20
---------------
    o         o
  o            
o         o    
---------------
IL NUMERO USCITO E' IL TUO PUNTEGGIO
---------------
o   o         o
  o            
o   o     o    
---------------
HAI PERSO!
HAI A DISPOSIZIONE 80 $
QUANTO VUOI PUNTARE (0 PER FINIRE)? 80
---------------
o   o     o   o
o   o     o   o
o   o     o   o
---------------
HAI PERSO!
HAI A DISPOSIZIONE 0 $
HAI PERSO TUTTO!

Il programma è solo apparentemente complicato perché è il più lungo di quelli presentati finora, ma se guardate le singole funzioni noterete che sono tutte composte da cose già viste, cicli, if/else, print e input, vi sono comunque almeno tre cose da notare.

Intanto la funzione "lancio" contiene due distinti lanci (d1 e d2) che vengono sommati, questo è importante perché sarebbe un grave errore di logica estrarre un singolo numero compreso tra 2 e 12 (come se si lanciasse un dadone con 11 facce), infatti in questo caso tutti i numeri avrebbero la stessa probabilità di uscire, mentre sommando i lanci di due dadi singoli alcuni numeri hanno più probabilità di uscire rispetto ad altri, ad esempio il 7 si forma con molte combinazioni (quindi esce più spesso), mentre il 2 e il 12 escono più raramente degli altri.

La seconda cosa è che la procedura di gioco è interamente contenuta nella funzione "vinto" che restituisce un valore booleano True o False, e pertanto risulta comodo chiamarla direttamente come condizione di una riga if, rendendo il programma molto leggero e "discorsivo".

E per finire, le figure dei dadi vengono assemblate riga dopo riga estraendo tre sottostringhe di cinque caratteri ciascuna dalle stringhe s1 e s2, che a loro volta ricevono il valore dalla funzione "dadini", la quale restituisce una stringa di 15 caratteri contenente le "immagini" dei dadi per ogni valore possibile.

 ☗   ◀   ☰   ▶