導入
第3章で String の内部構造は見ました。ここでは実際に文字列を作り、つなぎ、分解する操作を扱います。&str(借りた文字列)と String(所有する文字列)の使い分けも改めて整理します。
説明
fn main() {
let mut s = String::new(); // 空の String
s.push_str("Hello"); // 文字列を追記
s.push('!'); // 1文字を追記
// + や format! で連結
let a = String::from("Hello");
let b = String::from("Rust");
let c = format!("{a}, {b}!"); // format! は所有権を奪わず新しい String を作る
println!("{c}"); // Hello, Rust!
// 分割・変換
let csv = "apple,banana,cherry";
for fruit in csv.split(',') { // 区切りで分割
println!("- {fruit}");
}
let upper = "rust".to_uppercase();
println!("{upper}"); // RUST
}
String::new()/String::from("...")… 空/初期値付きで作成。push_str(文字列)・push(1文字)で追記。format!("{a}, {b}")… 複数の値から新しいStringを作るマクロ。引数の所有権を奪わないので、連結によく使います(+演算子は左辺の所有権をムーブするクセがあり、format!の方が扱いやすい)。split・to_uppercase・trimなど便利メソッドが豊富です。
&str と String の使い分け:関数の引数は基本 &str(借用)にしておくと、String でもリテラルでも渡せて柔軟です。値を所有・保持したい・変更したいときは String を使います。「借りるだけなら &str、持ちたいなら String」が目安です。
補足:Rust の文字列は UTF-8 で、
charは1バイトとは限りません。そのためs[0]のようなバイト添字アクセスはできず、文字単位ならs.chars()、バイト単位ならs.bytes()を使います。日本語のようなマルチバイト文字を安全に扱うための設計です。
試すには
"文字列".chars().count() で文字数、"文字列".len() でバイト数が得られます。日本語だと両者がずれる(1文字が3バイトなど)ことを確認すると、Rust が文字列を UTF-8 として厳密に扱っている理由が見えてきます。