Rustの基礎 - 基本的なデータ型

提供: MochiuWiki : SUSE, EC, PCB

概要

ここでは、Rustプログラミングの基礎として、基本的なデータ型と文法等を記載する。


println!マクロ

以下に示すように、文字列リテラルを println! マクロで出力するには、() の中にダブルクォーテーション""で文字列を囲んで入力する。
Rustでは、出力には println! マクロを使用する。
Rustでは、マクロには ! が付く。

 fn main() {
     println!("Rust");
 }
 
 // 出力
 Rust


次に、以下のように入力すると、Rust C++と出力される。

 fn main() {
     println!("Rust C++");
 }
 
 // 出力
 Rust C++


複数の値を出力する場合は、プレースホルダー{}を使用する。

 fn main() {
     println!("{} {}", "Rust", "C++");
 }
 
 // 出力
 Rust C++



println!マクロのフォーマット

複数の値の出力

プレースホルダーを使用して、複数の値を出力することができる。

 fn main() {
     println!("{},{}", "Rust", "C++");
 }
 
 // 出力
 Rust,C++


名前付きパラメータを使用することもできる。

 fn main() {
     println!("{lang1},{lang2}", lang1 = "Rust", lang2 = "C++");
 }
 
 // 出力
 Rust,C++


printマクロ (改行なし)

改行しない出力を行う場合は、print!マクロを使用する。

 fn main() {
     print!("Rust,");
     print!("C++");
 }
 
 // 出力
 Rust,C++


明示的に改行コード \n を入れることもできる。

 fn main() {
     print!("Rust\n");
     print!("C++\n");
 }
 
 // 出力
 Rust
 C++



変数の宣言と使用

基本

Rustでは、let キーワードを使用して変数を宣言する。
デフォルトで変数は 不変 (immutable) である。

 fn main() {
     let msg = "こんにちは、Rust";
     let num = 100;
     println!("{}", msg);
     println!("{}", num);
 }
 
 // 出力
 こんにちは、Rust
 100


Rustの変数はデフォルトで不変なので、値を変更する場合は mut キーワードを使用して可変にする必要がある。

 fn main() {
     let mut msg = "こんにちは、Rust";
     let num = 100;
     msg = "さようなら、Rust";
     println!("{}", msg);
 }
 
 // 出力
 さようなら、Rust


型注釈

Rustは静的型付け言語であり、変数の型を明示的に指定することができる。
型推論も強力なので、多くの場合は型を省略できるが、明示的に記述することで可読性が向上する。

 fn main() {
     let msg: &str = "こんにちは、Rust";
     let num: i32 = 100;
     println!("{}", msg);
     println!("{}", num);
 }


シャドーイングを使用すると、同じ変数名で異なる型の値を代入できる。

 fn main() {
     let msg = "こんにちは、Rust";
     let msg = 100;
     println!("{}", msg);
 }
 
 // 出力
 100


型変換 (キャスト)

文字列を数値に変換する場合、parse メソッドを使用する。
parseメソッドはResult型を返すので、unwrapexpect で値を取り出す。

 fn main() {
     let strnum = "100";
     let inum: i32 = strnum.parse().unwrap();
     println!("{}", inum);
 }
 
 // 出力
 100


数値型から別の数値型への変換には、as キーワードを使用する。

 fn main() {
     let x: i32 = 100;
     let y: f64 = x as f64;
     println!("{}", y);
 }
 
 // 出力
 100



数値と四則演算

Rustの基本的な数値型には、符号付き整数(i8, i16, i32, i64, i128, isize)、符号なし整数(u8, u16, u32, u64, u128, usize)、浮動小数点数(f32, f64)がある。
デフォルトでは、整数はi32、浮動小数点数はf64として推論される。

 fn main() {
     let a = 10;
     let b = 20;
     
     println!("足し算: {}", a + b);
     println!("引き算: {}", b - a);
     println!("掛け算: {}", a * b);
     println!("割り算: {}", b / a);
     println!("剰余: {}", b % a);
 }
 
 // 出力
 足し算: 30
 引き算: 10
 掛け算: 200
 割り算: 2
 剰余: 0


複合代入演算子を使用することができる。

 fn main() {
     let mut x = 10;
     x += 5;  // x = x + 5
     println!("{}", x);
     
     x *= 2;  // x = x * 2
     println!("{}", x);
 }
 
 // 出力
 15
 30



文字列

Rustには、文字列リテラル型 &strString型 の2種類の文字列がある。
文字列リテラルは不変で、プログラムにハードコードされたテキストに使用される。
String型は可変で、実行時に変更可能なヒープ割り当ての文字列である。

 fn main() {
     let s1 = "Hello";  // &str型
     let s2 = String::from("Hello");  // String型
     
     println!("{}", s1);
     println!("{}", s2);
     
     let s3 = "Hello ".to_string() + "Rust!";
     println!("{}", s3);
 }
 
 // 出力
 Hello
 Hello
 Hello Rust!


文字列の長さを取得するには、len メソッドを使用する。

 fn main() {
     let greeting = "Hello Rust!";
     println!("{}", greeting.len());
 }
 
 // 出力
 11


文字列の繰り返しは、repeat メソッドを使用する。

 fn main() {
     let s = "Hello!".repeat(3);
     println!("{}", s);
 }
 
 // 出力
 Hello!Hello!Hello!


改行

改行する箇所に、\nを入れる。

 fn main() {
     println!("Hello, \nRust");
 }
 
 // 出力
 Hello, 
 Rust


