1. 概要
今回はRustの文字列型について学んでいきたいと思います。
2. 文字列型
Rustの文字列型には、2つの種類があります。「String型」と「&str型」です。
それぞれの特徴としては、
- String型は、Rust内部では「Vec<u8>」として扱われます。伸縮可能でヒープ上に保持されます。C言語などとは違い、末端にnullは含みません。
- &str型は、ある文字列のスライス「&[u8]」です。参照型で、所有権を持たない型です。
&str型について、実際にプログラムで確認していきましょう。
fn main() {
// 先頭1文字を取得
let s = "Hello,World";
println!("{}", &s[0..1]);
// 日本語の&str型から、先頭の1文字と3文字目を取得
let s2 = "こんにちは";
println!("{}", &s2[0..3]);
println!("{}", &s2[6..9]);
// &str型をString型へ変換
let s3 = "Hello Rust";
let str = String::from(s3);
let str2 = s3.to_string();
println!("{}", get_type(s3));
println!("{}", get_type(str));
println!("{}", get_type(str2));
}
// 型名を取得
fn get_type<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
結果
Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
Finished dev [unoptimized + debuginfo] target(s) in 0.53s
Running `target/debug/hello_rust`
H
こ
に
&str
alloc::string::String
alloc::string::String
最初は、先頭の1文字目を取得するものです。前回にスライスついてやりましたが、使い方は同じです。次に日本語の文字列からスライスで文字列を取り出しています。どちらも先頭の1文字だけを取得しているのですが、違いは、半角英字の方は「&s[0..1]」ですが、日本語の方は「&s2[0..3]」になっています。これはなぜかというとバイト単位で指定しなければならないからです。試しに、「&s2[0..2]」に書き替えて実行して見ましょう。
Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
Finished dev [unoptimized + debuginfo] target(s) in 0.53s
Running `target/debug/hello_rust`
H
thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside 'こ' (bytes 0..3) of `こんにちは`', library/core/src/str/mod.rs:127:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
訳すると、「s2の0から数えて2文字目は、文字の境界線ではない。」と言われてます。名前などの日本語の文字列から1部を参照する場合などは、気をつけたいですね。
最後に、&str型からString型に変換する処理です。 「String::from()」「to_String()」などを使用すると変換ができます。
次に、String型についてプログラムで確認していきましょう。
fn main() {
// String型の変数を定義
let str = String::from("Hello World");
println!("{}", str);
// String型も変数を宣言し、push_strメソッドを使用して、文字列を追加
let mut str = String::new();
str.push_str("hello");
str.push_str(",World");
println!("{}", str);
// String型から&str型へ変換
let str2 = String::from("Hello Rust");
let s1: &str = &str2;
let s2 = str2.as_str();
println!("{}", get_type(&str2));
println!("{}", get_type(s1));
println!("{}", get_type(s2));
}
// 型名を取得
fn get_type<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
結果
Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
Finished dev [unoptimized + debuginfo] target(s) in 0.54s
Running `target/debug/hello_rust`
Hello World
hello,World
&alloc::string::String
&str
&str
最初は、「String:: from()」を使用して、String型の変数を定義しています。String型の変数を定義する時はこの方法がよく使われると思うます。
次に、「String:: new()」で初期化して、その後「push_str()」を使用して文字列を追加しています。冒頭で述べた通り、Rust内部でString型は「Vec<u8>」として扱われます。なので文字列を追加する時は、「pusu_str()」を、文字を追加する時は「push()」を使用します。
最後に、String型を&str型へ変換する処理です。&を使用し、借用して値を代入することで変換できます。次は、「as_str()」を使用して変換しています。
3. まとめ
今回は、文字列型についてやっていきました。場面によって使い分けることができるので個人的には便利だと感じました。文字列型にも関数がたくさんあるので、今後、他の記事でも使っていきたいなと思ってます。
投稿者プロフィール
最新の投稿
【Remix】2024年3月23日【Remix】 環境構築手順
【Rust】2022年11月27日【Rust】Unsafe Rust
【Rust】2022年11月27日【Rust】列挙型
【Rust】2022年10月22日【Rust】構造体