Rust 中双引号和单引号的区别

Mle*_*vil 1 rust

我正在 Rust 中进行 2020 年第 3 天的 adventofcode 训练,因为我是 Rust 的新手,我的代码无法编译,这取决于我在“树”变量上使用单引号还是双引号

第一个代码片段不会编译并抛出错误:预期u8,找到&[u8; 1]

use std::fs;

fn main() {
    let text: String = fs::read_to_string("./data/text").unwrap();
    let vec: Vec<&str> = text.lines().collect();
    let vec_vertical_len = vec.len();
    let vec_horizontal_len = vec[0].len();

    let mut i_pointer: usize = 0;
    let mut j_pointer: usize = 0;
    let mut tree_counter: usize = 0;

    let tree = b"#";
    loop {
        i_pointer += 3;
        j_pointer += 1;
        if j_pointer >= vec_vertical_len {
            break;
        }

        let i_index = i_pointer % vec_horizontal_len;
        let character = vec[j_pointer].as_bytes()[i_index];
        if character == tree {
           tree_counter += 1
        }
    }

    println!("{}", tree_counter);
}
Run Code Online (Sandbox Code Playgroud)

第二个片段编译并给出正确答案..

use std::fs;

fn main() {
    let text: String = fs::read_to_string("./data/text").unwrap();
    let vec: Vec<&str> = text.lines().collect();
    let vec_vertical_len = vec.len();
    let vec_horizontal_len = vec[0].len();

    let mut i_pointer: usize = 0;
    let mut j_pointer: usize = 0;
    let mut tree_counter: usize = 0;

    let tree = b'#';
    loop {
        i_pointer += 3;
        j_pointer += 1;
        if j_pointer >= vec_vertical_len {
            break;
        }

        let i_index = i_pointer % vec_horizontal_len;
        let character = vec[j_pointer].as_bytes()[i_index];
        if character == tree {
           tree_counter += 1
        }
    }

    println!("{}", tree_counter);
}
Run Code Online (Sandbox Code Playgroud)

我没有找到任何参考资料来解释使用单引号或双引号时发生了什么。有人可以帮助我吗?

Loc*_*cke 6

简短的回答是它的工作原理类似于 java。字符的单引号和字符串的双引号。

let a: char = 'k';
let b: &'static str = "k";
Run Code Online (Sandbox Code Playgroud)

b''b""前缀手段采取什么我这里并解释为字节的文字来代替。

let a: u8 = b'k';
let b: &'static [u8; 1] = b"k";
Run Code Online (Sandbox Code Playgroud)

字符串导致引用的原因是它们在编译后的二进制文件中的存储方式。在每个方法中存储一个字符串常量会太低效,因此字符串被放在头区域中二进制文件的开头。当您的程序正在执行时,您正在引用该标头中的字节(因此是静态生命周期)。

更进一步,单引号在技术上包含一个代码点。这基本上就是您可能认为的角色。因此 Unicode 字符也将被视为单个代码点,即使它可能是多个字节长。代码点被假定为配合到u32或更少,因此您可以放心地将任何char使用as u32,而不是周围的其他方法,因为不是所有的u32值将匹配有效码点。这也意味着b'\u{x}'无效,因为\u{x}可能会产生不适合单个字节的字符。

// U+1F600 is a unicode smiley face
let a: char = '\u{1F600}';
assert_eq!(a as u32, 0x1F600);
Run Code Online (Sandbox Code Playgroud)

但是,您可能会发现有趣的是,由于 Rust 字符串存储为 UTF-8,超过 127 的代码点将占用字符串中的多个字节,尽管它们自己适合单个字节。您可能已经知道,UTF-8 只是一种将代码点转换为字节然后再返回的方法。

let foo: &'static str = "\u{1F600}";
let foo_chars: Vec<char> = foo.chars().collect();
let foo_bytes: Vec<u8> = foo.bytes().collect();
    
assert_eq!(foo_chars.len(), 1);
assert_eq!(foo_bytes.len(), 4);

assert_eq!(foo_chars[0] as u32, 0x1F600);
assert_eq!(foo_bytes, vec![240, 159, 152, 128]);
Run Code Online (Sandbox Code Playgroud)

  • “与 java 的工作方式类似”或 C、C++、C#、D、Go 或…… (2认同)