我正在使用扫描仪(如果您愿意,还可以使用标记器或词法分析器)。我必须遍历一个字符串切片。我找到了两种方法来完成这项工作:
首先,我可以创建一个迭代器并遍历每个字符。这是一个简化的例子:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["myCNN"].ConnectionString))
{
using (var cmd = new SqlCommand("dbo.myStoredProcedure", connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@PatientId", SqlDbType.VarChar, 40).Value = number;
cmd.Parameters.Add("@NickName", SqlDbType.VarChar, 20).Value = "stlukeshs";
var reader = cmd.ExecuteReader();
while(reader.Read())
{
//Do Stuff..
}
//closer reader
reader.Close();
}
}
但是,如果我想展望未来,那就不那么简单了:
let s = "чеllo".chars();
for c in s {
println!("{}", c);
}
不幸的是,如果我想要查看下一个下一个字符,我似乎无法多次查看。
所以我可以使用第二个方法。我可以将字符串切换转换为字符向量。例如:
let mut s = "чеllo = ==".chars().peekable();
loop {
match (s.next(), s.peek()) {
(Some('='), Some(&'=')) => { s.next(); println!("==") },
(Some('='), _ ) => println!("="),
(Some(c) , _ ) => println!("{}", c),
(None, _) => break,
}
}
我现在要尝试的是第三种方法,它们在两者之间有点交叉。基本上,我想要的是Rust之前拥有的char_at方法,我希望能够获得字形集群的大小。
如果我有这两个功能,我可以使用类似于我的矢量字符方法的方法,但我可以直接在字符串切片上这样做。这样的事情(这不是有效的Rust代码):
fn char_at(text: &Vec<char>, pos: usize) -> Option<char> {
if pos < text.len() {
Some(text[pos])
} else {
None
}
}
let mut text = "чеllo = ==".chars().collect();
let mut position: usize = 0;
loop {
match (char_at(&text, position), char_at(&text, position + 1)) {
(Some('='), Some('=')) => { position += 1; println!("==") },
(Some('='), _ ) => println!("="),
(Some(c) , _ ) => println!("{}", c),
(None , _ ) => break,
}
position += 1;
}
注意:我想要的是let mut text = "чеllo = ==";
let mut position: usize = 0;
loop {
let next_char = text.char_at(position);
let peek_char = text.char_at(position + next_char.len());
match (next_char, peek_char)) {
(Some('='), Some('=')) => {
position += peek_char.len();
println!("==")
},
(Some('='), _ ) => println!("="),
(Some(c) , _ ) => println!("{}", c),
(None , _ ) => break,
}
position += next_char.len();
}
和next_char.len()
为我提供这些字素所包含的字节数。
以下是我对上述方法的理解:
我是Rust的新手。所以这些是我的问题:
答案 0 :(得分:3)
str::chars()
返回的迭代器({3}}类型实现Clone
。这意味着您可以创建一个与现有迭代器具有相同状态的迭代器,但然后通过在迭代器上调用.clone()
来独立迭代。您可以使用克隆进行前瞻,只有在准备好进展时才能使原始迭代器前进。
str::Chars
简单地包裹iter::Slice<u8>
,它本身只是一对指针。因此,克隆str::Chars
只是将这两个指针复制到一个新值中,这不涉及任何内存分配。这使得克隆str::Chars
非常便宜,所以不要害羞!
fn main() {
let mut s = "чеllo = ==".chars();
loop {
let mut s2 = s.clone();
let c1 = s2.next();
let c2 = s2.next();
match (c1, c2) {
(Some('='), Some('=')) => { s.next(); println!("=="); }
(Some('='), _ ) => { s.next(); println!("="); }
(Some(c) , _ ) => { s.next(); println!("{}", c); }
(None, _) => break,
}
}
}