ピットガイドへの錆:行時に行

長い時間のための錆のピットを掘っはピットの列の一部を掘るために、今日、問題ではありませんでした。はい、それは、コレクション・データ型のいくつかのタイプを導入することです。「行時に行」このタイトルは非常に文化を思えませんか?

ピットガイドへの錆:一般ルーチンの記事で私たちは、基本データ型をいくつか紹介してきた、と彼らはスタック上に保存されている、と今日はデータ型の三種類に焦点を当て:文字列、ベクトルおよびハッシュマップ。

我々は以前の研究ではより多くの接点を持っていますが、詳細に記載されていないことを文字列型。一部の学生は、String型の基礎をプログラムしている可能性のあるすべての後に、すべてのプログラミング言語で最も一般的なタイプであり、我々は非常に精通していると言うことができる、学ぶためにわざわざ。学生のこの考え方については、私は彼らに言いたい:私はそう思い始めた、私は彼の頭のコンパイラパッケージでヒットされるまで、人々は戻って真剣にくる文字列を入力するもの勉強して決定しました。

錆の文字列は、次のタイプに分け:

  • STR:固定された長さを表す文字列
  • 文字列:可変長を表す文字列
  • CStr関数:さび列借りCで表される分布は、一般的にC言語と対話するために使用します
  • CSTRING:錆やC言語の文字列に分配パスによって表すことができます。
  • OsStr:主にWindowsとの互換性のためのシステムを表現し、操作する文字列、
  • OSString:OsStrの変数バージョン
  • パスは:パスを示します
  • PathBuf:パスの変数バージョン

彼らは最も一般的な開発プロセスであるが、より多くの混乱ので、この記事では、最初の二つに焦点を当てています。strのために、それは私たちの共通の参照型です&strあなたが読めばピットガイドに錆を:コアコンセプト後者の記事を、私はあなたが参照型と所有権の概念を理解するために持っていると信じています。その文字列の種類と所有権&strがされていません。

サビでは、文字列の性質がVecを<U8>で、Vecとはベクトルのキーワードのセットで、我々は後で紹介します。すなわち、3つの部分からなる文字列型:バイトのスタック内のバイトの配列を指すポインタ、スタック、記録容量の長さの配列は、ヒープを割り当てられました。おそらく、あなたは非常に深くコードの一部を通じて理解します。

fn main() {
    let mut a = String::from("foo");
    println!("{:p}", a.as_ptr());
    println!("{:p}", &a);
    assert_eq!(a.len(), 3);
    a.reserve(10);
    assert_eq!(a.capacity(), 13);
}
复制代码

このコードでは、我々は()と同じではないポインタとポインタ&GETを得ることがa.as_ptr、見ることができます。

rust06-1

ここでは、取得したアドレスポインタas_ptr、説明スタック内のポインタ・バイト配列であり、そのアドレスは、スタック上の文字列変数ポインタアドレスであると。さらに、数は方法ではなく、文字の数で得られたバイトの長さlen()と容量()です。ここでは、中国語の文字の長さに手を試すことができます。

文字列の基本的な概念上の話をした後、私はあなたがすでに錆の文字列の一般的な理解を持っていると信じています。次に、我々は、CRUDメソッド文字列、それを見てみましょう。

文字列を作成します

ADOは、のはあなたの文字列を作成するためのさまざまな方法を示してみましょう。

fn main() {
    let string: String = String::new();
    let string: String = String::from("hello rust");
    let string: String = String::with_capacity(10);
    let str: &'static str = "Jackey";
    let string: String = str.to_owned();
    let string: String = str.to_string();
}
复制代码

より一般的に使用されるここでは、後に見て、いくつかの方法があり、最初の二つです。with_capacity()は空の文字列パラメータを作成ヒープに割り当てられたバイト数を示します。to_ownedとto_stringには、文字列に&strのタイプを変換する方法を実証することです。

文字列を変更します

文字列が更新等二つの文字列、文字列を連結する、追加された後、多くの従来の方法は、例えば、ある文字列を変更しさび。次のコードは、文字列を変更するいくつかの方法が表示されます。