複数行にわたる長い文章の表示は、生文字列リテラル(r#"..."#)を使用する。

 fn main() {
     let strhoge = r#"Hello, 
              Rust"#;
     println!("{}", strhoge);
 }
 
 // 出力
 Hello, 
 Rust


または、通常の文字列リテラルでも複数行にわたって記述できる。

 fn main() {
     let strhoge = "Hello, 
              Rust";
     println!("{}", strhoge);
 }
 
 // 出力
 Hello, 
 Rust



文字列の抽出と分割

Rustの文字列は、UTF-8エンコードされたバイト列である。
文字列のインデックスは、バイト単位であり、文字単位ではないことに注意が必要である。

文字の抽出

chars メソッドを使用して、文字列を文字単位で処理する。

 fn main() {
     let word = "rust";
     let chars: Vec<char> = word.chars().collect();
     
     println!("{}", chars[0]);
     println!("{}", chars[1]);
 }
 
 // 出力
 r
 u


nth メソッドを使用して、特定の位置の文字を取得する。

 fn main() {
     let word = "rust";
     
     if let Some(c) = word.chars().nth(0) {
         println!("{}", c);
     }
     if let Some(c) = word.chars().nth(3) {
         println!("{}", c);
     }
 }
 
 // 出力
 r
 t


文字列の抽出

文字列を抽出する場合は、スライスを使用する。

※注意
スライスはバイト単位で指定するため、マルチバイト文字の途中で切ると実行時エラーになる。

 fn main() {
     let word = "rust";
     println!("{}", &word[0..3]);
     println!("{}", &word[..3]);
     println!("{}", &word[1..4]);
     println!("{}", &word[2..]);
 }
 
 // 出力
 rus
 rus
 ust
 st


安全に部分文字列を取得するには、get メソッドを使用する。

 fn main() {
     let word = "rust";
     
     if let Some(sub) = word.get(0..3) {
         println!("{}", sub);
     }
     if let Some(sub) = word.get(2..) {
         println!("{}", sub);
     }
 }
 
 // 出力
 rus
 st



文字列の検索・置換・結合

lenメソッドで文字列の長さを出力

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     println!("{}", s.len());
 }
 
 // 出力
 66


containsメソッドを使用して存在の有無を調べる

文字列の中に、特定の文字や文字列が含まれるかどうかを contains メソッドを使用して調べる。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     let in_rust_word = s.contains("Rust");
     let in_cpp_word = s.contains("C++");
     
     println!("{}", in_rust_word);
     println!("{}", in_cpp_word);
 }
 
 // 出力
 true
 false


splitメソッドで文字列を分割する

split メソッドを使用して、文字列を分割する。
分割結果はイテレータとして返されるので、collect メソッドでベクターに変換できる。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     let words: Vec<&str> = s.split_whitespace().collect();
     println!("{:?}", words);
 }
 
 // 出力
 ["I", "am", "programming", "with", "Rust.", "It", "is", "a", "systems", "programming", "language."]


次に、セパレータにピリオドを指定して分割する。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     let parts: Vec<&str> = s.split('.').collect();
     println!("{:?}", parts);
 }
 
 // 出力
 ["I am programming with Rust", " It is a systems programming language", ""]


更に、セパレータにスペースを指定して分割する。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     let parts: Vec<&str> = s.split(' ').collect();
     println!("{:?}", parts);
 }
 
 // 出力
 ["I", "am", "programming", "with", "Rust.", "It", "is", "a", "systems", "programming", "language."]


joinメソッドで結合する

join メソッドは、文字列のスライスを1つの文字列に結合する。

 fn main() {
     let words = vec!["I", "am", "programming", "with", "Rust"];
     let sentence = words.join(" ");
     println!("{}", sentence);
 }
 
 // 出力
 I am programming with Rust


findメソッドで検索する

find メソッドは、対象の文字列から検索したい文字列がどこにあるのか調べるメソッドである。
Option型を返すので、Some で値を取り出す。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     
     if let Some(pos) = s.find("Rust") {
         println!("{}", pos);
     }
 }
 
 // 出力
 22


また、文字列を後ろから検索する場合は、rfind メソッドを使用する。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     
     if let Some(pos) = s.rfind("programming") {
         println!("{}", pos);
     }
 }
 
 // 出力
 48


matchesメソッドで数える

文字列の中に特定の文字列が何回出現するかを数えるには、matches メソッドを使用する。

 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     let count = s.matches("programming").count();
     println!("{}", count);
     
     let count_i = s.matches('i').count();
     println!("{}", count_i);
 }
 
 // 出力
 2
 4


replaceメソッドで置換する

文字や文字列を置き換える場合は、replace メソッドを使用する。

 fn main() {
     let s = "I am programming with Rust.";
     let new_s = s.replace("Rust", "Go");
     println!("{}", new_s);
 }
 
 // 出力
 I am programming with Go.


to_uppercase / to_lowercaseメソッドで文字列を変換する

これらのメソッドは、文字列の大文字・小文字を操作する時に使用する。

  • to_uppercaseメソッド
    全ての文字を大文字に変換する。
  • to_lowercaseメソッド
    全ての文字を小文字に変換する。
 fn main() {
     let s = "I am programming with Rust. It is a systems programming language.";
     println!("{}", s.to_uppercase());
     println!("{}", s.to_lowercase());
 }
 
 // 出力
 I AM PROGRAMMING WITH RUST. IT IS A SYSTEMS PROGRAMMING LANGUAGE.
 i am programming with rust. it is a systems programming language.


trim メソッドで前後の空白を削除する。

 fn main() {
     let s = "   Hello Rust   ";
     println!("'{}'", s.trim());
 }
 
 // 出力
 'Hello Rust'