类型转换在很多时候需要使用上,方便且安全的转换是很有必要的。从C语言的一些api到c++中提供的stringstream流都有很多方式可以实现,了解他们的特点可以让我们在日常编码中编写出漂亮的代码。
一、C语言中常用的类型转换
char szBuf[100];
int nValue = 100000000;
sprintf_s(szBuf, sizeof(szBuf), "%d", nValue);
printf("%s\n", szBuf);
float fValue = 1.2f;
sprintf_s(szBuf, sizeof(szBuf), "%f", fValue);
printf("%s\n", szBuf);
char szOutBuf[100] = { "123.12456" };
sscanf_s(szOutBuf, "%f", &fValue);
printf("%f\n", fValue);
// 尝试从以%f格式化一个int类型的数字
//sprintf_s(szBuf, sizeof(szBuf), "%f", nValue);
//printf("%s\n", szBuf);
通过sprintf和sscanf可以从数值类型到字符串类型的转换, <stdlib.h>头文件中包含大量数据转换的api封装,比如_i64toa、_itoa、strtod、strtol、_fcvt等等。详细可参考msdn手册。
二、C++中通过stringstream流进行数据类型转换
//记得加上头文件
#include <sstream>
#include <iostream>
using namespace std;
string strValue;
string strOtherValue;
stringstream ssIO;
int nValue = 123;
ssIO << nValue << " " << nValue + 1; // 往stringstream流中写入123 124
string strBuf = ssIO.str(); // 从stringBuf中获取内容
cout << "stringstream buffer:" << strBuf << endl; // 123 124
ssIO >> strValue; // 将数值从ssIO流中读取到strOtherValue中
int nState = ssIO.rdstate(); // goodbit 0x00
cout << "stringstream state:" << nState << endl;
ssIO >> strOtherValue; // 将数值从ssIO流中读取到strOtherValue中
cout << strValue << " " << strOtherValue << endl; // 123 124
nState = ssIO.rdstate(); // eofbit 0x01 已经读取到最后了
cout << "stringstream state:" << nState << endl;
ssIO.clear(); // 清除eofbit状态
nState = ssIO.rdstate(); // goodbit 0x00
cout << "stringstream state:" << nState << endl;
strBuf = ssIO.str(); // 从stringBuf中获取内容
cout << "cleared state stringstream buffer:" << strBuf << endl; // 123 124
double lfValue = 12.0123456789;
ssIO << lfValue; // 往stringstream中写入double数值
strBuf = ssIO.str(); // 从stringBuf中获取内容
cout << "stringstream buffer:" << strBuf << endl; // 123 12412.0123456789
ssIO >> strValue;
cout << strValue << endl;
ssIO.str(""); // 设置stringstream中的buffer为空
strBuf = ssIO.str(); // 从stringBuf中获取内容
cout << "stringstream buffer:" << strBuf << endl; // ""
在使用stringstream流的时候需要注意,stringbuffer读取到最后的时候会被设置eofbit标志,可查看C++ library了解细节便于出错时快速的定位问题。通过stringstream流我们可以实现类型转换,使用模块封装类型的转换过程可提高编写代码的效率。封装是为了解决重复造轮子,我们有必要给自己造大量的轮子,以后就使用轮子组装我们的车子。
template<typename OutType, typename InType>
OutType ConvertType(const InType& src)
{
OutType dst;
stringstream ssIO;
ssIO << src;
ssIO >> dst;
return dst;
}
int nValue = ConvertType<int>("123");
cout << nValue << endl;
float fValue = ConvertType<float>("123.123123123");
cout << fValue << endl;
double lfValue = ConvertType<double>("123.123123123");
cout << lfValue << endl;
string strValue = ConvertType<string>(1234);
cout << strValue << endl;
通过模板封装使得代码更简洁了,不过对于数据的一些控制就减弱,比如float类型的精度long类型的进制控制。这些需要通过更好的封装方式才能达到,后续尝试封装下。
三、通过boost库中的模板方法lexical_cast进行转换#include <boost\lexical_cast.hpp> // 需要包含头文件才能使用
using boost::lexical_cast;
int nValue = lexical_cast<int>("123");
cout << nValue << endl;
float fValue = lexical_cast<float>("123.123123123");
cout << fValue << endl;
double lfValue = lexical_cast<double>("123.123123123");
cout << lfValue << endl;
string strValue = lexical_cast<string>(1234);
cout << strValue << endl;
lexical_cast和ConvertType封装的形式有点像,其实是因为lexical_cast内部也是对于输入输出流的封装。不过有大牛进行封装了,我们就可以省去自己造轮子。