自己紹介
出田 守と申します。
しがないPythonプログラマです。
情報セキュリティに興味があり現在勉強中です。CTFやバグバウンティなどで腕を磨いています。主に低レイヤの技術が好きで、そっちばかり目が行きがちです。
Rustを勉強していくうえで、読んで学び、手を動かし、記録し、楽しく学んでいけたらと思います。
環境
新しい言語を学ぶということで、普段使わないWindowsとVimという新しい開発環境で行っています。
OS: Windows10 Home 64bit 1903
CPU: Intel Core i5-3470 @ 3.20GHz
Rust: 1.38.0
RAM: 8.00GB
Editor: Vim 8.1.1
Terminal: PowerShell
前回
前回は配列、ベクタ、スライスについて学びました。
Rust勉強中 - その9
型
文字列型
Rustの文字列型には2つあります。
- ある文字列の位置を指す
&str
型 - ヒープメモリ上に確保される文字列を指す
String
型
バイト文字列
バイト文字列は、u8の列からなるスライスです。先頭にbを付けることで生成できます。
fn print_byte_string() {
println!("\n[print byte string]");
println!("b\"\\\"byte string\\\"\" = {:?} {:?}", b"\"byte string\"", get_type(b"byte string"));
}
[print byte string]
b"\"byte string\"" = [34, 98, 121, 116, 101, 32, 115, 116, 114, 105, 110, 103, 34] "&[u8; 11]"
raw string
以前にも説明しましたraw stringです。一部の文字をエスケープをせずにそのまま出力することができます。
fn print_raw_string() {
println!("\n[print raw string]");
println!("r#\"\"raw string\"\"# = {} {}", r#""raw \nstring""#, get_type(r#"raw \nstring"#));
}
[print raw string]
r#""raw string""# = "raw \nstring" &str
&str型の生成
&str(「string slice」)は連続したUTF-8テキストへの参照を借用しています。&strは常に有効なUTF-8を指します。また、&strもほかのスライスのように、fat pointerです。つまり、文字列のある位置を指したポインタと要素数を持っています。
fn print_string_slice() {
println!("\n[print string slice]");
println!("{} {}", "\"string slice\"", get_type("string slice"));
}
[print string slice]
"string slice" &str
&strの文字へのアクセス
こちらもほかのスライスと同じようなアクセスができます。
fn print_string_slice_access() {
println!("\n[print string slice access]");
println!("&\"string slice\"[..6] = {} {}", &"string slice"[..6], get_type("string slice"));
println!("&\"ストリング スライス\"[..6] = {} {}", &"ストリング スライス"[..6], get_type("ストリング スライス"));
println!("&\"ストリング スライス\"[..15] = {} {}", &"ストリング スライス"[..15], get_type("ストリング スライス"));
}
[print string slice access]
&"string slice"[..6] = string &str
&"ストリング スライス"[..6] = スト &str
&"ストリング スライス"[..15] = ストリング &str
ASCIIは1byteで、UTF-8は複数byteで格納しています。なので上記のような結果になっています。注意が必要です。
&strのメソッド
一部のメソッドを載せておきます。
fn print_string_slice_methods() {
println!("\n[print string slice methods]");
println!("\"string slice\".len() = {}", "string slice".len());
println!("\"ストリング スライス\".len() = {}", "ストリング スライス".len());
println!("\"ストリング スライス\".chars() = {:?}", "ストリング スライス".chars());
println!("\"ストリング スライス\".chars().count() = {}", "ストリング スライス".chars().count());
println!("\"string slice\".contains(\"sli\") = {}", "string slice".contains("sli"));
println!("\"string slice\".to_uppercase() = {}", "string slice".to_uppercase());
println!("\"String Slice\".to_lowercase() = {}", "String Slice".to_lowercase());
println!("\"\\nstring \\tslice\\n\".trim() = {}", "\nstring slice\n".trim());
}
[print string slice methods]
"string slice".len() = 12
"ストリング スライス".len() = 30
"ストリング スライス".chars() = Chars(['ス', 'ト', 'リ', 'ン', 'グ', '\u{3000}', 'ス', 'ラ', 'イ', 'ス'])
"ストリング スライス".chars().count() = 10
"string slice".contains("sli") = true
"string slice".to_uppercase() = STRING SLICE
"String Slice".to_lowercase() = string slice
"\nstring \tslice\n".trim() = string slice
Stringの生成方法
&strをスライスへの参照とするなら、Stringはベクタといった位置づけです。
Stringの生成方法は様々にあるようです。
- String::newとString::with_capacityから生成
- to_stringメソッドから生成
- format!マクロから生成
- concatメソッド, joinメソッドから生成
などなど色々あるようです。
fn print_String() {
println!("\n[print String]");
println!("String::new() = {} {}", String::new(), get_type(String::new()));
println!("String::with_capacity(6) = {} {}", String::with_capacity(6), get_type(String::with_capacity(6)));
println!("\"String\".to_string() = {} {}", "String".to_string(), get_type("String".to_string()));
println!("format!(\"{}\", \"String\") = {} {}", "{}", format!("{}", "String"), get_type(format!("{}", "String")));
println!("[\"Str\", \"ing\"].concat() = {} {}", ["Str", "ing"].concat(), get_type(["Str", "ing"].concat()));
}
[print String]
String::new() = alloc::string::String
String::with_capacity(6) = alloc::string::String
"String".to_string() = String alloc::string::String
format!("{}", "String") = String alloc::string::String
["Str", "ing"].concat() = String alloc::string::String
Stringのメソッド
一部メソッドを載せておきます。
fn print_String_methods() {
println!("\n[print String methods]");
let mut s = String::new();
println!("s.push('S'); s.push_str(\"tring\") = {}", {s.push('S'); s.push_str("tring"); s});
println!("\"String\".to_string().len() = {}", "String".to_string().len());
println!("\"String\".to_string().capacity() = {}", "String".to_string().capacity());
println!("\"String\".to_string().remove(0) = {}", "String".to_string().remove(0));
}
[print String methods]
s.push('S'); s.push_str("tring") = String
"String".to_string().len() = 6
"String".to_string().capacity() = 6
"String".to_string().remove(0) = S
使用したソース
...
fn print_byte_string() {
println!("\n[print byte string]");
println!("b\"\\\"byte string\\\"\" = {:?} {:?}", b"\"byte string\"", get_type(b"byte string"));
}
fn print_raw_string() {
println!("\n[print raw string]");
println!("r#\"\"raw string\"\"# = {} {}", r#""raw \nstring""#, get_type(r#"raw \nstring"#));
}
fn print_string_slice() {
println!("\n[print string slice]");
println!("{} {}", "string slice", get_type("string slice"));
}
fn print_string_slice_access() {
println!("\n[print string slice access]");
println!("&\"string slice\"[..6] = {} {}", &"string slice"[..6], get_type(&"string slice"[..6]));
println!("&\"ストリング スライス\"[..6] = {} {}", &"ストリング スライス"[..6], get_type(&"ストリング スライス"[..6]));
println!("&\"ストリング スライス\"[..15] = {} {}", &"ストリング スライス"[..15], get_type(&"ストリング スライス"[..15]));
}
fn print_string_slice_methods() {
println!("\n[print string slice methods]");
println!("\"string slice\".len() = {}", "string slice".len());
println!("\"ストリング スライス\".len() = {}", "ストリング スライス".len());
println!("\"ストリング スライス\".chars() = {:?}", "ストリング スライス".chars());
println!("\"ストリング スライス\".chars().count() = {}", "ストリング スライス".chars().count());
println!("\"string slice\".contains(\"sli\") = {}", "string slice".contains("sli"));
println!("\"string slice\".to_uppercase() = {}", "string slice".to_uppercase());
println!("\"String Slice\".to_lowercase() = {}", "String Slice".to_lowercase());
println!("\"\\nstring \\tslice\\n\".trim() = {}", "\nstring slice\n".trim());
}
fn print_String() {
println!("\n[print String]");
println!("String::new() = {} {}", String::new(), get_type(String::new()));
println!("String::with_capacity(6) = {} {}", String::with_capacity(6), get_type(String::with_capacity(6)));
println!("\"String\".to_string() = {} {}", "String".to_string(), get_type("String".to_string()));
println!("format!(\"{}\", \"String\") = {} {}", "{}", format!("{}", "String"), get_type(format!("{}", "String")));
println!("[\"Str\", \"ing\"].concat() = {} {}", ["Str", "ing"].concat(), get_type(["Str", "ing"].concat()));
}
fn print_String_methods() {
println!("\n[print String methods]");
let mut s = String::new();
println!("s.push('S'); s.push_str(\"tring\") = {}", {s.push('S'); s.push_str("tring"); s});
println!("\"String\".to_string().len() = {}", "String".to_string().len());
println!("\"String\".to_string().capacity() = {}", "String".to_string().capacity());
println!("\"String\".to_string().remove(0) = {}", "String".to_string().remove(0));
}
fn main() {
...
println!("\n>> String type <<");
print_byte_string();
print_raw_string();
print_string_slice();
print_string_slice_access();
print_string_slice_methods();
print_String();
print_String_methods();
}
>> String type <<
[print byte string]
b"\"byte string\"" = [34, 98, 121, 116, 101, 32, 115, 116, 114, 105, 110, 103, 34] "&[u8; 11]"
[print raw string]
r#""raw string""# = "raw \nstring" &str
[print string slice]
string slice &str
[print string slice access]
&"string slice"[..6] = string &str
&"ストリング スライス"[..6] = スト &str
&"ストリング スライス"[..15] = ストリング &str
[print string slice methods]
"string slice".len() = 12
"ストリング スライス".len() = 30
"ストリング スライス".chars() = Chars(['ス', 'ト', 'リ', 'ン', 'グ', '\u{3000}', 'ス', 'ラ', 'イ', 'ス'])
"ストリング スライス".chars().count() = 10
"string slice".contains("sli") = true
"string slice".to_uppercase() = STRING SLICE
"String Slice".to_lowercase() = string slice
"\nstring \tslice\n".trim() = string slice
[print String]
String::new() = alloc::string::String
String::with_capacity(6) = alloc::string::String
"String".to_string() = String alloc::string::String
format!("{}", "String") = String alloc::string::String
["Str", "ing"].concat() = String alloc::string::String
[print String methods]
s.push('S'); s.push_str("tring") = String
"String".to_string().len() = 6
"String".to_string().capacity() = 6
"String".to_string().remove(0) = S
今回はここまで。
ここまでで一応基本的な型は終わりです。