C++11 的 to_string()

看到用 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 包括长的、短的 )

源码
  1. 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);
	}
  1. 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 下找到的

发布了20 篇原创文章 · 获赞 3 · 访问量 487

猜你喜欢

转载自blog.csdn.net/xiao_ma_nong_last/article/details/103745012
今日推荐