Step 7 of 7
Characters
A char holds one character, written in single quotes: 'a', 'Z', '7', '?'. Rust's char is a Unicode scalar value: it can be any character from any writing system, including emoji. Every char takes 4 bytes of memory.
fn main() {
let letter = 'R';
let accented = 'é';
let kanji = '錆';
let crab = '🦀';
println!("{letter} {accented} {kanji} {crab}");
println!("{}", 'A' as u32);
println!("{}", crab as u32);
}
R é 錆 🦀
65
129408
as u32 gives a character's code point, its number in the Unicode table: 'A' is 65, the crab is 129408. (錆 means "rust" in Japanese.)
char versus text
'F' is a char. "F" is a &str: text that happens to be one character long. They are different types:
fn main() {
let initial: char = "F";
println!("{initial}");
}
error[E0308]: mismatched types
--> src/main.rs:2:25
|
2 | let initial: char = "F";
| ---- ^^^ expected `char`, found `&str`
| |
| expected due to this
|
help: if you meant to write a `char` literal, use single quotes
|
2 - let initial: char = "F";
2 + let initial: char = 'F';
Asking questions about characters
char has many methods. Most answer a yes/no question, so they return a bool:
fn main() {
let c = '7';
println!("{}", c.is_ascii_digit());
println!("{}", c.is_alphabetic());
println!("{}", 'q'.is_lowercase());
println!("{}", 'q'.to_ascii_uppercase());
println!("{:?}", c.to_digit(10));
println!("{}", ' '.is_whitespace());
}
true
false
true
Q
Some(7)
true
is_alphabetic,is_numeric,is_alphanumeric,is_whitespace,is_uppercaseandis_lowercasework for every language.- The
asciimethods only know the basic Latin letters and digits (ASCII):is_ascii_digitis true only for'0'to'9', andto_ascii_uppercaseandto_ascii_lowercaseleave every other character alone. to_digit(10)turns'7'into the number 7 (asSome(7), orNoneif it isn't a digit). The 10 is the base.
Doing arithmetic with characters
You can't add a number to a char (error[E0369]: cannot add `{integer}` to `char`). Convert it to a number, compute, and convert back. Only u8 converts to char with as, because every u8 value is a valid character:
fn main() {
let letter = 'c';
let position = letter as u8 - b'a' + 1;
let next = (letter as u8 + 1) as char;
println!("{letter} is letter {position}, next is {next}");
}
c is letter 3, next is d
b'a' is a byte literal: the u8 value of the ASCII character a (97). This trick only works for ASCII letters: as u8 would cut a character like 'é' down to a wrong value.
Common mistakes
- Double quotes for a char, or several characters in single quotes:
'ab'giveserror: character literal may only contain one codepoint. - Assuming a
charis one byte, as in C. It's 4 bytes. Text (&str) is stored more compactly, as UTF-8; the strings modules explain the difference.
Your task
Print three facts about grade, one per line: whether it's alphabetic, its uppercase form, and its code point (as u32). For 'b' that's:
true
B
98
Challenge 2
Fill in the method that checks whether a character is a digit, so the program prints true false.
Challenge 3
A Caesar cipher shifts each letter 3 places along the alphabet, wrapping from z back to a. Shift letter ('y') and print y -> b.
Turn the letter into its position 0 to 25 (letter as u8 - b'a'), add 3, wrap with % 26, add b'a' back, and convert to char.