带有sprintf()的C ++ toString()

时间:2012-08-09 22:16:14

标签: c++ string tostring printf c-str

使用C ++我试图为我的类实现一个toString()函数:

void ClassName::toString(string& returnString)
{
    sprintf(returnString.c_str(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
}

但是我一直收到这个错误:类型为const char *的参数与char *类型的参数不兼容

如何修复此问题并使参数不再为常量?

5 个答案:

答案 0 :(得分:5)

  

我该如何解决这个问题?

使用其他方法,改为使用stringstream或辅助缓冲区。

void ClassName::toString(string& returnString)
{
    std::stringstream ss;
    ss << "Position: (" << position.x << ", " << position.y << ", " 
       << position.z << ")\n");
    returnString = ss.str();
}
  

并使参数不再是const?

不要。如果将c_str更改为非const类型,地狱将会失败。同事们会哭泣。天使会失去翅膀。小猫会死。油价将上涨。股市崩盘。 Zombie apocalipse。

原因是const - 所以你不要修改它。这样做会导致未定义的行为。

答案 1 :(得分:0)

在现代C ++中你可以说:

std::string ClassName::toString() const
{
    return "Position: (" + std::to_string(position.x) + ", "
          + std::to_string(position.y) + ", "
          + std::to_string(position.z) + ")\n";
}

如果你必须使用printf,你仍然可以使用字符串,但你必须先调整它的大小。

std::string ClassName::toString() const
{
    static const int initial_size = 1024;

    std::string s(initial_size);
    int ret = std::snprintf(&s[0], s.size(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    s.resize(ret);

    // handle overflow: print again
    if (s.size() > initial_size)
    {
        std::snprintf(&s[0], s.size(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    }
    return s;
}

请注意&s[0]为您提供了一个指向可变char的指针,实际上是一个大小为s.size()的整个数组的第一个元素。

答案 2 :(得分:0)

c_str()返回const char *,因为使用c_str()函数返回的指针更改字符串的值通常不是一个好主意。

顺便说一句,你要做的事情毫无意义。您应该只使用returnString.append()方法。

但是如果你必须使用sprintf,你应该确保你的字符串有空间来保存sprintf的输出。

第一种方法:您可以使用.reserve()方法执行此操作,但如果直接修改字符串,则不会更改.size()返回的字符串内部大小计数器使用sprintf()方法的缓冲区(append()将进行适当的大小调整)。如果您不需要使用.size()方法,就不会有任何问题。

第二种方法(更好):如果您知道sprintf的确切输出长度,这是更好的方法。您应该使用.resize()方法而不是.reserve().resize()会正确调整字符串的大小计数器。

最后,您应该使用:sprintf(const_cast<char *>(returnString.data()), ...

顺便说一句,这件事并不是一个好主意。

<强> P.S。 .data().**c**_str()相同,除了它不附加null终止符以使其成为c样式字符串。

答案 3 :(得分:0)

为sprintf制作一个缓冲区。然后再分配给returnString。

void ClassName::toString(string& returnString)
{ 
    char buffer[64] = {}; // expect the length of `Position Info` will not exceed 63
    sprintf(buffer, "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    returnString = buffer;
}

答案 4 :(得分:-1)

http://www.cplusplus.com/reference/string/string/c_str/

  

返回的数组指向一个内部位置,该位置具有此字符序列所需的存储空间及其终止的空字符,但此数组中的值不应在程序中修改,只保证保持不变,直到接下来调用字符串对象的非常量成员函数。

您不得修改返回的char *

的内容

尝试类似:

void ClassName::toString(string& returnString)
{
    char tmp[256];
    sprintf(tmp, "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    returnString=tmp;
}