Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 为什么将字符串的第一个字母大写会如此复杂?_String_Rust_Uppercase - Fatal编程技术网

String 为什么将字符串的第一个字母大写会如此复杂?

String 为什么将字符串的第一个字母大写会如此复杂?,string,rust,uppercase,String,Rust,Uppercase,我想把a&str的第一个字母大写。这是一个简单的问题,我希望有一个简单的解决办法。直觉告诉我这样做: let mut s = "foobar"; s[0] = s[0].to_uppercase(); 但是&strs不能像这样被索引。我唯一能做到这一点的方法似乎过于复杂。我将&str转换为迭代器,将迭代器转换为向量,向量中的第一项大写,这将创建一个迭代器,我将其索引,创建一个选项,我将其展开以给出大写的第一个字母。然后我把向量转换成迭代器,我把它转换成一个字符串,我把它转换成&str let

我想把a
&str
的第一个字母大写。这是一个简单的问题,我希望有一个简单的解决办法。直觉告诉我这样做:

let mut s = "foobar";
s[0] = s[0].to_uppercase();
但是
&str
s不能像这样被索引。我唯一能做到这一点的方法似乎过于复杂。我将
&str
转换为迭代器,将迭代器转换为向量,向量中的第一项大写,这将创建一个迭代器,我将其索引,创建一个
选项
,我将其展开以给出大写的第一个字母。然后我把向量转换成迭代器,我把它转换成一个
字符串,我把它转换成
&str

let s1 = "foobar";
let mut v: Vec<char> = s1.chars().collect();
v[0] = v[0].to_uppercase().nth(0).unwrap();
let s2: String = v.into_iter().collect();
let s3 = &s2;
let s1=“foobar”;
让mut v:Vec=s1.chars().collect();
v[0]=v[0]。to_大写();
设s2:String=v.into_iter().collect();
设s3=&s2;
有比这更简单的方法吗?如果有,是什么?如果不是,为什么防锈设计是这样的

为什么这么复杂? 让我们一行一行地把它分解

let s1 = "foobar";
我们已经创建了一个编码为的文本字符串。UTF-8允许我们以一种非常紧凑的方式对的1114112进行编码,如果您来自世界上的一个地区,输入的字符主要是1963年创建的标准中的字符。UTF-8是一种可变长度编码,这意味着单个代码点可能会发生变化。较短的编码是为ASCII保留的,但是

这将获取第一个代码点并请求将其转换为大写变量。不幸的是,对于我们这些从小说英语的人来说,这是一个错误。旁注:我们称之为大写和小写

当代码点没有相应的大写变量时,此代码将死机。实际上,我不确定这些是否存在。当一个代码点有一个包含多个字符的大写变体(如德语
ß
)时,它也可能在语义上失败。请注意,在现实世界中,ß可能永远不会大写,这正是我可以始终记住并搜索的示例。事实上,截至2017年6月29日,德语拼写的官方规则已经更新,因此

在这里,我们将字符转换回UTF-8,并需要新的分配来存储它们,因为原始变量存储在常量内存中,以便在运行时不占用内存

let s3 = &s2;
现在我们引用这个
字符串

这是一个简单的问题

不幸的是,事实并非如此。也许我们应该努力使世界转变为

我认为
char::to_大写
已经正确地处理了Unicode

是的,我当然希望如此。不幸的是,Unicode在所有情况下都是不够的。 多亏了,大写(İ)和小写(i)版本都有一个点。也就是说,字母
i
没有一个适当的大写字母;这也取决于源文本的格式

为什么需要所有数据类型转换

因为当您担心正确性和性能时,使用的数据类型非常重要。字符为32位,字符串为UTF-8编码。它们是不同的东西

索引可以返回多字节的Unicode字符

这里可能有一些不匹配的术语。
char
是多字节Unicode字符

如果逐字节执行,则可以对字符串进行切片,但如果不在字符边界上,则标准库将死机

为字符串建立索引以获取字符从未实现的原因之一是,许多人将字符串误用为ASCII字符数组。为字符串编制索引以设置字符永远不会有效率-您必须能够将1-4字节替换为1-4字节的值,从而导致字符串的其余部分大量跳转

to_uppercase
可能返回大写字符

如上所述,
ß
是一个单独的字符,当大写时,会变成两个字符

解决 另请参见哪些仅使用大写ASCII字符

起初的 如果我必须写代码,它看起来会像:

fn some_kind_of_uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().chain(c).collect(),
    }
}

fn main() {
    println!("{}", some_kind_of_uppercase_first_letter("joe"));
    println!("{}", some_kind_of_uppercase_first_letter("jill"));
    println!("{}", some_kind_of_uppercase_first_letter("von Hagen"));
    println!("{}", some_kind_of_uppercase_first_letter("ß"));
}
但我可能会在crates.io上搜索,然后让比我聪明的人来处理

改进 说到“比我聪明的人”,在访问第一个大写代码点之后,将迭代器转换回切片可能更有效。这允许剩余字节的
memcpy

fn some_kind_of_uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}
fn某种类型的大写字母首字母(s:&str)->字符串{
设mut c=s.chars();
匹配c.next(){
None=>String::new(),
Some(f)=>f.to_大写().collect::()+c.as_str(),
}
}
有比这更简单的方法吗?如果有,是什么?如果不是,为什么防锈设计是这样的

嗯,是和否。正如另一个答案所指出的,你的代码是不正确的,如果你给它类似的东西,它会惊慌失措བོད་སྐད་ལ་. 因此,使用Rust的标准库执行此操作比您最初想象的还要困难

然而,Rust的设计目的是鼓励代码重用,并使引入库变得容易。因此,将字符串大写的惯用方法实际上非常容易接受:

extern crate inflector;
use inflector::Inflector;

let capitalized = "some string".to_title_case();

如果您能够将输入限制为仅限ASCII字符串,则不会特别复杂

由于Rust 1.23,
str
有一个
make_ascii_uppercase
方法(在较旧的Rust版本中,可通过
AsciiExt
trait获得)。这意味着您可以相对轻松地仅使用大写ASCII字符串片段:

fn make_ascii_titlecase(s: &mut str) {
    if let Some(r) = s.get_mut(0..1) {
        r.make_ascii_uppercase();
    }
}
这将把
“taylor”
变成
“taylor”
,但不会把
“édouard”
变成
“édouard”
。()


请谨慎使用。

这里有一个版本比@Shepmaster的改进版稍慢一些,但也更惯用:

fn首字母大写(s:&str)->字符串{
fn some_kind_of_uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}
extern crate inflector;
use inflector::Inflector;

let capitalized = "some string".to_title_case();
fn make_ascii_titlecase(s: &mut str) {
    if let Some(r) = s.get_mut(0..1) {
        r.make_ascii_uppercase();
    }
}
fn str_cap(s: &str) -> String {
  format!("{}{}", (&s[..1].to_string()).to_uppercase(), &s[1..])
}
fn str_cap(s: &str) -> String {
  format!("{}{}", s.chars().next().unwrap().to_uppercase(), 
  s.chars().skip(1).collect::<String>())
}