やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

RustのコレクションString型

 文字列型はなんと6種類もある。

成果物

文字列

 文字列型は2種類に大別できる。Rust内部で文字はUTF-8で扱う。

メモリ確保領域 (可不)変
str スタック 不(固定長 immutable)
String ヒープ 可(可変長 mutable)

文字列型

(可 不)変 Rust C言語 Windowsワイド文字 Windows拡張 Unix拡張
std::str std::ffi::CStr std::ffi::OsStr std::os::windows::ffi::OsStrExt std::os::unix::ffi::OsStrExt
std::string::String std::ffi::CString std::ffi::OsString std::os::windows::ffi::OsStringExt std::os::unix::ffi::OsStringExt

内部表現

 StringVec<u8>のラッパ。String.len()で得られるのはバイト数である。文字数ではない。StringはUTF-8のバイト配列となる。

観点

使い方

生成

let s = String::new();
let s = "init".to_string();
let s = String::from("init");

追記

let mut s = String::new();
s.push('A');
s.push_str("BC");

 mutStringであるべき。

結合

+演算子

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;
  • s1の所有権がムーブされる(以降、使えない)

 理由は以下参照。一言でいうと、s1の所有権は+演算子の実体fn add(self, s: &str) -> String {selfにムーブする。

 また、直感的でない表記である。

  • 第一引数は&がなく、以降は&が必要

 上記2点から、+演算子による結合は使いにくい。

format!マクロ

let s1 = String::from("A");
let s2 = String::from("B");
let s3 = String::from("C");
let s = format!("{}-{}-{}", s1, s2, s3);

 所有権を奪わない。冗長だが、これが最善か。

走査

文字(char)

    let hello = "Здравствуйте";
    for c in hello.chars() {
        println!("{}", c);
    }

バイト

    // str.bytes()を使えばバイト単位(u8型)で走査できる
    let hello = "Здравствуйте";
    for c in hello.bytes() {
        println!("{}", c);
    }

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで