本文介绍了C ++格式的宏/内联ostringstream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图编写一个宏,它允许我做一些类似于: FORMAT(a<<b< c< d),结果将是一个字符串 - 与创建ostringstream一样,插入 a ... d ,并返回。 STR()。像这样: pre $ c $ string $ $ o<<一个< b<< c< d; return o.str()} 实际上, FORMAT(a 。 首先,我试过: 1:#define FORMAT(items)\ ((std :: ostringstream& amp; amp; ;)(std :: ostringstream() 第一个项目是一个C字符串( const char * ),它将以十六进制打印字符串的地址,接下来的项目将打印罚款。如果第一个项是 std :: string ,它将无法编译(没有匹配的运算符<< 2:#define FORMAT( (std :: ostringstream())(std :: ostringstream() 给出了正确的输出,但是 0 和 \ b 出现在字符串当然。 以下似乎工作,但编译警告(以临时地址): 3:#define FORMAT(items)\ ((std: :ostringstream&)(*((std :: ostream *)(& std :: ostringstream())) std :: string ?是不是1和3基本上是相同的?我怀疑,C ++ 0x可变参数模板将使格式(a,b, c,d)可能。但现在有没有办法解决这个问题呢? 解决方案 但是要遵循一点点挑战。所以,让我试着总结一下你所说的话... 这里的困难在于: p> 我们正在玩一个临时的 ostringstream 对象,因为它是一个临时的,所以我们不能通过强制转换来转换为一个 ostream 对象。 构造函数[显然]和 str()都是类 ostringstream 方法。 (是的,我们需要使用 .str()。直接使用 ostringstream 调用 ios :: operator void *(),返回一个类似于指针的好/坏值,而不是字符串对象。 b 运算符<(lt;(...)既作为继承的 ostream 方法和全局功能。在任何情况下,它都会返回一个 ostream& 引用。 > ostringstream()<<foo< / code>是继承的方法 ostream :: operator<<(void *) 运算符<<(ostream&,const char *)。继承的 ostream ::运算符<<(void *)胜出,因为我们不能转换为 ostream 对象引用来调用全局函数。 [b] [b] [b] [b] [b] [b] [b] [b] [b] [b] [ >所以,要解决这个问题,我们需要: 分配一个临时的 ostringstream 。 将其转换为 ostream 。 附加数据。 将它转换回 ostringstream 。 并调用 str()。 分配: ostringstream()。 $ b 转换: 有几个选择。其他人则建议: $ b $ li $ ostringstream()<< std :: string()//对* David Norman的赞美* ostringstream()<< std :: dec //授予* cadabra * 使用: ostringstream()。 seekp(0,ios_base :: cur) ostringstream()。 write(,0) ostringstream()。 flush() ostringstream()<<刷新 ostringstream()<< ostringstream()<< unitbuf ostringstream()<< noshowpos 或其他任何标准操纵器。 [ #include ] 参考:参见插入带格式的数据这个网页的1/3。 b $ b 我们不能使用: b 运算符<<(lttringstream(),) (ostream&)ostringstream() 添加: 现在简单明了。 我们可以使用 code>(ostringstream&安培;)。但 dynamic_cast 会更安全。在不太可能的情况下, dynamic_cast 返回 NULL (它不应该),下面的 .str ()会触发coredump。 $ b 调用 str(): 猜猜。 放在一起。 $ b #define FORMAT(ITEMS)\ ((dynamic_cast< ostringstream&>(\ ostringstream()) seekp(0,ios_base :: cur)<< ITEMS)\ ).str()) 参考文献: b $ b IOstream图书馆 ostringstream 类型转换教程 Wiki:类型转换 。 I'm trying to write a macro that would allow me to do something like: FORMAT(a << "b" << c << d), and the result would be a string -- the same as creating an ostringstream, inserting a...d, and returning .str(). Something like:string f(){ ostringstream o; o << a << "b" << c << d; return o.str()}Essentially, FORMAT(a << "b" << c << d) == f().First, I tried:1: #define FORMAT(items) \ ((std::ostringstream&)(std::ostringstream() << items)).str()If the very first item is a C string (const char *), it will print the address of the string in hex, and the next items will print fine. If the very first item is an std::string, it will fail to compile (no matching operator <<).This:2: #define FORMAT(items) \ ((std::ostringstream&)(std::ostringstream() << 0 << '\b' << items)).str()gives what seems like the right output, but the 0 and \b are present in the string of course.The following seems to work, but compiles with warnings (taking address of temporary):3: #define FORMAT(items) \ ((std::ostringstream&)(*((std::ostream*)(&std::ostringstream())) << items)).str()Does anyone know why 1 prints the address of the c-string and fails to compile with the std::string? Aren't 1 and 3 essentially the same?I suspect that C++0x variadic templates will make format(a, "b", c, d) possible. But is there a way to solve this now? 解决方案 You've all pretty much nailed this already. But it's a little challenging to follow. So let me take a stab at summarizing what you've said...That difficulties here are that:We are playing with a temporary ostringstream object, so taking addresses is contra-indicated.Because it's a temporary, we cannot trivially convert to an ostream object through casting.Both the constructor [obviously] and str() are class ostringstream methods.(Yes, we need to use .str(). Using the ostringstream object directly would wind up invoking ios::operator void*(), returning a pointer-like good/bad value and not a string object.)operator<<(...) exists as both inherited ostream methods and global functions. In all cases it returns an ostream& reference.The choices here for ostringstream()<<"foo" are the inherited method ostream::operator<<(void* ) and the global function operator<<(ostream&,const char* ). The inherited ostream::operator<<(void* ) wins out because we can't convert to an ostream object reference to invoke the global function. [Kudos to coppro!]So, to pull this off, we need to:Allocate a temporary ostringstream.Convert it to an ostream.Append data.Convert it back to an ostringstream.And invoke str().Allocating: ostringstream().Converting: There are several choices. Others have suggested:ostringstream() << std::string() // Kudos to *David Norman*ostringstream() << std::dec // Kudos to *cadabra*Or we could use:ostringstream() . seekp( 0, ios_base::cur )ostringstream() . write( "", 0 )ostringstream() . flush()ostringstream() << flushostringstream() << nounitbufostringstream() << unitbufostringstream() << noshowposOr any other standard manipulator. [#include <iomanip>] Reference: See "Insert data with format" 1/3 of the way down on this webpage.We cannot use:operator<<( ostringstream(), "" )(ostream &) ostringstream()Appending: Straightforward now.Converting back: We could just use (ostringstream&). But a dynamic_cast would be safer. In the unlikely event dynamic_cast returned NULL (it shouldn't), the following .str() will trigger a coredump.Invoking str(): Guess.Putting it all together.#define FORMAT(ITEMS) \ ( ( dynamic_cast<ostringstream &> ( \ ostringstream() . seekp( 0, ios_base::cur ) << ITEMS ) \ ) . str() )References:IOstream Libraryostringstreamostream::operator<<()Type Casting TutorialWiki: Type Casting. 这篇关于C ++格式的宏/内联ostringstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
06-30 21:31