2

使用 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* 类型的参数不兼容

我该如何解决这个问题并使论点不再是 const?

4

5 回答 5

5

我该如何解决?

使用不同的方法,使用stringstream替代或辅助缓冲区。

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

并使论点不再是常量?

不。c_str如果您更改为非常量类型,地狱将失败。其他程序员会哭的。天使会失去翅膀。小猫会死。油价将上涨。股市崩盘。僵尸启示录。

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

于 2012-08-09T22:17:59.443 回答
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]为您提供了一个指向可变字符的指针,实际上是指向整个数组的第一个元素的 size s.size()

于 2012-08-09T22:31:37.580 回答
0

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

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

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

第一种方法:你可以用方法来做,但是如果你直接用方法修改字符串缓冲区,.reserve()它不会改变字符串的内部大小计数器(会做适当的大小调整)。据我所知,如果您不需要使用该方法,不会有任何问题。.size()sprintf()append().size()

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

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

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

PS .data()与它相同,.**c**_str()只是它不附加空终止符以使其成为 c 样式字符串。

于 2012-08-09T22:34:08.140 回答
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;
}
于 2014-10-29T09:15:30.703 回答
-1

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

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

您不能修改返回的字符的内容 *

尝试类似:

void ClassName::toString(string& returnString)
{
    char tmp[256];
    sprintf(tmp, "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    returnString=tmp;
}
于 2012-08-09T22:28:20.087 回答