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

来源:互联网 发布:怎样通过网络找人 编辑:程序博客网 时间:2024/05/22 17:34

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

说到如何将数字转换为字符串,我们可能先想到的是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差不多)。

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

0 0