当前位置: 首页 > 知识库问答 >
问题:

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

齐凯康
2023-03-14

我想把a

let mut s = "foobar";
s[0] = s[0].to_uppercase();

但是<代码>

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;

有比这更简单的方法吗?如果有,是什么?如果不是,为什么防锈设计是这样的?

类似问题


共有3个答案

吴凯泽
2023-03-14

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

由于Rust 1.23,str有一个make_ascii_uppercase方法(在较旧的Rust版本中,可通过AsciiExttrait获得)。这意味着您可以相对轻松地仅使用大写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”。(游乐场)

小心使用。

司徒运锋
2023-03-14

有比这更简单的方法吗?如果有,是什么?如果不是,为什么防锈设计是这样的?

嗯,是也不是。正如另一个答案所指出的,你的代码是不正确的,如果你给它类似 བོད་སྐད་ལ་.所以用Rust的标准库做这件事比你最初想象的还要难。

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

extern crate inflector;
use inflector::Inflector;

let capitalized = "some string".to_title_case();
公西永嘉
2023-03-14

让我们一行一行地把它分解

let s1 = "foobar";

我们创建了一个以UTF-8编码的文字字符串。UTF-8允许我们以一种非常紧凑的方式编码Unicode的1,114,112个代码点,如果你来自世界上一个主要输入ASCII中字符的地区,ASCII是一个创建于1963年的标准。UTF-8是一种可变长度编码,这意味着单个代码点可能需要1到4个字节。较短的编码是为ASCII保留的,但是许多汉字在UTF-8中使用3个字节。

let mut v: Vec<char> = s1.chars().collect();

这将创建一个characters的向量。字符是直接映射到代码点的32位数字。如果我们从仅ASCII文本开始,我们的内存需求将增加两倍。如果我们有一堆来自星体层的角色,那么也许我们还没有使用那么多。

v[0] = v[0].to_uppercase().nth(0).unwrap();

这将获取第一个代码点并请求将其转换为大写变量。不幸的是,对于我们这些从小说英语的人来说,并不总是有一个简单的“小写字母”到“大写字母”的一一对应关系。旁注:我们称它们为大写和小写,因为一盒字母在当天的另一盒字母之上。

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

let s2: String = v.into_iter().collect();

在这里,我们将字符转换回UTF-8,并需要一个新的分配来存储它们,因为原始变量html" target="_blank">存储在恒定内存中,以便在运行时不占用内存。

let s3 = &s2;

现在我们引用这个String

这是一个简单的问题

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

我假设char::to_uppercase已经正确处理Unicode。

是的,我当然希望如此。不幸的是,Unicode在所有情况下都是不够的。多亏休恩指出了土耳其语I,大写(İ)和小写(I)版本都有一个点。也就是说,字母i没有一个适当的大写字母;它还取决于源文本的区域设置。

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

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

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

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

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

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

to_uppercase可以返回大写字符

如上所述,ß是一个单独的字符,大写后变成两个字符。

另请参见trentcl的答案,该答案仅使用大写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("ß"));
}

但我可能会在板条箱上搜索大写或unicode。让比我聪明的人来处理。

谈到“比我聪明的人”,Veedrac指出,在访问第一个大写代码点后,将迭代器转换回切片可能更有效。这允许剩余字节的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(),
    }
}
 类似资料:
  • 将一个字符串的第一个字母(大写字母)变成小写。 使用数组解构和 String.toLowerCase() 将第一个字母变成小写,...rest 是获取第一个字母之后字符数组,然后使用 Array.join('') 使其再次拼接成为字符串。 省略 upperRest 参数来保持字符串的其余部分不变,或者将其设置为 true 来将字符串的其余部分转换为大写。 const decapitalize =

  • 我正在尝试制作一个自动更正系统,当用户键入一个大写字母的单词时,自动更正就不起作用了。为了解决这个问题,我制作了一个字符串的副本。小写,然后比较它们。如果字符串确实输入错误,则应更正该单词。但是,替换键入的单词的单词都是小写的。所以我需要申请。大写字符串,仅限于第一个字母。我本来以为我可以用 但这显然不起作用。如何将字符串的第一个字母转换为大写,然后能够打印首字母大写的完整字符串? 感谢任何帮助!

  • 问题内容: 我想在angularjs中大写字符串的第一个字符 当我用它转换整个字符串为大写。 问题答案: 使用此大写过滤器

  • 我有一个函数,应该把字符串中每个单词的第一个字母大写,但不知何故,它提供了不正确的结果,知道为什么吗?我需要修理一下。 所以输入:hello dolly输出:hello dolly。 空格计算正确,但大写不正确。

  • 问题内容: 如何仅使用CSS将以下每个句子的大写字母转换为小写和首字母大写? 来自: 这是一个例句。 收件人: 这是一个例句。 更新: 当我使用文本转换时:大写;结果还是一样。 问题答案: CSS中没有句子大写选项。其他答案表明是不正确的,因为该选项将 每个单词 都大写。 如果您只希望 每个元素* 的 首字母 大写,则这是一种 粗略的 实现方式,但是与实际的句子大写绝对不符: *

  • 我试图编写一个函数,将字符串中每个单词的第一个字母大写(将字符串转换为标题大小写)。 例如,当输入是时,我希望是输出。然而,该函数返回。 这是我的代码: