在此之前,我已经提到过相关问题和其他帖子。我也意识到std::to_string()是最好的方法(但它在少数平台上是不可用的)。
当experimenting,遇到memcpy()时,我遇到了一个奇怪的问题。为了示例起见,假设我们总是将内置数据类型(int、char、long)传递给下面的函数:
template<typename T>
std::string to_string (const T& value)
{
std::string s(16, 0); // Max size captured
::memcpy(&s[0], &value, sizeof(value));
return s;
}在示例程序中单独运行此函数可以工作得很好。但是,当插入一个更大的代码库时,不知怎么的,它会产生奇怪的结果!也就是说,它提供了虚假的值。(Ubuntu14.10,g++4.9 -std=c++11)
但是,如果我使用sprintf()来转换上面的程序,它就会工作得很好。
template<typename T>
std::string to_string (const T& value)
{
std::string s(16, 0); // Max size captured
s[::snprintf(&s[0], "%d", value)] = 0;
return s;
}问题:
memcpy() (甚至sprintf())中未定义的行为?发布于 2014-08-09 01:40:48
简单地说,是的,您不想使用memcpy()。使用snprintf(),您不必自己将数字转换为ASCII。不过,像这样的事情可能更可取:
template<typename T>
std::string to_string (const T& value)
{
char buf[16];
::snprintf(buf, sizeof(buf), "%d", value);
// ^-- size was missing in your example
return buf;
}但是,这个函数有一个很大的流,因为你不知道T会是什么。它可能是双倍的,而且"%d"不会像预期的那样工作。类似地,它可以是一个字符串(char const *)。
如果要手动将数字转换为ASCII,可以使用循环,如下所示:
template<typename T>
std::string to_string (T value)
{
char buf[16]; // any int number is less than 16 characters
char *s = buf + sizeof(buf);
*--s = '\0';
do
{
*--s = value % 10 + '0'; // conversion to ASCII, 1 digit at a time
value /= 10;
}
while(value > 0);
return s;
}警告:该函数不能正确处理负数。我会让这件事做个练习,你可以根据需要来处理。
现在,如果您想使用一种C++方式,它应该可以在您提到的所有系统上工作,而不需要boost或C++11。
template<typename T>
std::string to_string (T const& value)
{
std::stringstream ss;
ss << value;
return ss.str();
}在这种情况下,只要这些东西理解<< (在std::cout << "Hello!" << std::endl;中),字符串流就知道如何处理T--不管T是什么、数字、对象等等。
如果您签出我的一个名为as2js的项目,您将看到一个名为include/as2js/node.h的文件声明如下所示:
std::ostream& operator << (std::ostream& out, Node const& node);这意味着您以后可以创建一个节点并按如下方式打印它:
Node n;
std::out << n << std::endl;这意味着您的to_string()函数将使用我的Node对象。
您可以在lib/nodedisplay.cpp下找到所有这些的实现。
https://stackoverflow.com/questions/25202083
复制相似问题