We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ground Rules: Values, Types, Control Flow step 9 of 24
bool and char
Classify every character of a string as "digit", "alpha", "space" or
"other", in order.
pub fn char_kinds(text: &str) -> Vec<String>
Test them in that order: a digit is a digit even though it is not alphabetic,
and anything that is neither a digit, nor a letter, nor whitespace is "other".
"a1 é" gives ["alpha", "digit", "space", "alpha"] — four results, from a
string that is five bytes long. That gap is the entire point.
The starter fails the gate on a clippy lint that exists specifically to catch a beginner reflex.
char is four bytes and holds a Unicode scalar value
In C, char is a byte. In Rust it is not. A char is exactly 4 bytes and
holds one Unicode scalar value — any code point from U+0000 to U+10FFFF,
excluding the surrogate range U+D800..=U+DFFF which exists only as a UTF-16
implementation detail.
So 'é' is one char. '語' is one char. '🦀' is one char. Each of them
occupies four bytes as a char value, and two, three or four bytes when encoded
into a UTF-8 string.
That is why "a1 é" is five bytes but four characters, and it is the seed of
the whole UTF-8 story that item 1.24 tells properly. Two ways of walking a
string:
text.chars() // yields char — what a human means by "character"
text.bytes() // yields u8 — what the memory actually contains
Reaching for .bytes() here would give you five results and would misclassify
the two halves of é as "other". .chars() is the one you want.
Useful predicates, all on char:
-
is_ascii_digit()— strictly'0'..='9'. There is alsois_numeric(), which is true for'٣'and'Ⅳ'too; pick deliberately. -
is_alphabetic()— Unicode-aware, so'é','Ω'and'語'all qualify. -
is_whitespace()— Unicode-aware, so non-breaking space counts. -
is_ascii_alphanumeric(),is_uppercase(),to_ascii_lowercase(), and more.
bool is a type, not an integer
Rust’s bool has exactly two values and does not convert to a number by
itself. if x requires x: bool — an integer will not do, and if 1 is
E0308. There is no truthiness. This removes an entire class of C bug and
occasionally annoys you for about four seconds.
Three default-on clippy lints police the beginner reflexes here, and you will meet the first one in the starter:
-
bool_comparison—x == trueis justx, andx == falseis!x. Comparing a boolean to a boolean literal adds a comparison and subtracts clarity. -
needless_bool—if cond { true } else { false }is justcond. -
char_lit_as_u8—'A' as u8compiles but is almost always a mistake in disguise;b'A'is a byte literal and says what you meant.
None of these need configuration. They are on for everyone, by default, and they are exactly the mistakes a newcomer makes — the gate does real teaching here for free.
Building the answer
Bind one &str from an if/else if chain, then convert it to a String when
you push it. Four string literals and one conversion; no format! needed, and
useless_format would tell you so if you tried.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.