字符串操作

fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }

    s.len()
}

Because we need to go through the String element by element and check whether a value is a space, we’ll convert our String to an array of bytes using the as_bytes method

 For now, know that iter is a method that returns each element in a collection and that enumerate wraps the result of iter and returns each element as part of a tuple instead. The first element of the tuple returned from enumerate is the index, and the second element is a reference to the element. This is a bit more convenient than calculating the index ourselves.

Because the enumerate method returns a tuple, we can use patterns to destructure that tuple, just like everywhere else in Rust. So in the for loop, we specify a pattern that has i for the index in the tuple and &item for the single byte in the tuple. Because we get a reference to the element from .iter().enumerate(), we use & in the pattern.

Inside the for loop, we search for the byte that represents the space by using the byte literal syntax. If we find a space, we return the position. Otherwise, we return the length of the string by using s.len()

fn main() {
    let mut s = String::from("hello world");

    let _word = first_word(&s); // word will get the value 5

    println!("{},{}",s,_word);
    s.clear(); // this empties the String, making it equal to ""

    // word still has the value 5 here, but there's no more string that
    // we could meaningfully use the value 5 with. word is now totally invalid!
}


fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }

    s.len()
}

 

字符串切片

str[index..end_position]

index:字符索引位置,从0开始

end_position:字符位置,从1开始

let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6..11];

2.6 Rust Slice Type

 

With Rust’s .. range syntax, if you want to start at the first index (zero), you can drop the value before the two periods. In other words, these are equal:

let s = String::from("hello");

let slice = &s[0..2];
let slice = &s[..2];

By the same token, if your slice includes the last byte of the String, you can drop the trailing number. That means these are equal:

let s = String::from("hello");

let len = s.len();

let slice = &s[3..len];
let slice = &s[3..];

You can also drop both values to take a slice of the entire string. So these are equal:

let s = String::from("hello");

let len = s.len();

let slice = &s[0..len];
let slice = &s[..];

Note: String slice range indices must occur at valid UTF-8 character boundaries. If you attempt to create a string slice in the middle of a multibyte character, your program will exit with an error.

 切片字符串操作

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

第一种方式为直接对字符串本身进行操作,没有第二个变量产生,切片则是新定义了一个变量,指向了原字符串的部分内容。当作用域发生变化时,它们的不同就会显现出来。

 下面这一段代码是正确的

fn main() {
    let mut s = String::from("hello world");

    let word = first_word(&s);

    s.clear(); // error!

    println!("the first word is: {}", word);
}

fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }

    s.len()
}

 

下面的代码是错误的

2.6 Rust Slice Type

 

下面test_s2方法是错误的,原因在于first_word2方法返回的是可变字符串s的一个切片,切片是什么?

切片只是原始字符串的一个局部引用,没有ownership,本身也不存储数据,只有一个指针和要读取字符长度

在这个方法,s.clear()方法清空了原始字符串,然后又使用了word,此时rust就认为这种做法破坏了切片word的原本的内容,将这种做法定义为error

 

pub fn test_s2(){
    let mut s = String::from("hello world");

    let word = first_word2(&s);

    s.clear(); // error!

    println!("the first word is: {}", word);

}



fn first_word2(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[..i];
        }
    }
    &s[..]
}

 

下面的代码是正确的,只需要更换一下对切片使用的位置

pub fn test_s2(){
    let mut s = String::from("hello world");

    let word = first_word2(&s);
    println!("the first word is: {}", word);
    s.clear(); // error!
}


fn first_word2(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[..i];
        }
    }
    &s[..]
}

 

相关文章: