我正在尝试编写一个宏来扩展结构的内容:
struct Str
{
int a;
float f;
char *c;
};
Str s = {123, 456.789f, "AString"};
#define STRINGIFY_STR(x) ... // Macro to stringify x which is an instance of Str
printf("%s", STRINGIFY_STR(s));
期望的输出:[a:123,f:456.789,c:AString]
是否可以编写一个执行此操作的宏?如果是,那怎么样?
答案 0 :(得分:6)
您是否有理由将此作为宏?
您应编写一个函数来执行此操作,而不是使用预处理器。
根据您的目标,有一些选择。 boost formatting library提供了一个很好的工具包来构建格式化的字符串。你总是可以overload operator<<
提供干净的输出。
如果您在纯C中执行此操作,sprintf系列方法可用于创建格式化输出。
答案 1 :(得分:1)
这非常严重,仅适用于gcc
/ g++
。
#define STRINGIFY_STR(x) \
std::string(({ std::ostringstream ss; \
ss << "[a: " << x.a \
<< ", f: " << x.f \
<< ", c: " << x.c << "]"; \
ss.str(); })).c_str()
您必须根据值创建字符串。请不要这样做。请按照里德的建议。
以下是我如何修改您的struct
以使其打印得非常漂亮:
struct Str
{
int a;
float f;
char *c;
std::ostream & dump (std::ostream &os) const {
return os << "[a: " << a
<< ", f: " << f
<< ", c: " << c << "]";
}
};
std::ostream & operator << (std::ostream &os, const Str &s) {
return s.dump(os);
}
Str s = {123, 456.789f, "AString"};
现在,要打印s
,您可以使用std::cout
:
std::cout << s << std::endl;
或者,如果你真的想要一个字符串:
std::stringstream ss;
s.dump(ss);
puts(ss.str().c_str());
答案 2 :(得分:1)
struct stringify
{
operator std::string() const
{
return str ;
}
std::string str ;
};
template < typename T > stringify operator+ ( stringify s, const T& object )
{
std::ostringstream stm ;
stm << object ;
if( !s.str.empty() && !std::isspace( *s.str.rbegin() ) ) s.str += ' ' ;
s.str += stm.str() ;
return s ;
}
答案 3 :(得分:0)
我也反对这种做法,但要回答这个问题:
#define STRINGIFY_STR(x) \
(std::string("[a: ") + std::to_string((long double)x.a) \
+ std::string(", f:") + std::to_string((long double)x.f) \
+ std::string(",c: ") + x.c + std::string("]") ).c_str()
我建议写一个成员函数来做到这一点。