简体   繁体   English

sprintf和char []与字符串

[英]sprintf and char [] vs. string

I need to pass const char * to a function. 我需要将const char *传递给函数。 Before I pass it, I usually need to build it from some variables. 在通过它之前,我通常需要根据一些变量来构建它。 I can never decide which approach is more elegant, and overall better: 我永远无法确定哪种方法更优雅,总体上更好:

  • Allocate an array long enough to fit the text and use sprintf to build the final variable and pass it to the function. 分配足够长的数组以适合文本,并使用sprintf构建最终变量并将其传递给函数。
  • Initialize string s with a variable using the + operator (concatenation) and then pass it to the function using s.c_str() . 使用+运算符(并置)使用变量初始化字符串s ,然后使用s.c_str()将其传递给函数。

Cons of using an array: May not fit the entire text. 使用数组的缺点:可能不适合整个文本。
Pro: Fast. 优点:快。

Cons of using a string: I don't need to worry about memory management, easy to build. 使用字符串的缺点:我不必担心易于构建的内存管理。 Pro: Slow. 优点:慢。

My second question is: How do you usually build a complete string from other variable strings? 我的第二个问题是:通常如何从其他变量字符串构建完整的字符串?

Unless it's absolutely performance critical, I tend to use a std::stringstream to build up the string from its components and then c_str() the resulting string. 除非绝对对性能至关重要,否则我倾向于使用std :: stringstream从其组件中构建字符串,然后使用c_str()生成字符串。 This is safe as there isn't really a chance of a buffer overflow this way and usually fast enough. 这是安全的,因为这样实际上几乎没有缓冲区溢出的机会,而且通常足够快。

If the profiler tells me that building up the string is a hot spot then you will have to trade some safety for speed and start using something like sprintf but I'd rather avoid this. 如果分析器告诉我建立字符串是一个热点,那么您将不得不为了速度而牺牲一些安全性,并开始使用sprintf之类的东西,但我宁愿避免这种情况。 Overall I'd use this as a last resort. 总的来说,我会将其作为最后的选择。

This really sounds like a case for Herb Sutter's excellent article The String Formatters of Manor Farm . 这听起来确实像是Herb Sutter出色的文章The Manor Farm的String Formatters的案例。

For the record: I myself use std::ostringstream , build the string up and pass oss.str().c_str() . 作为记录:我自己使用std::ostringstream ,构建字符串并传递oss.str().c_str()

One crash from a too-short buffer will negate all the speed savings you get from sprintf. 缓冲区太短导致的一次崩溃将抵消您从sprintf获得的所有速度节省。 I'm not convinced it's faster anyway. 我不认为它反而会更快。 And even if it is, is the difference significant enough to worry about? 即使是这样,差异是否也足以令人担忧?

I almost always use string and stringstream , due to the easier memory management. 由于内存管理更加简便,因此我几乎总是使用stringstringstream sprintf and other old-fashioned-C library calls are just too error-prone. sprintf和其他老式C库调用很容易出错。

The one benefit of sprintf -style functions over stringstream is that it makes it easy to use different format strings at runtime, for internationalization purposes. sprintf样式函数相对于stringstream的一个好处是,可以轻松地在运行时使用不同格式的字符串,以实现国际化。 But you should definitely use snprintf or one of the other "safer" variants of it. 但是,您绝对应该使用snprintf或它的其他“更安全”的变体之一。

When it comes to C++ and elegance, I tend to follow two rules: 关于C ++和优雅,我倾向于遵循两个规则:

  1. Say what you mean. 说你的意思。
  2. Profile first, optimize later. 首先进行分析,然后进行优化。

You're talking about concatenating strings here, so this is the code that comes to mind: 您在这里谈论的是连接字符串,因此这是我想到的代码:

std::string s = s1 + s2 + s3 + s4;
foo(s.c_str());

To "say what you mean," I reach for operator + . 为了“说出您的意思”,我联系operator + Using std::stringstream (a stream of strings) is pretty good too, but I don't immediately go for another #include just to concatenate strings. 使用std::stringstream (字符串流)也很不错,但是我不会立即去使用另一个#include来连接字符串。 It's a matter of personal preference I guess. 我猜这是个人喜好问题。 I definitely don't think of building up a raw char array by hand. 我绝对不考虑手动构建原始char数组。

In terms of performance, my guess is that operator + is probably the slowest method of putting the strings together. 就性能而言,我猜测operator +可能是将字符串放在一起的最慢的方法。 But even a slow method might be fast enough for your purposes. 但是即使是慢速的方法也可能足够快达到您的目的。

Repeat the following to yourself three times every morning when you wake up and three times every night before you go to bed: 每天早晨醒来时重复三遍,每晚睡觉前重复三遍:

"Premature optimization is the root of all evil." “过早的优化是万恶之源。” - Knuth -努斯

In other words, go with the safe, idiomatic C++ way. 换句话说,请遵循安全,惯用的C ++方式。 Speed should be fixed when (and if) it becomes an issue, not before, ESPECIALLY if fixing it before makes your code more error-prone. 当(如果有)速度成为问题时,应该固定速度,而不是以前,尤其是如果在速度之前固定速度会使您的代码更容易出错,则应该固定速度。

As for your second question: look up ropes . 至于您的第二个问题:查找绳索

You didn't mention your platform, but in case you use glibc as your standard library, there is GNU extension - asprintf() , that automatically allocate string big enough. 您没有提到平台,但是如果您使用glibc作为标准库,则可以使用GNU扩展asprintf() ,该扩展会自动分配足够大的字符串。

See man asprintf for details. 有关详细信息,请参见man asprintf

More universal approach - first call fprintf() to unused stream just to get the returned length, then allocate the string and print to it, like this: 更通用的方法-首先对未使用的流调用fprintf()只是为了获取返回的长度,然后分配该字符串并打印到该字符串,如下所示:

FILE *stream = tmpfile();
char *string;

string = malloc(fprintf(stream, format, param)+1);
sprintf(string, format, param);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM