« Tcl: Creazione di nuovi comandi: comandi global e upvarAppunti di Tcl/TkTcl: Manipolazione delle liste »

Tcl

manipolazione delle stringhe

Come il C e molti altri linguaggi Tcl fornisce alcune facilities per la manipolazione delle stringhe, che è uno dei compiti più frequenti nella programmazione nella maggior parte delle applicazioni.

La definizione di stringa è molto semplice: si tratta di una sequenza di caratteri, vista come una singola unità. La sequenza può anche essere vuota e in tal caso si parla di stringa vuota o stringa nulla, che quindi è un valore ammissibile con cui inizializzare una variabile stringa. Come già sappiamo Tcl ha come unico tipo di dati la stringa.

Poiché sulle stringhe è possibile fare molti tipi di elaborazioni distinte, abbiamo bisogno di un elevato numero di comandi. Per evitare la proliferazione dei comandi, si è deciso di utilizzare un solo comando per la manipolazione delle stringhe, il comando string(n), passandogli come primo argomento option il nome di un sottocomando. Questa è una situazione tipica in Tcl e voi stessi potete creare con l'aiuto di proc(n) e switch(n) dei comandi che hanno un numero arbitrario di sottocomandi.

string option arg ?arg ...?

Le operazioni più comuni e semplici sono documentate nell'elenco seguente (ma per un elenco esaustivo consultare la manpage di string(n)). Le stringhe sono passate a string(n) sempre per valore; quei sottocomandi che modificano la copia passata per valore della stringa argomento, ritornano sempre la stringa modificata. Questo implica che se intendete modificare la stringa stessa che avete passato, dovete assegnargli il valore di ritorno del comando string(n).

string length string
Ritorna il numero di caratteri (lunghezza) della stringa string.
% puts [string length ""]
0
% puts [string length {I am}]
4
string index string charIndex
Ritorna il charIndex-esimo carattere della stringa argomento string, come una stringa consistente in un solo carattere oppure ritorna la stringa vuota se charIndex è negativo o maggiore o uguale alla lunghezza della stringa. I caratteri vengono contati a partire da 0 come in C, quindi se charIndex è zero viene restituito il primo carattere. Corrisponde all'operatore subscript [ ] su un rvalue del C (ricordo che Tcl non ha operatori nella sua sintassi, ma solo comandi). Se invece di essere un intero charIndex è la stringa end, viene restituito l'ultimo carattere, e si evita così la complicazione di doverne calcolare la posizione:
% set s stringa
stringa
% puts [string index $s [expr [string length $s]-1]]
a
% puts [string index $s end]
a
Inoltre end-1 indica il penultimo carattere, end-2 il precedente del penultimo e così via:
% puts [string index $s end-1]
g
string range string first last
Ritorna la sottostringa composta da i caratteri tra le posizioni first e last comprese. Le posizioni possono essere specificate nei tre modi visti col sottocomando index: intero, end oppure end-intero. Se first è minore di zero, viene trattato come se fosse zero, mentre se last è maggiore o uguale della lunghezza della stringa viene considerato come se fosse end. Se first è maggiore di last viene ritornata la stringa vuota.
string repeat string count
Ritorna la stringa string ripetuta count volte:
% puts [string repeat - 30]
------------------------------
string compare ?-nocase? ?-length int? string1 string2
Per i programmatori C è analoga alle funzioni strcmp(3), strncmp(3), strcasecmp(3) e strncasecmp(3). Effettua un confronto lessicografico (non numerico, per quello usate expr(n), implicitamente con if(n) o esplicitamente) tra le due stringhe string1 e string2 e ritorna: Se viene specificato -length il confronto riguarderà al più i prefissi delle stringhe aventi il numero di caratteri specificato (i valori negativi fanno sì che l'opzione -length venga ignorata). -nocase specifica che il confronto non deve tenere conto della differenza tra maiuscole e minuscole. Un esempio di uso ripetuto di questa funzione si ha in una qualsiasi procedura di ordinamento lessicografico tra stringhe. Come abbiamo visto anche con expr(1) si possono fare i confronti tra stringhe. Qual'è allora la differenza tra usare expr(1) e usare string compare? Osservate il seguente esempio che la mette in luce:
% expr "10" < "9"
0
% string compare "10" "9"
-1
Come si vede, expr(1) ha convertito le stringhe in numeri prima di fare il confronto, accorgendosi che entrambe sono degli interi sintatticamente ben scritti, invece string compare effettua sempre il confronto lessicografico tra stringhe. Per maggiori informazioni vedere la sezione STRING OPERATIONS della manpage di expr(1).
string first string1 string2 ?startIndex?
Ritorna l'indice numerico del carattere in string2 in cui inizia la prima occorrenza esatta di string1, oppure -1 se la stringa string2 non contiene la stringa string1. Se viene specificato startIndex (in una delle tre forme accettata dal sottocomando index), la ricerca in string2 parte parte da quell'indice anziché dall'indice zero.
string last string1 string2 ?startIndex?
Come string first, ma considera l'ultima occorrenza, se esiste.
string match ?-nocase? pattern string
Ritorna 1 se il pattern corrisponde alla stringa, altrimenti 0. Se presente l'argomento -nocase effettua un confronto insensibile alle differenze tra maiuscole e minuscole. Riconosce nel pattern un significato speciale ai seguenti caratteri jolly (gli stessi della shell Unix sh(1)):
car. significato speciale
* trova corrispondenza con qualsiasi sequenza di caratteri, compresa la stringa vuota
? Corrisponde ad un solo carattere, qualsiasi
\x Fa corrispondenza solo col carattere x, inteso in senso letterale. È necessario usarlo quando si vuole evitare l'interpretazione speciale dei caratteri come *?[]\ nel pattern.
[chars] Corrisponde ad una singola occorrenza di uno qualsiasi dei caratteri dell'insieme chars. Se chars comprende una sequenza del tipo x-y, la corrispondenza sarà fatta per qualsiasi carattere compreso tra x e y, estremi inclusi. Ad esempio [A-Za-z] fa match con una qualsiasi lettera dell'alfabeto inglese, sia maiuscola che minuscola
string replace string first last ?newstring?
Rimuove da string una sottostringa che inizia all'indice first e finisce all'indice last, specificati come si fa col metodo index. Se viene specificata newstring, essa viene inserita al posto della sottostringa rimossa. Ritorna la stringa ottenuta dopo queste elaborazioni.
string tolower string ?first? ?last?
Converte i caratteri maiuscoli in minuscoli nella sottostringa che inizia all'indice first (incluso) e finisce all'indice last (incluso) e ritorna la stringa ottenuta. Gli indici possono essere specificati come col metodo index. Se non vengono specificati first e last, la ricerca di caratteri maiuscoli da convertire si estende a tutta la stringa. Se viene specificato solo first, la ricerca parte da questo indice e si estende fino alla fine delle stringa.
string toupper string ?first? ?last?
Analogo a string tolower, solo che converte da minuscolo a maiuscolo.
string trim string ?chars?
Ritorna la stringa ottenuta dopo che da string è stato eliminato il più lungo prefisso e suffisso costituito tutto da caratteri dell'insieme chars. Se quest'ultimo non è specificato, allora per default si assume che sia l'insieme dei vari tipi di bianchi (spazi, tabulazioni, caratteri di nuova linea e di ritorno a carrello).
string trimleft string ?chars?
Come string trim, ma elimina solo il prefisso (l'estremità sinistra).
string trimright string ?chars?
Come string trim, ma elimina solo il suffisso (l'estremità destra).

Un esempio che utilizza il comando string map: rot13 è un comando che implementa un semplice metodo di crittografia usato ad esempio per nascondere la scrittura della soluzione di un gioco o un indovinello quando viene mandata via email. Immaginando di disporre tutte le 26 lettere dell'alfabeto in un cerchio ad esempio in senso antiorario, il metodo consiste nel sostituire ciascuna lettera con quella che si trova 13 posizioni più avanti in senso antiorario, da cui il nome della tecnica. Naturalmente questa è una tecnica di crittografia molto debole, percui va usata solo per giochi e cose non troppo importanti!

proc rot13 string {
  string map {a n b o c p d q e r f s g t h u i v j w k x l y
      m z n a o b p c q d r e s f t g u h v i w j x k y l z m
      A N B O C P D Q E R F S G T H U I V J W K X L Y M Z N A
      O B P C Q D R E S F T G U H V I W J X K Y L Z M} $string
} 

Per appendere una stringa ad una variabile, potete utilizzare la funzionalità di sostituzione dell'interprete e il comando set(n):

% set a inter
inter
% set b net
net
% set a $a$b
internet

In alternativa potete usare il comando append(n) che è più efficiente (la differenza è significativa nel caso di stringhe lunghe e/o nel caso in cui l'operazione di concatenazione deve essere ripetuta molte volte):

append varName ?value value value ...?

% set a inter
inter
% set b net
net
% append a $b
internet

« Tcl: Creazione di nuovi comandi: comandi global e upvarAppunti di Tcl/TkTcl: Manipolazione delle liste »