rust - 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);
}
第二个片段编译并给出正确的答案..
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);
}
我没有找到任何参考来解释使用单引号或双引号时发生了什么……有人可以帮助我吗?
解决方案
简短的回答是它的工作方式类似于 java。字符的单引号和字符串的双引号。
let a: char = 'k';
let b: &'static str = "k";
b''
or前缀意味着取我在这里的b""
内容并解释为字节文字。
let a: u8 = b'k';
let b: &'static [u8; 1] = b"k";
字符串导致引用的原因是它们在编译后的二进制文件中的存储方式。在每个方法中存储一个字符串常量效率太低了,所以字符串被放在标题区域的二进制文件的开头。当您的程序正在执行时,您将引用该标头中的字节(因此是静态生命周期)。
进一步深入兔子洞,单引号在技术上包含一个代码点。这基本上就是你可能认为的角色。因此,Unicode 字符也将被视为单个代码点,即使它可能是多个字节长。假定代码点适合 au32
或更少,因此您可以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);
但是,您可能会发现有趣的是,由于 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]);
推荐阅读
- go - 需要一个例子来说明赋值运算符的 Go 语法如何使用使用 EBNF 指定的语法规则
- java - 无法运行颤振医生--android-licenses
- intellij-idea - 我可以在不运行程序的情况下在 IntellIJ 中显示环境变量吗?
- c - 在 C 中加载不正确
- spring - 带有 Eclipselink 保存操作的 Spring JPA 不会持续存在
- metal - sample() 是否总是在 Metal Shading Language 中以 RGBA 格式返回 float4?
- flutter - 颤振 setState 未定义
- flutter - 有谁知道如何在没有页眉或页脚的情况下加载 webview 颤振?
- c - 为什么 Apple Clang 会在 -O1/2/3 下留下多余的堆栈推送弹出指令?
- java - Gradle 无法正确识别 mainModule