取代snprintf(3)的c++习惯用法是什么?
What is the C++ idiom to replace snprintf(3)?
我有一些c++代码,需要在解析某个文件头失败时生成错误消息。在这种情况下,我需要确保头中的某个4字节字段是"OggS",如果不是,则返回错误消息,如"无效的capture_pattern: 'FooB';期待ogg"。我的代码看起来像这样:
const string OggPage::parseHeader(void) {
read(fd, capture_pattern, sizeof(capture_pattern)); // error handling omitted
if (strncmp(capture_pattern, CAPTURE_PATTERN, sizeof(capture_pattern)) != 0) {
char err[256];
snprintf(err, sizeof(err), "Failed to read %d bytes from file descriptor %d: %sn", sizeof(capture_pattern), fd, err);
return err;
}
return "Everything was A-OK!";
}
从其他数据类型构建字符串的标准c++习惯用法是什么?这里我不拘于printf(3)
样式的格式,所以请随意提出任何可行的方法。
您可以使用c++标准库中的stringstream
或ostringstream
。如果不使用进一步的流来读取它的值(例如,它的istream
部分将不使用)ostringstream
更合适。
#include <sstream>
#include <string>
#include <iostream>
int main() {
std::stringstream str_stream;
int number = 5;
str_stream << " String with number " << number << std::endl;;
std::string str = str_stream.str();
std::cout << str;
}
作为一个注意事项,请不要建议替换实际的阅读-这里我想使用C标准库进行I/O是有原因的。:)
你不能真的要求用"习惯"的方式在c++中做某事,然后说"但是我想坚持使用C标准库…
无论如何,你有三个选择。我不相信它们中的任何一个是惯用的(因为这意味着某种共识认为这是最好的方式):
- 坚持使用你已经在使用的C api
- 使用c++
std::stringstream
,它是标准库 的iostreams部分的一部分。 - 使用增加。
后者的缺点是它依赖于第三方库,但它的优点是它以类型安全和可扩展的方式为您提供了类似printf
的语法,可以与c++流清晰地互操作。
使用cstring
中的字符串函数绝对可以进行阅读。它们快速、方便且不冗长。
对于构建错误消息,您可以使用stringstream
,与string
类相关的操作符,boost::format
或如您所说的snprintf
。
你也有boost::lexical_cast
简单的事情:
string message = "Failed to read " + lexical_cast<string>(n) +
" bytes from the descriptor " + lexical_cast<string>(fd) + ".";
我建议你看一下这篇文章,以获得同样的观点。
如果你有很多格式化要做,我推荐boost::format
。使用lexical_cast
的简单孤立的东西,并使用stringstream
,如果你有需求,使你需要他们(例如。自定义operator<<
,不能使用boost
等)。
说实话,snprintf
真的很好。
c++的方法是std::stringstream
。
std::stringstream err;
err << "Failed to read " << sizeof(capture_pattern)
<< " bytes from fd " << fd << std::endl;
return err.str();
创建stringstream,使用'<<'操作符编写所需内容,然后使用成员函数.str()将字符串从流中取出。
#include <sstream>
#include <string>
using namespace std;
stringstream err;
err << "Failed to read " << sizeof(capture_pattern) << " bytes from file descriptor: " << fd << endl;
string outstr = err.str();
- 复制和交换习惯用法与移动操作之间的交互
- 命名参数习惯用法和(抽象)基类
- 复制交换习惯用法-我们可以在这里使用动态强制转换操作吗
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 使用 PIMPL 惯用法,实现是否应始终是类的私有成员?
- C++移动分配可防止复制交换习惯用法
- 将 PIMPL 习惯用法与成员函数模板一起使用(无需预先了解所有可能的数据类型)
- 使用新线程在类似于 Scott Meyer 的单例习惯用法的实现中实例化单例是否安全?
- Pimpl习惯用法、单独的接口/实现文件和多个虚拟继承.如何
- C++迭代器"for loop"习惯用法,其步长> 1 并允许非随机访问反向迭代器
- 访问基类型数组成员(Int-to-type习惯用法)
- 基于智能指针的 CRTP 习惯用法的编译问题
- 通过C接口分配和释放资源的正确习惯用法
- 副本交换习惯用法的有效性
- 视图和控制器之间接口的习惯用法
- Boost:创建一组线程并等待所有线程的正确习惯用法是什么
- 当涉及分配器时,是否有类似于复制和交换习惯用法的东西
- 是具有复制和交换习惯用法的复制赋值运算符,建议进行自赋值检查
- C++或D:在没有动态调度的情况下解耦类的习惯用法
- 标准::rel_ops的惯用法