文字列
Rust で最もよく使われる 2 つの文字列型は String と &str です。
String はバイトのベクター(Vec<u8>)として格納されますが、常に有効な UTF-8 シーケンスであることが保証されています。String はヒープに割り当てられ、伸長可能で、null 終端されません。
&str は、常に有効な UTF-8 シーケンスを指すスライス(&[u8])であり、&[T] が Vec<T> へのビューであるのと同様に、String へのビューとして使用できます。
fn main() { // (すべての型注釈は余分です) // 読み取り専用メモリに割り当てられた文字列への参照 let pangram: &'static str = "the quick brown fox jumps over the lazy dog"; println!("Pangram: {}", pangram); // 単語を逆順に反復処理する。新しい文字列は割り当てられない println!("Words in reverse"); for word in pangram.split_whitespace().rev() { println!("> {}", word); } // 文字をベクターにコピーし、ソートして重複を削除する let mut chars: Vec<char> = pangram.chars().collect(); chars.sort(); chars.dedup(); // 空で伸長可能な `String` を作成する let mut string = String::new(); for c in chars { // 文字列の末尾に文字を挿入する string.push(c); // 文字列の末尾に文字列を挿入する string.push_str(", "); } // トリムされた文字列は元の文字列へのスライスなので、新しい // 割り当ては行われない let chars_to_trim: &[char] = &[' ', ',']; let trimmed_str: &str = string.trim_matches(chars_to_trim); println!("Used characters: {}", trimmed_str); // 文字列をヒープに割り当てる let alice = String::from("I like dogs"); // 新しいメモリを割り当て、変更後の文字列をそこに格納する let bob: String = alice.replace("dog", "cat"); println!("Alice says: {}", alice); println!("Bob says: {}", bob); }
さらに多くの str/String メソッドは std::str および std::string モジュールにあります
リテラルとエスケープ
特殊文字を含む文字列リテラルを書く方法は複数あります。 いずれも同様の &str になるため、書くのに最も便利な形式を使うのが最善です。 同様に、バイト文字列リテラルを書く方法も複数あり、いずれも &[u8; N] になります。
一般に、特殊文字はバックスラッシュ文字 \ でエスケープします。 この方法により、出力できない文字や入力方法が分からない文字であっても、任意の文字を文字列に追加できます。 リテラルのバックスラッシュが必要な場合は、もう 1 つのバックスラッシュでエスケープします: \\
リテラル内に現れる文字列または文字リテラルの区切り文字はエスケープする必要があります: "\"", '\''。
fn main() { // エスケープを使って、16 進数値でバイトを書くことができます... let byte_escape = "I'm writing \x52\x75\x73\x74!"; println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape); // ...または Unicode コードポイントを書くこともできます。 let unicode_codepoint = "\u{211D}"; let character_name = "\"DOUBLE-STRUCK CAPITAL R\""; println!("Unicode character {} (U+211D) is called {}", unicode_codepoint, character_name ); let long_string = "String literals can span multiple lines. The linebreak and indentation here ->\ <- can be escaped too!"; println!("{}", long_string); }
エスケープが必要な文字が多すぎる場合や、文字列をそのまま書く方がはるかに便利な場合もあります。 ここで raw 文字列リテラルが役に立ちます。
fn main() { let raw_str = r"Escapes don't work here: \x3F \u{211D}"; println!("{}", raw_str); // raw 文字列内に引用符が必要な場合は、# のペアを追加する let quotes = r#"And then I said: "There is no escape!""#; println!("{}", quotes); // 文字列内に "# が必要な場合は、区切り文字にさらに多くの # を使用するだけです。 // 最大 255 個の # を使用できます。 let longer_delimiter = r###"A string with "# in it. And even "##!"###; println!("{}", longer_delimiter); }
UTF-8 ではない文字列が必要ですか?(str と String は有効な UTF-8 でなければならないことを思い出してください)。 または、ほとんどがテキストであるバイト配列が必要でしょうか? そんなときはバイト文字列の出番です!
use std::str; fn main() { // これは実際には `&str` ではないことに注意 let bytestring: &[u8; 21] = b"this is a byte string"; // バイト配列には `Display` トレイトがないため、出力には少し制限があります println!("A byte string: {:?}", bytestring); // バイト文字列にはバイトエスケープを含めることができます... let escaped = b"\x52\x75\x73\x74 as bytes"; // ...しかし Unicode エスケープは使えません // let escaped = b"\u{211D} is not allowed"; println!("Some escaped bytes: {:?}", escaped); // raw バイト文字列は raw 文字列と同じように機能します let raw_bytestring = br"\u{211D} is not escaped here"; println!("{:?}", raw_bytestring); // バイト配列を `str` に変換すると失敗する可能性があります if let Ok(my_str) = str::from_utf8(raw_bytestring) { println!("And the same as text: '{}'", my_str); } let _quotes = br#"You can also use "fancier" formatting, \ like with normal raw strings"#; // バイト文字列は UTF-8 である必要はありません let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // SHIFT-JIS の "ようこそ" // ただし、その場合は常に `str` に変換できるとは限りません match str::from_utf8(shift_jis) { Ok(my_str) => println!("Conversion successful: '{}'", my_str), Err(e) => println!("Conversion failed: {:?}", e), }; }
文字エンコーディング間の変換については、encoding クレートを確認してください。
文字列リテラルとエスケープ文字の書き方のより詳細な一覧は、Rust Reference の 'Tokens' chapter に記載されています。