看到用 Java 的朋友 “ int to string” 可以用 toString(),让我这学 C++ 的顿觉惆怅,为啥我大 C++ 没有这么好用的方法,直到昨天我才在网上看到,原来 C++11 中已经有 std::string to_string() 方法了,看来还是我太菜了,没有发现这么好用的方法,我忍不住看了一下源代码,在这里分享一下
如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢
声明
// #include <string>
string to_string(int _Val);
string to_string(unsigned int _Val);
string to_string(long _Val);
string to_string(unsigned long _Val);
string to_string(long long _Val);
string to_string(unsigned long long _Val);
string to_string(float _Val);
string to_string(double _Val);
string to_string(long double _Val);
可以看到 to_string(); 方法不仅支持各种整型( 有符号的、无符号的、长的、短的 任意组合,哈哈哈哈 ),还支持各种浮点型( float/double 包括长的、短的 )
源码
- int to string
// #include <string>
// 这是 int to string 方法的 to_string();
// to_string NARROW CONVERSIONS
_NODISCARD inline string to_string(int _Val)
{ // convert int to string
// 各种整型均调用了_Integral_to_string(); 这个模板函数,这里以 int to string 介绍源码
return (_Integral_to_string<char>(_Val));
}
// 这是 _Integral_to_string(); 模板函数的源码
template<class _Elem,
class _Ty> inline
basic_string<_Elem> _Integral_to_string(const _Ty _Val)
{ // convert _Val to string
static_assert(is_integral_v<_Ty>, "_Ty must be integral");
using _UTy = make_unsigned_t<_Ty>;
// 这里定义了一个字符数组用于放 -2^63 and 2^64 - 1 之间的数转换后的字符串
_Elem _Buff[21]; // can hold -2^63 and 2^64 - 1, plus NUL
// _Buff_end 指向 _Buff 的最后一个位置也就是 _Buff[20] 的位置
_Elem* const _Buff_end = _STD end(_Buff);
// _RNext 指针也初始化为 _Buff 的最后一个位置
_Elem* _RNext = _Buff_end;
const auto _UVal = static_cast<_UTy>(_Val);
if (_Val < 0)
{
// 如果是负数先通过 0 - _UVal 转化成正数,然后调用 _UIntegral_to_buff() 最后加一个负号
_RNext = _UIntegral_to_buff(_RNext, 0 - _UVal);
*--_RNext = '-';
}
else
// 如果是正数直接调用 _UIntegral_to_buff()
_RNext = _UIntegral_to_buff(_RNext, _UVal);
// 最后返回一个用字符串开始和结尾初始化的 string
// 这个初始化先使用过 STL 的 traits 将指针转化成通用的迭代器,这里不多介绍了,感兴趣的可以看 STL 中 string 的构造函数
return (basic_string<_Elem>(_RNext, _Buff_end));
}
// _UIntegral_to_buff 的源码,没有全粘过来,只粘了重要的部分,感兴趣的可以到 string 头文件中查看
// HELPERS FOR to_string AND to_wstring
template<class _Elem,
class _UTy> inline
_Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal)
{ // format _UVal into buffer *ending at* _RNext
static_assert(is_unsigned_v<_UTy>, "_UTy must be unsigned");
// 通过这个do {... } while(); 循环完成了从低位到高位完成转换,最后返回指向最高位的指针
do
{
*--_RNext = static_cast<_Elem>('0' + _UVal_trunc % 10);
_UVal_trunc /= 10;
}
while (_UVal_trunc != 0);
return (_RNext);
}
- float to string
// #include <string>
// float to string 和 int to string 流程类似
_NODISCARD inline string to_string(float _Val)
{ // convert float to string
// 浮点型都是调用的 _Floating_to_string() 这个模板函数
return (_Floating_to_string("%f", _Val));
}
// 这是 _Floating_to_string() 模板函数的源码
template<class _Ty> inline
string _Floating_to_string(const char *_Fmt, _Ty _Val)
{ // convert _Val to string
static_assert(is_floating_point_v<_Ty>,
"_Ty must be floating point");
// _scprintf 获取浮点数的长度
const auto _Len = static_cast<size_t>(_CSTD _scprintf(_Fmt, _Val));
// 初始化一个与浮点数等长的 string
string _Str(_Len, '\0');
// sprintf_s 将浮点数格式化输出到前面定义好的 string 中
_CSTD sprintf_s(&_Str[0], _Len + 1, _Fmt, _Val);
return (_Str);
}
以上源码是在 VS2017 __cplusplus == 201402L 下找到的