fn main() {
    let mut hello = String::from("Hello, ");
    hello.push('J');    // 追加单个字符
    hello.push_str("ackey! ");    //追加字符串
    println!("push: {}", hello);

    hello.extend(['M', 'y', ' '].iter());   //追加多个字符,参数为迭代器
    hello.extend("name".chars());
    println!("extend: {}", hello);

    hello.insert(0, 'h');   //类似于push,可以指定插入的位置
    hello.insert(1, 'a');
    hello.insert(2, '!');
    hello.insert_str(0, "Haha");
    println!("insert: {}", hello);

    let left = "Hello, ".to_string();
    let right = "World".to_string();
    let result = left + &right;
    println!("+: {}", result);   //使用+连接字符串时,第二个必须为引用
    let mut message = "rust".to_string();   //使用+=连接字符串时,字符串必须定义为可变
    message += "!";
    println!("+=: {}", message);

    let s = String::from("foobar");
    let s: String = s
        .chars()
        .enumerate()
        .map(|(_i, c)| {c.to_uppercase().to_string()})
        .collect();
    println!("update chars: {}", s);
  
    let s1 = String::from("hello");
    let s2 = String::from("rust");
    let s3 = format!("{}-{}", s1, s2);
    println!("format: {}", s3);
}
复制代码

私たちは、上記のコードのためにいくつかの追加の説明をしました。

プッシュして受信したパラメータ_STR方法で、同じように挿入は文字列である、または単一の文字のみを受け取ります。インサートは、指定された位置に挿入することができ、および文字列のみの挿入端部を押すことができます。

「+」接続文字列、String型の最初の引数、あなたが参照型&STRする必要が秒を使用しました。これは、私たちがこのように定義されたaddメソッド、呼んでいるものに似ています。

