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

15

我正在使用Rust完成2020年的编程挑战日历第3天,以便进行一些训练,因为我是Rust的新手,我的代码是否能够编译取决于我在“tree”变量上使用单引号还是双引号。

第一段代码片段将无法编译,并显示错误:expected u8, found &[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);
}

第二个片段编译并给出了正确的答案。

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);
}

我没有找到任何解释单引号或双引号用法的资料..有人可以帮忙吗?


2
请参见 https://doc.rust-lang.org/1.30.0/book/2018-edition/ch03-02-data-types.html#the-character-type:*`char` 字面量使用单引号指定,而字符串字面量则使用双引号。* - jub0bs
1个回答

23

简短回答是它的工作方式类似于Java。单引号用于表示字符,双引号用于表示字符串。

let a: char = 'k';
let b: &'static str = "k";

b'' 或者 b"" 前缀意味着将此处内容解释为字节文字。

let a: u8 = b'k';
let b: &'static [u8; 1] = b"k";

字符串结果是引用的原因是由于它们在编译二进制文件中的存储方式。在每个方法内部存储一个字符串常量太低效了,所以字符串被放置在二进制文件开头的头部区域中。当您的程序正在执行时,您正在获取该头部中字节的引用(因此具有静态生命周期)。

更深入地探索,单引号技术上持有一个码点。这本质上就是您可能认为的一个字符。因此,即使它可能由多个字节组成,Unicode 字符也将被视为单个码点。假定一个码点适合 u32 或更少,因此您可以使用 as u32 安全地转换任何 char,但反之则不行,因为并非所有 u32 值都与有效的码点匹配。这也意味着 b'\u{x}' 不是有效的,因为 \u{x} 可能产生不适合单个字节的字符。

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

然而,你可能会发现有趣的是,由于 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]);

3
“工作方式类似于Java”或C、C ++、C#、D、Go等。 - mcarton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接