String::len() / is_empty() / contains()
| 対応: | Rust 1.0(2015) |
|---|
Rustの文字列(String・&str)には長さの取得・空文字判定・検索・前後判定など多くのメソッドが用意されています。『len()』『is_empty()』『contains()』『starts_with()』『ends_with()』などがよく使われます。
構文
let s = String::from("Hello, Rust!");
// バイト数を返します(文字数ではありません)。
let len = s.len(); // 12(ASCII文字は1バイト)
// 空文字かどうかを返します。
let empty = s.is_empty(); // false
// 部分文字列が含まれるか確認します。
let has = s.contains("Rust"); // true
// 指定した文字列で始まるか確認します。
let starts = s.starts_with("Hello"); // true
// 指定した文字列で終わるか確認します。
let ends = s.ends_with("!"); // true
// 最初に一致した位置(バイトオフセット)を返します。
let idx = s.find("Rust"); // Some(7)
// すべての一致位置を取得します。
let positions: Vec<_> = s.match_indices("l").collect();
メソッド一覧
| メソッド | 概要 |
|---|---|
| s.len() | 文字列のバイト数を返します(文字数ではありません)。 |
| s.is_empty() | 文字列が空(len() == 0)かどうかを返します。 |
| s.contains(pattern) | パターンが含まれていれば true を返します。 |
| s.starts_with(prefix) | 指定した文字列・文字で始まれば true を返します。 |
| s.ends_with(suffix) | 指定した文字列・文字で終われば true を返します。 |
| s.find(pattern) | 最初にマッチしたバイトオフセットをOption<usize>で返します。 |
| s.rfind(pattern) | 最後にマッチしたバイトオフセットをOption<usize>で返します。 |
| s.match_indices(pattern) | すべてのマッチ位置と文字列をイテレータで返します。 |
| s.chars().count() | Unicode文字数を返します(日本語など多バイト文字対応)。 |
| s.is_ascii() | すべての文字がASCII文字かどうかを返します。 |
サンプルコード
『len』『is_empty』『contains』を使った文字列の検査メソッドを確認するサンプルコードです。
sample_string_len_isempty_contains.rs
fn main() {
let s = String::from("Hello, Rust! Rustは素晴らしい。");
// バイト数と文字数の違いです。
println!("len(バイト数): {}", s.len());
println!("chars().count()(文字数): {}", s.chars().count());
// 空文字の判定です。
let empty = String::new();
let non_empty = String::from("hello");
println!("empty.is_empty(): {}", empty.is_empty());
println!("non_empty.is_empty(): {}", non_empty.is_empty());
println!();
// contains・starts_with・ends_with です。
println!("'Rust'を含む: {}", s.contains("Rust"));
println!("'Python'を含む: {}", s.contains("Python"));
println!("'Hello'で始まる: {}", s.starts_with("Hello"));
println!("'。'で終わる: {}", s.ends_with("。"));
println!("'Rust'で終わる: {}", s.ends_with("Rust"));
println!();
// find(最初の位置)です。
match s.find("Rust") {
Some(i) => println!("最初の'Rust'の位置: {}", i),
None => println!("'Rust'は見つかりません"),
}
match s.find("Python") {
Some(i) => println!("最初の'Python'の位置: {}", i),
None => println!("'Python'は見つかりません"),
}
// rfind(最後の位置)です。
if let Some(i) = s.rfind("Rust") {
println!("最後の'Rust'の位置: {}", i);
}
println!();
// match_indices(すべての一致)です。
let text = "majima goro";
let positions: Vec<_> = text.match_indices("ma").collect();
println!("'majima goro'内の'ma'の位置: {:?}", positions);
// ASCII判定です。
println!("'Hello'はASCII: {}", "Hello".is_ascii());
println!("'Hello世界'はASCII: {}", "Hello世界".is_ascii());
// 実用例:入力値の検証です。
let input = " ";
if input.trim().is_empty() {
println!("\n入力が空です");
}
}
コンパイルして実行すると次のように出力されます。
rustc string_len_isempty_contains.rs ./string_len_isempty_contains len(バイト数): 38 chars().count()(文字数): 24 empty.is_empty(): true non_empty.is_empty(): false 'Rust'を含む: true 'Python'を含む: false 'Hello'で始まる: true '。'で終わる: true 'Rust'で終わる: false 最初の'Rust'の位置: 7 'Python'は見つかりません 最後の'Rust'の位置: 13 'majima goro'内の'ma'の位置: [(0, "ma"), (4, "ma")] 'Hello'はASCII: true 'Hello世界'はASCII: false 入力が空です
よくあるミス
よくあるミス1: len()を文字数と勘違い
len()はバイト数を返します。日本語のような多バイト文字の文字列では、文字数を取得するにはchars().count()が必要です。
string_len_mistake1.rs
fn main() {
let s = "五条悟"; // 各漢字は3バイト
println!("len()={}", s.len()); // 9(バイト数)
println!("chars().count()={}", s.chars().count()); // 3(文字数)
// len()が0でなくても文字がない場合はあります。
// (ただし通常のUTF-8文字列では起こりません)
// 文字数での判定が必要な場合です。
if s.chars().count() == 3 {
println!("3文字の名前です");
}
}
rustc string_len_mistake1.rs ./string_len_mistake1 len()=9 chars().count()=3 3文字の名前です
よくあるミス2: find()の戻り値をバイトオフセットでなく文字インデックスと混同
find()はバイトオフセットを返します。日本語文字列では文字インデックスと異なります。取得したオフセットはスライスに使えますが、「何文字目」という意味ではありません。
string_find_note.rs
fn main() {
let s = "こんにちは、世界!";
// find()は「世」のバイトオフセットを返します(文字インデックスではない)。
if let Some(idx) = s.find("世") {
println!("バイトオフセット: {}", idx); // 18(3バイト×6文字)
println!("スライス: {}", &s[idx..]); // 「世界!」として正しく使えます。
}
// 文字インデックス(何文字目か)を求める場合です。
let char_pos = s.chars().position(|c| c == '世');
println!("文字インデックス: {:?}", char_pos); // Some(6)
}
rustc string_find_note.rs ./string_find_note バイトオフセット: 18 スライス: 世界! 文字インデックス: Some(6)
概要
Rustの文字列はUTF-8エンコードされており、『len()』はバイト数を返します。日本語などのマルチバイト文字を含む場合はバイト数と文字数が異なります。文字数を取得するには『s.chars().count()』を使ってください。
『find()』はバイトオフセットを返します。このオフセットは文字境界である保証があるため、スライス『&s[0..idx]』のように使えます。ただし日本語文字の「途中」を指すインデックスでスライスするとパニックします。
len()は文字数(Unicodeコードポイント数)ではなくバイト数を返します。文字数が必要な場合は必ずchars().count()を使ってください。
文字列の置換・分割・トリムは『String::replace() / split() / trim()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。