0

我正在尝试编写一个宏来扩展结构的内容:

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]

是否可以编写一个执行此操作的宏?如果是,那怎么办?

4

4 回答 4

6

您是否有理由将其作为宏来执行?

您应该编写一个函数来执行此操作,而不是使用预处理器。


根据您的目标,有几种选择。boost 格式化库提供了一个很棒的工具包来构建格式化的字符串。您也可以始终重载operator<<以提供干净的输出。

如果您在纯 C 中执行此操作,则sprintf系列方法可用于创建格式化输出。

于 2012-06-16T00:56:28.433 回答
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());
于 2012-06-16T01:16:20.063 回答
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 ;
}
于 2014-05-09T08:45:55.123 回答
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()

我建议编写一个成员函数来执行此操作。

于 2012-06-16T01:15:15.480 回答