在Rust中,使用字符串字面量进行更方便的字符串拼接

21
在 Rust 的最新版本中,不再可以使用“~”字符来将字符串字面值指定为 String 类型。在此处
例如,在 C++ 中,我使用用户定义的字面量来连接字符串字面值,而无需每次都提及 std::string。
inline std::string operator"" _s (const char* str, size_t size) {return std::string (str, size);}
foo ("Hello, "_s + "world!");

Rust 中是否存在或计划推出类似的功能,以使字符串字面量的连接过程不像 String::from_str ("Hello, ") + "world!" 那样麻烦?


1
为了提高可读性。 - ArtemGr
2
为什么要连接字符串字面值?你不能直接将它们写成单个字面量吗? - huon
1
@dbaupp 你一定在开玩笑。当然不是!连接字符串字面量是我的拿手好戏,如果我只写一个字面量,那我在工作中该做什么呢? - ArtemGr
我相信在 C 和 C++ 中,如果您像这样连续编写字符串文字 char foo[] = "Hello " "world";,它们将会连接起来,生成 "Hello world"。因此,没有必要使用用户定义的文字。 - Amomum
@Amomum 不过在 Rust 中这不是一个问题,fomat-macros 可以实现这一点(也是我目前最喜欢构建字符串的方式)。示例:https://github.com/KomodoPlatform/atomicDEX-API/blob/841f82e8d0f30eb1e602e4317937060feb0bd675/mm2src/mm2.rs#L88 - ArtemGr
显示剩余3条评论
3个回答

45

如果你字面上(哈哈)有字符串文字,你可以使用concat!宏:

let lit = concat!("Hello, ", "world!")
您可以在原生状态下将字符串拆分成多行:
let lit = "Hello, \
           World";

\ 消耗所有后续的空白字符,包括下一行开头的空格;省略 \ 将原样包含字符串数据,包括换行和前导空格等。

您可以将 &str 添加到 String

let s = "foo".to_string() + "bar" + "baz";

你可以迭代使用push_str方法:

let mut s = "foo".to_string();
s.push_str("bar");
s.push_str("baz");

您可以使用SliceConcatExt::concat

let s = ["foo", "bar", "baz"].concat();

如果所有其他方法都失败了,您可以定义一个宏来完全实现您想要的功能。

另请参阅:


17
您可以使用format! 宏。它更易读,更易于翻译,更高效,更强大(您可以连接多个字符串,就像C++的ostringstream)。它也完全支持类型安全。
format!("Hello, {}", "world!")

你还可以使用命名参数来提高可读性。

format!("hello, {who}", who = "world")

完整的格式化语法在std::fmt中有描述。

Rust没有用户定义的字面量。我认为添加这样的功能是向后兼容的,因此也许在Rust 1.0之后会添加这个功能。


谢谢你的回答。我喜欢Rust能够实现这样的事情,但是如果我们谈论程序的可读性,那么这些printf变体都会遭受将事物打乱而不是保持自然顺序的问题。当构建一个复杂的字符串,比如SQL查询时,像这篇文章中描述的那样保持事物在原位的版本(安全字符串内核)更可取。http://blog.moertel.com/posts/2006-10-18-a-type-based-solution-to-the-strings-problem.html - ArtemGr
我还应该提到Scala中的字符串插值,它也避免了洗牌问题:http://slick.typesafe.com/doc/2.0.0-M3/sql.html#string-interpolation - 在那里,变量会自动转义(或者说绑定到一个准备好的查询中),就像Haskell版本一样,尽管前者更强大。 - ArtemGr
1
@ArtemGr,应该可以编写一个宏来以类似的方式进行准备/插值(语法示例);类型系统肯定足够强大,可以表达像安全字符串这样的概念。 - huon
@dbaupp,这是我听到的好消息,我可能会投入一些时间学习Rust宏系统,谢谢。 - ArtemGr

2

使用concat!宏,您可以连接str字面值而不使用String

最初的回答:

let input = concat!("Hello", ' ', "world");

要将它转换为字符串,指定目标类型并使用 into
将其转换为字符串,指定目标类型并使用 into
let input: String = concat!("Hello", ' ', "world").into();

完整程序:

fn main() {
    let input: String = concat!("Hello", ' ', "world").into();
    println!("{}", input);  // Output: Hello world
}

“concat!”已经被得票最高的答案展示了。这个答案并没有添加任何有价值的内容。 - Shepmaster

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