Home Rhyylen
Contatto
 
 
 
Rust Language
Capitolo 7
Caratteri

I caratteri in Rust sono valori scalari Unicode. Essi, nella pratica, rappresentano un singolo carattere e sono identificati all'interno di una coppia di singoli apici. Per cui:

'a'  '6'  '%'  'T'

sono certamente dei caratteri. Quindi ogni elemento all'interno di una coppia di singoli apici perde in certo senso la sua natura e diventa un carattere. La cifra 6 che trovate in seconda posizione non è più un i32 pertanto ma un carattere. Sotto il cofano i caratteri sono collegati a precisi range numerici in particolare andiamo da 0 a 0x10FFFF incluso.  Per quanto riguarda l'occupazione di memoria Rust prevede 4 byte per le variabili di questo tipo. La cosa può sembrare un po' dispendiosa ma in realtà non esistono solo le nostre lettere latine, un po' di simboli e le cifre da 0 a 9, molti caratteri sono veri e propri grafemi la cui rappresentazione necessita di più caratteri appaiati.
La definizione formale di una variabile di tipo char è la consueta:


let c1 = 'a';
let c2: char = 'b';

lasciando fare all'inferenza oppure no. E' anche possibile usare il formato tipicamente Unicode come segue:

'\u{valore}' ad esempio:
let c4 = '\u{D7FF}';

Per leggere l'occupazione di memoria del singolo carattere possiamo usare anche qui un semplice programma come il seguente:

  Esempio 7.1
1
2
3
4
5
6
7
8
fn main() {
    let c1: char = 'a';
    let c2: char = '1';
    let size_in_bytes = std::mem::size_of_val(&c1);
    println!("L'occupazione in memoria del carattere 'a' è di {} byte", size_in_bytes);
    let size_in_bytes = std::mem::size_of_val(&c2);
    println!("L'occupazione in memoria del carattere '1' è di {} byte", size_in_bytes);
}

Il legame tra caratteri e numeri è comprovato dal fatto che è immediato passare da carattere a numero tramite cast. E' possibile anche l'inverso ma questa conversione non è considerata sicura a causa ovviamente della differenza di range tra i due tipi. Usando as, la nostra consueta keyword, finora, arma totale (mica tanto sicura però, lo ribadirò sempre...) per le conversioni:

  Esempio 7.2
1
2
3
4
5
6
7
8
fn main()
{
    let c1 = 'a';
    println!("{}", c1 as i32);
    println!("{}", 98 as char);
    println!("{}", (char::MAX) as i32);
//  println!("{}", (char::MIN) as i32);
}

che ci dà il seguente output:

97
b
1114111

All'interno del nostro piccolo programma troviamo la costante MAX che ci indica il limite numerico massimo possibile per il tipo char. Le righe 4 e 5 ci mostrano rispettivamente una conversione da carattere verso intero, come detto sempre possibile ed una da intero verso carattere, che in questo caso non dà problemi. La riga 8 è commentata in questo la costante MIN è instabile e disponibile solo nelle versione nightly del compilatore, almeno per ora (agosto 2024). La conversione da intero verso char la ritroveremo nel capitolo dedicato alle conversioni e vedremo come le cose possono essere eseguite in maniera un po' più sicura.
I caratteri dispongono di vari metodi che, come consueto, trovate nel sito ufficiale. Qui di seguito darò un breve esempio:

  Esempio 7.3
1
2
3
4
5
6
7
8
9
fn main()
{
  let c1 = '9';
  println!("{}", c1.is_digit(10));
  println!("{}", c1.is_digit(8));
  let c2 = 'A';
  println!("{}", c2.is_uppercase());
  println!("{}", c2.is_lowercase());
}

 La riga 4 ci restituirà true in quanto 9 è un numero in base 10 mentre la riga 5 ci restituisce false in quanto 9 non è contemplato in base 8. Interessante è il metodo from_digit che  che viene utilizzato per convertire un numero (di tipo u32) in un carattere rappresentante una cifra numerica (cioè '0' - '9') in una determinata base (radice) che può variare da 2 a 36 mentre sopra il valore 36 il programma va in panico.

  Esempio 7.4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() {
    let digit = 7;
    let base = 10;
    if let Some(character) = char::from_digit(digit, base) {
        println!("La cifra {} in base {} -> '{}'", digit, base, character);
    } else {
      println!("{} non è una cifra valida in base {}", digit, base);
      }
    let hex_digit = 15;
    let hex_base = 16;
        if let Some(character) = char::from_digit(hex_digit, hex_base) {
        println!("La cifra {} in base {} -> '{}'", hex_digit, hex_base, character);
      } else {
     println!("{} non è una cifra valida in base {}", hex_digit, hex_base);
    }
}

Reincontreremo presto i caratteri, il loro uso nell'ambito di sequenze ci porterà nel cuore di Rust.