2016-07-22 3 views
0

なぜs [n]が文字列である場合に文字列のn letter文字を見つけるために文字列を移動する必要がありますか? (https://doc.rust-lang.org/book/strings.htmlによる)[]文字列の演算子、ベクトルのスライスとのリンク

私が理解したところから、文字列はcharの配列であり、charは4バイトまたは4バイトの配列です。だから、n番目の文字がこれをするのと同じようになるでしょう:v [4 * n。4 * n + 4]ここで、vはベクトルですか?

v [i..j]のコストはいくらですか?

私はVのコストは[i..j]寺であり、Sのコスト[n]は4

+0

を錆が人より優れたプログラマーを作る方法をちょうど別の例。私はちょうどdownvotesを理解していない。正当な疑問とよくある誤解です。 –

+0

この質問は、「Rust []演算子は文字列でどうやって動作するのですか」から「Rust文字列がどのようにスライスされ、文字がどのようにインデックス付けされるのか」という言い回しを少し変更しても問題ありません。また、与えられたリンクと矛盾し、ダウンボントを容易に引きつけるいくつかのステートメントがあります。 –

+0

@ dpc.pw多分、ここで多くの質問がありますので、OPが少し難しく検索したり、質問をする前に取り入れる努力の量を見せている場合は、これについて説明しています。 – Shepmaster

答えて

4

する必要がありますので、私はでルーストに文字列に関するこれらの誤解を明確にしようとすることを前提としています本からの引用(https://doc.rust-lang.org/book/strings.html)。それらは、&str又はStringされる文字の配列でないかどうか

A ‘string’ is a sequence of Unicode scalar values encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid encoding of UTF-8 sequences.

これを考慮して

、プラスそのUTF-8コード・ポイントは、可変(文字に依存して1〜4バイト)のサイズである、さび内のすべての文字列、 、そのように扱うことはできません。理論的には、これは私たちが一定時間内のn番目のバイトを取得することを可能にするだろうが、そのバイトは保証されませんので、ご質問で述べたものとは異なり

Because strings are valid UTF-8, they do not support indexing:

let s = "hello"; 

println!("The first letter of s is {}", s[0]); // ERROR!!! 

Usually, access to a vector with [] is very fast. But, because each character in a UTF-8 encoded string can be multiple bytes, you have to walk over the string to find the nᵗʰ letter of a string. This is a significantly more expensive operation, and we don’t want to be misleading.

を、1はs[n]を行うことはできません:それは、さらに、なぜスライスに説明しますそれ自身で何らかの意味をなす。

v [i..j]のコストはいくらですか?

それはバイトレベルで行われるので、スライスのコストは、実際には一定である:

You can get a slice of a string with slicing syntax:

let dog = "hachiko"; 
let hachi = &dog[0..5]; 

But note that these are byte offsets, not character offsets. So this will fail at runtime:

let dog = "忠犬ハチ公"; 
let hachi = &dog[0..2]; 

with this error:

thread '' panicked at 'index 0 and/or 2 in 忠犬ハチ公 do not lie on character boundary'

は基本的には、スライスが許容され、その文字列の新しいビューが得られますので、何のコピーは行われません。ただし、オフセットが文字境界の点で正しいことが完全にわかっている場合にのみ使用してください。

文字列の各文字を反復するためには、あなたの代わりにchars()を呼び出すことができます:

let c = s.chars().nth(n); 

でもこのことを念頭に置いて、あなたがしたい場合はUnicode文字を処理することは正確に何をしたいではないかもしれないことに注意してくださいキャラクタモディファイアをUTF-8で扱います(スカラー値は単独で扱うべきではありません)。 str API今から引用:あなたがされていない(コードポイントの配列として文字列を扱いたいならば

extern crate unicode_segmentation; 

use unicode_segmentation::UnicodeSegmentation; 

let s = "a̐éö̲\r\n"; 
let g = UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>(); 
let b: &[_] = &["a̐", "é", "ö̲", "\r\n"]; 
assert_eq!(g, b); 
+0

ああ、私は理解しました:各文字はC++のchar(1バイト)またはUnicode文字(4バイト)のどちらでもかまいませんので、文字列は配列にできません。だからそれはシーケンス(リンクされたリスト?)です。 str.chars()もシーケンスですが、str.bytes()は配列です。文字列を配列として使用する場合、UTF-8配列を使用できますか? – x4rkz

+3

UTF-8は、Unicodeコードポイントをバイト単位で可変長符号化したものです。各コードポイントは、1,2,3、または4バイトになります。 ASCII文字(主に英語で使用される)は1バイト(ASCIIと同じ値)になります。 –

+0

マイナーニックピック:ユニコードスカラー値は、数値であるだけでなく、コンピュータに定義された表現を持たないため、可変サイズにすることはできません。 UTF-8 *コードポイント*は可変サイズで、各コードポイントは1つのUnicodeスカラー値をエンコードします。例えば、 'char'はUTF-32コードポイントであり、固定サイズですが、Unicodeのスカラ値を1つもエンコードしません。 –

2

fn chars(&self) -> Chars

Returns an iterator over the chars of a string slice.

As a string slice consists of valid UTF-8, we can iterate through a string slice by char. This method returns such an iterator.

It's important to remember that char represents a Unicode Scalar Value, and may not match your idea of what a 'character' is. Iteration over grapheme clusters may be what you actually want.

Remember, chars may not match your human intuition about characters:

let y = "y̆"; 

let mut chars = y.chars(); 

assert_eq!(Some('y'), chars.next()); // not 'y̆' 
assert_eq!(Some('\u{0306}'), chars.next()); 
assert_eq!(None, chars.next()); 

unicode_segmentationクレートは書記素クラスタ境界を定義するための手段を提供します文字と厳密に同じ;結合マーク、別のスキントーン修飾子を持つ絵文字など)、あなたはVecにそれを収集することができます。

fn main() { 
    let s = "£10 !"; 
    for (i,c) in s.char_indices() { 
     println!("{} {}", i, c); 
    } 
    let v: Vec<char> = s.chars().collect(); 
    println!("v[5] = {}", v[5]); 
} 

Play link

いくつかの様々な文字幅のボーナスデモで、これは出力:

0 £ 
2 1 
3 0 
4 
5 
9 ! 
v[5] = ! 
+0

それは確かに一つの可能​​性です。私は 'chars()'に言及することを選択しました。なぜなら、それは怠惰でメモリの効率が高いからです。 :) –

+0

合意しました!時にはO(1)索引付け、他の時(たぶんほとんどの場合) 'chars()'または 'char_indices()'が正しいとすると便利です。 –

+0

ありがとうございます。 charは4バイトの錆です。だから、私は拡張ASCII文字だけを使用している場合、私はバイトのテーブル(とC++ charctersのテーブル)を取得するためにバイト()を使用することができますか? – x4rkz

関連する問題