2012-08-09 34 views
2

用C++我想实现我的类的toString()函数:C++的toString()与sprintf的()

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

不过,我不断收到此错误:类型为const char *的说法是不兼容使用参数类型char *

我该如何解决这个问题,并使参数不再是const?

回答

5

How do I fix this?

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

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

and make the argument no longer const?

不要。如果您将c_str更改为非常量类型,地狱将会破碎。各位程序员会哭泣。天使会失去他们的翅膀。小猫会死。油价会上涨。股市崩溃。僵尸apocalipse。

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

+1

'地狱就会失去'luv it! :) – 2012-08-09 22:18:41

+0

AHHHHH。不需要toString()。只需为该类定义一个流操作符。然后,您可以使用lexial_cast <>做转换,如果你确实需要一个字符串,但通常是的toString的唯一原因()是打印出来,以便流运营商完美。 – 2012-08-09 23:00:53

-1

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

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.

你不允许修改返回字符的内容*

尝试类似:

void ClassName::toString(string& returnString) 
{ 
    char tmp[256]; 
    sprintf(tmp, "Position: (%f, %f, %f)\n", position.x, position.y, position.y); 
    returnString=tmp; 
} 
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]给你一个指针指向可变的字符,确实给那些规模s.size()的一整个阵列的第一个元素。

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()只是它不追加空终止,使其C风格的字符串。

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