fn add(self, s: &str) -> String {
复制代码

したがって、最初のパラメータの所有権は、関数に移し、そして戻り結果を通って通過します。つまり、+演算子を使用した後、leftのない所有権を持っていません。

文字列検索

サビでは、文字列は、指定された文字の位置に応じて取得することはできません。次のコードはコンパイルされているが、。

let s1 = String::from("hello");
let h = s1[0];
复制代码

錆は、この手段最初のバイトが0である、とあなたは、単にする場合は、文字の錆の文字列は、だから、(私はあなたが中国語の文字コードで実験できるようになる以前に覚えていますか?)バイト以上を占めることができることと思うだろう、のでバイトを取得するには、コンパイラはあなたが本当に対応するバイト値を取得するために、またはその文字を取得したいということを知りません。

文字列を処理する場合、通常、弊社では以下のメソッドがあります:

fn main() {
    let hello = "Здравствуйте";
    let s = &hello[0..4];
    println!("{}", s);

    let chars = hello.chars();
    for c in chars {
        println!("{}", c);
    }

    let bytes = hello.bytes();
    for byte in bytes {
        println!("{}", byte);
    }

    let get = hello.get(0..1);
    let mut s = String::from("hello");
    let get_mut = s.get_mut(3..5);

    let message = String::from("hello-world");
    let (left, right) = message.split_at(6);
    println!("left: {}, right: {}", left, right);
}
复制代码

通常、文字スライスを使用して、あなたはイテレータが、その後、各文字のために別々に処理することができます方法の文字の文字を使用して得ることができます。また、取得またはget_mut方法はまた、インデックスの範囲を受け取るスライス指定された文字列を返すことができます。指定されたインデックスのリターンは完全な文字を返すことができない場合は、錆はNoneを返しますので、結果は、オプションのタイプです。Is_char_boundary方法は、境界の位置が不正であるかどうかを決定するためにここで使用することができます。

最後に、split_at_mutのsplit_atまたは文字列を分割する方法を使用することも可能です。これは、分割位置は、ちょうど文字境界位置である必要があり、そうでなければ、プログラムがクラッシュします。

削除文字列

錆標準ライブラリは、文字列を削除するには、いくつかの方法を提供し、我々はそれらのいくつかを証明する必要があります。

fn main() {
    let mut hello = String::from("hello");
    hello.remove(3);
    println!("remove: {}", hello);
    hello.pop();
    println!("pop: {}", hello);
    hello.truncate(1);
    println!("truncate: {}", hello);
    hello.clear();
    println!("clear: {}", hello);
}
复制代码

結果が示されています。

rust06-2

それは、文字の開始位置でない場合は、クラッシュの原因となります、文字の受信パラメータの開始位置である文字列を、削除する方法を削除します。

この方法は、文字列のポップ終わりをポップアップ表示されます、サイズが指定されている撮影したTRUNCATE、この方法は、明確な空の文字列に使用されています。

したがって、我々は以上導入した文字列の基本的な概念とCRUD錆は、その後、我々はタイプベクターの別のセットを見ていきます。

ベクター

ベクターは、データ型の同じデータ型の複数のデータを格納するために使用されます。それはキーワードですVec<T>ここでは、それCRUDベクトルを見てみましょう。

作成ベクトル

fn main() {
    let v1: Vec<i32> = Vec::new();
    let v2 = vec![1, 2, 3];
}
复制代码

上記第一、2つの方法でコードベクトルの生成を実証ない追加の要素、明示的に記憶素子を指定する種類ため、新しい空のベクターを作成するための機能です。第二は、私たちが直接VECを使用し、初期値のベクトルの集合を作成することです!マクロ、その後、コンパイラは自分自身を推測することができるので、あなたは、ベクトル内のデータ要素の型を指定する必要はありません、初期値を指定します。

更新ベクトル

fn main() {
    let mut v = Vec::new();
    v.push(1);
    v.push(2);
}
复制代码

我々は要素を追加したい場合は、空のベクターを作成した後、あなたは最後までダイレクトプッシュ方式、付加的な要素を使用することができます。

削除ベクトル

fn main() {
    let mut v = Vec::new();
    v.push(1);
    v.push(2);
    v.push(3);

    v.pop();
    for i in &v {
        println!("{}", i);
    }
}
复制代码

単一の要素を削除するだけで、その所有権などの他の構造が失敗したように、全体のベクトルを削除するには、ポップの方法を使用することができるが。

読むのベクトル要素

fn main() {
    let v = vec![1, 2, 3, 4, 5];

    let third: &i32 = &v[2];
    println!("The third element is {}", third);

    match v.get(2) {
        Some(third) => println!("The third element is {}", third),
        None => println!("There is no third element."),
    }

    let v = vec![100, 32, 57];
    for i in &v {
        println!("{}", i);
    }
}
复制代码

あなたは、単一の指定された要素を読み取る必要がある場合には、二つの方法があります使用することができる、1が使用され[]、別の方法は、getを使用することです。これは、2つの方法の違いです:最初のタイプは、リターン要素であり、リターン・オプションの種類を取得します。あなたが範囲外の場所を指定した場合、最初のメソッドを使用するプログラムは、第2の方法は、Noneを返します使用して、直接、クラッシュします。

さらに、要素は、ベクトル形式をトラバースすることによって読み取ることができます。あなたはさまざまな種類のデータを保存したい場合は、我々は、列挙型を使用することができます。

fn main() {
    enum SpreadsheetCell {
        Int(i32),
        Float(f64),
        Text(String),
    }

    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
}
复制代码

HashMapの

KVのHashMap格納されたデータ構造は、各キー値の各々は、同じタイプである必要があり、同じ型でなければなりません。HashMapのは、最小限のコレクションの3種類がありますので、その前に、使用することを、手動導入は来る必要です

use std::collections::HashMap;
复制代码

HashMapを作成します。

まず、新しいハッシュマップを作成し、要素を追加する方法で見てみましょう。

use std::collections::HashMap;
fn main() {
    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    map.insert(field_name, field_value);
}
复制代码

insertメソッドを使用して、する場合がありますfield_nameし、field_value所有権を失うことになります。あなたがそれらを使用する前に、どのようにそれを行うには?私たちは、ハッシュマップからやり直すことができます。

アクセスハッシュマップデータ

use std::collections::HashMap;
fn main() {
    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    map.insert(field_name, field_value);

    let favorite = String::from("Favorite color");
    let color = map.get(&favorite);
    match color {
        Some(x) => println!("{}", x),
        None => println!("None"),
    }
}
复制代码

私たちは、私たちが指定したキーの値を取得するために使用を得ることができることを見ることができる値を指定しない場合はメソッドが返すオプションの種類を取得し、Noneを返します。また、あなたはハッシュ地図を反復するforループを使用することができます。

use std::collections::HashMap;
fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }
}
复制代码

アップデートハッシュ地図

私たちは同じキーの挿入を重視する場合、古い値が上書きされます。あなたが存在しないキーに挿入したい場合は、エントリを使用することができます。

use std::collections::HashMap;
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);

    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

    println!("{:?}", scores);
}
复制代码

概要

今日は、みんなで、一緒に3つのピット、文字列、ベクトルやハッシュマップを掘った各データ型CRUDを導入しました。それは、最も一般的なデータ型のいずれかであるため、文字列への導入は、比較的大きなスペースを占めています。もちろんたくさんのこの部分の、知識、と私は交流を学んであなたを歓迎します。

おすすめ

転載: juejin.im/post/5de52a36e51d452515148067