C++ toString() with sprintf()

C++ toString() with sprintf()

本文关键字:sprintf with toString C++      更新时间:2023-10-16

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

我如何解决这个问题并使参数不再恒定?

我该如何解决这个问题?

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

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

并使论点不再持续?

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

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

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()), ...

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

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

在现代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]为您提供了一个指向可变字符的指针,实际上是指向大小为 s.size() 的整个数组中的第一个元素。

为 sprintf 创建一个缓冲区。然后分配给返回字符串返回。

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;
}

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

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

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

尝试类似这样的操作:

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