Rustの文字列
テキストの扱いは、Rustがほかの言語と違うと感じる最初のポイントのひとつです。その主な理由は、Rustには文字列の型が2つあるからです。でも、なぜ2つあるのかがわかれば、もう混乱することはありません。
&str と String
Section titled “&str と String”&str(「文字列スライス」)— どこかにすでに存在しているテキストです。たいていはコードの中に直接書いたものです。サイズは固定で、伸ばすことはできません。String— 所有権を持った、伸ばせるテキストです。あとから文字を追加でき、ヒープ(heap)というメモリ領域に置かれます。
fn main() { let literal: &str = "こんにちは"; // 文字列スライス let owned: String = String::from("こんにちは"); // 所有権を持つ String
println!("{literal} / {owned}");}簡単な目安:決まったテキストを表示するだけなら、"こんなふうに" 書いたもの(&str)で十分です。実行中にテキストを組み立てたり、伸ばしたり、変更したりする必要があるなら、String を使いましょう。
String を伸ばす
Section titled “String を伸ばす”fn main() { let mut greeting = String::from("こんにちは"); greeting.push_str("、世界"); // &str を追加する greeting.push('!'); // 1文字(char)を追加する
println!("{greeting}");}実行結果:
こんにちは、世界!文字列を連結する
Section titled “文字列を連結する”文字列は + でつなげることもできますし、format! を使うこともできます(たいていは format! のほうがわかりやすいです)。
fn main() { let first = String::from("こんにちは、"); let second = String::from("世界!");
let combined = first + &second; // second の前に & が付いていることに注意 println!("{combined}");
// format! のほうが読みやすいことが多い let name = "Ferris"; let greeting = format!("こんにちは、{name}さん!"); println!("{greeting}");}よく使う文字列メソッド
Section titled “よく使う文字列メソッド”いつも使うことになるメソッドをいくつか紹介します。この例では、あえてテキストを英語のままにしています。.len() は長さをバイト数で数えますが、日本語の文字は1文字で3バイトになるため、日本語にすると結果が変わってしまうからです。また、大文字・小文字の変換も英字でないと違いがわかりません。
fn main() { let text = " Hello, Rust! ";
println!("{}", text.trim()); // "Hello, Rust!"(前後の空白を除去) println!("{}", text.to_uppercase()); // " HELLO, RUST! " println!("{}", text.to_lowercase()); // " hello, rust! " println!("{}", text.contains("Rust")); // true println!("{}", text.trim().len()); // 12(バイト単位の長さ) println!("{}", text.trim().replace("Rust", "World")); // "Hello, World!"}文字列を1文字ずつループする
Section titled “文字列を1文字ずつループする”1文字ずつ順番に処理するには、.chars() を使います。
fn main() { for c in "abc".chars() { println!("{c}"); }}1. 入力を整える
Section titled “1. 入力を整える”誰かがフォームに " rUsT is FUN " と入力しました。これを rust is great に変えてください。余分な空白を取り除き、すべて小文字にして、fun を great に置き換えます。そして、結果とその長さを表示しましょう。ヒント:文字列のメソッドは text.trim().to_lowercase()... のように、次々につなげて呼び出せます。
解答を見る
ここでも、テキストは英語のままにしています。.len() はバイト数を数えるので、日本語にすると結果が変わってしまうからです。
fn main() { let input = " rUsT is FUN ";
// まず trim、次に小文字にして、(もう小文字になった)"fun" を置き換える let clean = input.trim().to_lowercase().replace("fun", "great");
println!("{clean}"); println!("{}バイト", clean.len());}実行結果:
rust is great13バイト順番が大切です。.to_lowercase() より前に .replace("fun", "great") を呼ぶと、テキストはまだ FUN のままなので、何も置き換わりません。
2. メールアドレスを組み立てる
Section titled “2. メールアドレスを組み立てる”first = "Ada" と last = "Lovelace" から、[email protected] という String を組み立てて表示してください。それから、@ が含まれているかどうかも表示しましょう。ヒント:format! の {} には、first.to_lowercase() のような式も渡せます。
解答を見る
fn main() { let first = "Ada"; let last = "Lovelace";
let email = format!("{}.{}@example.com", first.to_lowercase(), last.to_lowercase());
println!("{email}"); println!("正しそう: {}", email.contains('@'));}実行結果:
正しそう: true&strは借用された固定のテキスト、Stringは所有権を持ち、伸ばせるテキストです。Stringを伸ばすには、.push_str()(テキスト用)か.push()(1文字用)を使います。- 文字列をつなげるときは、
+よりformat!を使いましょう。わかりやすく、何もムーブしません。 - よく使うメソッド:
.trim()、.to_uppercase()、.contains()、.replace()、.chars()。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. 所有権を持ち、実行中に伸ばせる文字列の型はどれですか?
2. 3つ以上の文字列をつなげるとき、このページが + より format! をすすめるのはなぜですか?
3. Rustの文字列に text[0] のようにインデックスでアクセスできないのはなぜですか?
4. greeting.push('!') のように、伸ばせる String に1文字を追加するメソッドはどれですか?
スコア: 0 / 4
さらに詳しく
Section titled “さらに詳しく”- 文字列でUTF-8でエンコードされたテキストを保持する — The Rust Programming Language 日本語版:
Stringについての公式の章です。位置を指定してインデックスでアクセスできない理由も説明しています。 - スライス型 — The Rust Programming Language 日本語版:「文字列スライス」の節で、
&strの正体を説明しています。借用を学んだあとに読むのがおすすめです。 - 文字列 — Rust by Example 日本語版:
Stringと&strの実行できる例に加えて、エスケープ文字や生文字列リテラル(raw string)も紹介しています。 String— 標準ライブラリのドキュメント(英語):所有権を持つStringのすべてのメソッドが、それぞれ小さな例付きで載っています。str— 標準ライブラリのドキュメント(英語):trim、contains、replace、splitなど、どんなテキストにも使えるメソッドです。