高效的将整型类型转换为字符串的方法

18 篇文章 1 订阅
4 篇文章 0 订阅

最近在项目中需要用到将数字转换为字符串,这里主要记录在使用过程中的一些思考。并且提供了一个较高效的转换实现。

说到如何将数字转换为字符串,我们可能先想到的是C函数库提供的snprintf等系列的函数或是C++库提供的功能更为强大的stringstream对象来进行转换。

没错C函数库提供的snprintf等系列函数非常的好用和方便。
例如:我们想要将一个int型的数值转换为对应的字符串。

#include <iostream>
#include <stdio.h>

using namespace std;

int main(void)
{
	//在VS2013中iValue = -2147483648会报错
	int iValue = -2147483647 - 1;
	char arrBuffer[32];

	//这里是在VC++进行编译,所以使用_snprintf。
	_snprintf(arrBuffer, sizeof(arrBuffer), "%d", iValue);

	cout << arrBuffer << endl;

	return 0;
}

结果正是我们想要的:

-2147483648


C++库提供stringstream对象也能简单的完成这样的转换。

#include <iostream>
#include <sstream>

using namespace std;

int main(void)
{
	stringstream streamStr;
	int iValue = -2147483648;
	char arrBuffer[32];

	streamStr << iValue;
	streamStr >> arrBuffer;

	cout << arrBuffer << endl;

	return 0;
}
输出如下:

-2147483648
使用起来相当的方便。不得不感叹stringstream的强大,安全,自动和直接。

下面我们来考虑使用snprintf或stringstream将数字转换为字符串的效率问题,在测试中我们关闭了优化选项,效率的测试在window(VS2013)上运行和Linux上面运行,在不同的机器上测试可能会有不同的表现。

先来看看用snprintf来执行数值转换的效率吧!

#include <iostream>
#include <stdio.h>
#include <time.h>

using namespace std;

int main(void)
{
	time_t NewTime;
	time_t OldTime;
	char arrBuffer[32];

	time(&OldTime);
	for (int i = -20000000; i <= 0; i++)
		//这里是在VC++进行编译,所以使用_snprintf。
		_snprintf(arrBuffer, sizeof(arrBuffer), "%d", i);
	time(&NewTime);

	cout << arrBuffer << endl;
	cout << "time = " << NewTime - OldTime << endl;

	return 0;
}

在Window上:	运行20000000次	8s	
在Linux上:	运行40000000次	4s
结果差距有点大。

再来看看使用stringstream进行转换吧!

#include <iostream>
#include <sstream>
#include <time.h>

using namespace std;

int main(void)
{
	time_t NewTime;
	time_t OldTime;
	string strBuffer;

	time(&OldTime);
	for (int i = -20000000; i <= 0; i++)
	{
		stringstream streamStr;
		streamStr << i;
		streamStr >> strBuffer;
	}
	time(&NewTime);

	cout << strBuffer << endl;
	cout << "time = " << NewTime - OldTime << endl;

	return 0;
}
在Window上:	运行20000000次	274s	
在Linux上:	运行40000000次	29s
差距同样很大。

看上去效率还行,如果需要在高效点呢!ps:这里并不是评判snprintf或stringstream,相反我觉得非常的好用。只是snprintf或stringstream的功能强大,将数值转换为字符串只是它们的一小部分功能。

于是,就针对高效的将整型转换为字符串进行思考。下面给出第一次的实现:

#include <iostream>
#include <stdio.h>
#include <time.h>

using namespace std;

const char NumTab[] = {"9876543210123456789"};

template<typename T>
int NumberToString(char arrBuffer[], T value)
{
	int iRemainder;
	T TmpValue = value;
	char *pTmp = arrBuffer;
	const char *pNumTab = &NumTab[9];

	do
	{
		iRemainder = static_cast<int>(TmpValue  % 10);
		*pTmp++ = pNumTab[iRemainder];
		TmpValue /= 10;
	}while(TmpValue != 0);

	if(value < 0)
		*pTmp++ = '-';

	*pTmp = '\0';
	//反转元素顺序
	std::reverse(arrBuffer, pTmp);

	return static_cast<int>(pTmp - arrBuffer);	
}

int main(void)
{
	time_t NewTime;
	time_t OldTime;
	char arrBuffer[32];

	time(&OldTime);
	for (int i = -20000000; i <= 0; i++)
		NumberToString(arrBuffer, i);
	time(&NewTime);

	cout << arrBuffer << endl;
	cout << "time = " << NewTime - OldTime << endl;
	
	return 0;
}
在Window上:	运行20000000次	19s	
在Linux上:	运行40000000次	5s

好吧!比起snprintf更慢,有点让人失望。继续改进。

#include <iostream>
#include <time.h>

using namespace std;

const char NumTab[] = {"9876543210123456789"};

template<typename T>
int NumberToString(char arrBuffer[], T value)
{
	int iStrNum = 0;
	int iRemainder;
	T TmpValue1 = value;
	T TmpValue2 = value;
	const char *pNumTab = &NumTab[9];

	if (value < 0)
		iStrNum++;

	do
	{
		iStrNum++;
	}while((TmpValue1 /= 10) != 0);

	char *pTmp = arrBuffer + iStrNum;

	*pTmp-- = '\0';

	do
	{
		iRemainder = static_cast<int>(TmpValue2 % 10);
		*pTmp-- = pNumTab[iRemainder];
		TmpValue2 /= 10;
	}while(TmpValue2 != 0);

	if(value < 0)
		*pTmp = '-';
	return iStrNum;
}

int main(void)
{
	time_t NewTime;
	time_t OldTime;
	char arrBuffer[32];

	time(&OldTime);
	for (int i = -20000000; i <= 0; i++)
		NumberToString(arrBuffer, i);
	time(&NewTime);

	cout << arrBuffer << endl;
	cout << "time = " << NewTime - OldTime << endl;
	
	return 0;
}

在Window上:	运行20000000次	4s	
在Linux上:	运行40000000次	4s

现在的效率还行,不管在Linux或Window上至少比snprintf和stringstream快(在Linux上和snprintf差不多)。

暂时没想到什么更高效的方法,就行这样了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值