C++中的数据类型转换方法总结

C++数据类型转换(全) 当我们用C++编写代码时,经常会遇到数据类型的转换,如string,char*,char[],const char*、Qstring以及int,float等各种类型之间的转换。而且有些转换的函数在低版本的C++中是不支持的,所幸这里我们对C++中常用的数据类型转换进行记录。在数据转换中,尤其是字符串转换是最常用的,所以我们以字符串来作为整个数据类型转换的核心。 阅读详情

C++中的数据类型转换方法总结

摘要:本文总结了C/C++中的多种数据类型转换方法,并比较了各自的优劣。给出了推荐的使用建议。

从int到char*,或者反过来从char*到int,在C/C++中到底有多少种转换方法呢?符合标准的大概有四种。即C数据转换函数族、sprintf/snprintf/sscanf函数族、字符串流std::stringstream、std::strsteam。不符合标准却又广为使用的包括CString和boost::lexical_cast。本文只讨论符合标准的转换方法,其中std::strstream由于已经被C++标准委员为指定为不推荐使用的(deprecated),所以不予考虑了。下面重点讨论三种标准转换方法之间的优劣。源代码的地址是:http://download.csdn.net/source/631475

1.      Int和char*或std::string之间的转换
C数据转换函数族
C数据转换函数族即包括itoa、atoi等数据类型转换函数在内的一大批C函数,在C语言时代曾经被大量使用。源代码如下:

  int i = 10;

  char szBuf[10] = "";

 

  itoa(i, szBuf, 10);

  cout<<"itoa: szBuf = "<<szBuf<<endl;

  i = 0;

  i = atoi(szBuf);

  cout<<"atoi: i = "<<i<<endl;

使用还是比较简单的。一个最大的问题是:没有进行char*的越界检查,可能会造成数组溢出。

snprintf/sscanf
sprintf是用来格式化字符串的一个C函数,sscanf则是从字符串中读取值的一个C函数。由于Herb Sutter(Exceptional C++系列著作的作者)教导我们“永远也不要使用sprintf”,所以这里我们只使用snprintf。由于snprintf进入C标准较晚,所以在你的编译器中也许只能使用非标准的_snprintf(例如我的VC6平台)。源代码如下:

  int i = 20;

  char szBuf[10] = "";

  memset(szBuf, 0, sizeof(szBuf));

  _snprintf(szBuf, sizeof(szBuf), "%d", i);

  cout<<"_snprintf: szBuf = "<<szBuf<<endl;

  i = 0;

  sscanf(szBuf,"%d",&i);

  cout<<"sscanf: i = "<<i<<endl;

使用很简单,而且,似乎没有什么内存泄露或者数组越界。

std::stringstream
对流很熟悉的人可能会更快适应std::stringstream的解决方案:

  #include <sstream>

using namespace std;

int i = 30;

string strRel;

  ostringstream oss;

  oss<<i;

  strRel = oss.str();

  cout<<"ostringstream: strRel = "<<strRel<<endl;

  i = 0;

  istringstream iss(strRel);

  iss>>i;

  cout<<"istringstream: i = "<<i<<endl;

使用较为复杂,而且,还使用了两个临时变量oss和iss,这必然带来性能上的开销。

2.      double和char*或std::string之间的转换
1.

C数据转换函数族
当开始进行double和char*之间的转换时,C数据转换函数的缺点暴露无疑。先看源代码:

  double d = 3.1415926;

  char szBuf[18] = "";

  _gcvt(d, 9, szBuf);

  cout<<"_gcvt: szBuf = "<<szBuf<<endl;

  d = 0;

  char* stopstring;

  d = strtod(szBuf, &stopstring);

  cout<<"strtod: d = "<<d<<endl;

首先转换函数的名字就让人大吃一惊,与itoa对应的不是我们想象的dtoa,而是_gcvt,而与atoi对应的是strtod。其次它们的参数很奇怪,没有msdn是不可能明白的。其次,数组越界依然存在。至此我想我们可以抛弃这组函数了。当然,更加无奈的理由在后面。

snprintf/sscanf
snprintf/sscanf表现不错,源代码如下:

  double d = 3.1415926;

  char szBuf[18] = "";

  memset(szBuf, 0, sizeof(szBuf));

  _snprintf(szBuf, sizeof(szBuf), "%f", d);

  cout<<"sprintf: szBuf = "<<szBuf<<endl;

  sscanf(szBuf, "%f", &d);

  cout<<"sscanf: d = "<<d<<endl;

很好,很强大!

std::stringstream
std::stringstream的代码似乎没有任何改动,除了一个int类型改成了double类型:

  double d = 9.1415926;

   string strRel;

  ostringstream oss;

  oss<<d;

  strRel = oss.str();

  cout<<"ostringstream: strRel = "<<strRel<<endl;

  d = 0;

  istringstream iss(strRel);

  iss>>d;

  cout<<"istringstream: d = "<<d<<endl;

写到这里,我似乎看到模板函数在向我招手。

3.      复杂的转换
考虑一个经典的场景,从一个int,一个double和一个string中读出值,然后拼凑为一个输出的字符串。最后,从这个字符串中再将这几个值读出来。

C数据转换函数族
直接看代码:

  int iAge = 25;

  float fPayment = 3.25;

  string strName ="Wang";

  char szBuf[100] = "";

  char szTemp[100];

  strcpy(szBuf,"Age= ");

  itoa(iAge, szTemp, 10);

  strcat(szBuf, szTemp);

  strcat(szBuf," ,Payment= ");

    _gcvt(fPayment, 4, szTemp);

  strcat(szBuf,szTemp);

  strcat(szBuf," ,Name= ");

  strcat(szBuf, strName.c_str());

  cout<<"szBuf = "<<szBuf<<endl;

以上代码的表现真是惨不忍睹,费了几鼻子的劲好歹是转为目标字符串了。转换回来的代码也没有写。也许有,不过那个复杂程度,我看还是算了。而且,strcpy、strcat和几个转换函数都是危险的API,不检查越界的。

snprintf/sscanf
主要看看sscanf的表现:

  int iAge = 25;

  float fPayment = 3.25;

  string strName ="Wang";

  char szBuf[100] = "";

  memset(szBuf, 0, sizeof(szBuf));

  _snprintf(szBuf, sizeof(szBuf), "Age = %d, Payment = %f, Name = %s",iAge,fPayment,strName.c_str());

  cout<<"sprintf: szBuf = "<<szBuf<<endl;

  iAge = 0;

  fPayment = 0.0;

  memset(szTemp, 0, sizeof(szTemp));

  sscanf(szBuf,"Age = %d, Payment = %f, Name = %s",&iAge,&fPayment,&szTemp);

  strName = szTemp;

  cout<<"sscanf: Age = "<<iAge<<",Payment="<<fPayment<<",name="<<strName<<endl;

snprintf表现还是一如既往的强大。sscanf的表现简直就是perfect,但是要注意,sscanf的样式字符串一定要和snprintf中的样式字符串一模一样,否则其后果是不可预计的。例如,我稍微改动了几个字符,最后的strname就读取错误了。

std::stringstream
std::stringstream的代码很长很长:

  int iAge = 25;

  float fPayment = 3.25;

  string strName ="Wang";

string strRel;

  ostringstream oss;

  oss<<"Age = "<<iAge<<", Payment = "<<fPayment<<", Name = "<<strName;

  strRel = oss.str();

  cout<<"ostringstream: strRel = "<<strRel<<endl;

  iAge = 0;

  fPayment = 0.0;

  strName = "";

  istringstream iss(strRel);

  string strTemp;

  iss>>strTemp>>strTemp>>iAge>>strTemp>>strTemp>>strTemp>>fPayment

     >>strTemp>>strTemp>>strTemp>>strName;

 

  cout<<"istringstream: Age = "<<iAge<<",Payment="<<fPayment<<",name="<<strName<<endl;

ostringstream的表现还是不错的,比snprintf毫不逊色,甚至更好一点,因为它不用记样式符。但是看到istringstream的这几行代码,估计大部分人要吐血了:

  string strTemp;

  iss>>strTemp>>strTemp>>iAge>>strTemp>>strTemp>>strTemp>>fPayment

     >>strTemp>>strTemp>>strTemp>>strName;

为什么中间有那么多strTemp?因为每当istringstream每当遇到由一个空格或者非数字字符包围的字符串时就必须输入到一个string中,因此例如“,”或者“=”都必须占用一个string来输入。总之,当字符串很复杂时,很麻烦。

4.      小结
从易用性、安全性和效率三个方面来考察以上方法。

易用性按从好到坏排列依次是:snprintf/sscanf、std::stringstream、C数据转换函数族。

安全性按从好到坏排列依次是:std::stringstream、snprintf/sscnaf、C数据转换函数族。

效率按从好到坏排列依次是:snprintf/sscanf、C数据转换函数族、std::stringstream。

到此我们可以抛弃C数据转换函数族了,接下来从其他方面来考察剩下的方法。

5.      模板函数
考虑写一个从任何内置数据类型到字符串的转换函数。此时只能使用std::stringstream了。

template<typename T> string to_str(T val)

{

  ostringstream oss;

  oss<<val;

  return oss.str();

}

  string strFromInt = to_str(10);

  cout<<strFromInt<<endl;

  string strFromDouble = to_str(3.1415926);

  cout<<strFromDouble<<endl;

换句话说,也就是std::stringstream是类型安全的,而snprintf不是。

6.      精度和格式
前面的例子都忽略了精度,事实上要进行精度和格式的设置,snprintf和std::stringstream的学习时间是差不多的。这里就不一一叙述了。

7.      再谈安全性
snprintf是安全的,因为它会检查数组越界并阻止这种行为。但是当目标字符数组长度小于需求时,其结果是不正确的。sscanf也是同样,当它的样式字符串不匹配时,其结果是未知的。

std::stringstream是更安全的。由于它采用了内存自动管理机制。无论在任何时候,只要它没有抛出异常,其结果总是正确的。

8.      总结
在易用性和效率方面,snprintf/sscanf都比std::stringstream强,因此只要程序员能够保证目标字符数组长度够用时,都可以放心使用snprintf。sscanf也是同理,只要程序员保证其样式字符串正确,其结果也总是正确的。

而std::stringstream的最大优点是具有模板亲和力,可以用于泛型编程。在效率不是很重要的情况下,建议使用std::stringstream。若你是一位非常谨慎的程序员,建议你总是使用std::stringstream,因为它是最安全的


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wxb_nudt/archive/2008/09/16/2938242.aspx

C++)的数据类型转换 C语言类型 隐式----自动转换 char a = 'a'; int b = a; 显示---强制转换 ---- () ----不管目标类型是什么,都可以将源类型转换过去,属于比较暴力行为 int a = 100; char b = (char)a; C++,除了继承C语言中的类型转换之外(不推荐),还提供四种类型转换方式 static_cast 静态类型转换,它大多数情况下,跟C语言类型转换差不多 reinterpret_cast 重新解释强制类型转换,一般指针使用 dynami 阅读详情

相关推荐

C++的类型转换

c++类型转换

rayn的专栏 3435

C/C++数据类型转换详解

自动类型转换常被称为隐式类型转换,强制类型转换常被称为显示类型转换,强制类型转换的一般形式为(类型标识符)(操作数)或(类型标识符)(表达式)。其功能就是把操作数或表达式结果的数据类型暂时地强制转换为圆括号()中的类型。

weixin_44049823的博客 6977

掌握C++类型转换:static_cast、const_cast、dynamic_cast 和 reinterpret_cast

静态类型转换静态类型转换是最常用的类型转换方式,它可以将一种类型的数据强制转换为另一种类型,但需要注意的是,这种转换可能会损失一些信息,因此在进行此类转换时应当谨慎。int a = 10;动态类型转换动态类型转换主要用于多态类型之间的转换,它可以将基类指针或引用转换为派生类指针或引用。如果进行非法的类型转换,动态类型转换会返回一个空指针。重新解释类型转换。

Lion_Long的博客 6376

vc6c语言int转char数组,C++中的数据类型转换方法

摘要:本文总结了C/C++中的多种数据类型转换方法,并比较了各自的优劣。给出了推荐的使用建议。从int到char*,或者反过来从char*到int,在C/C++中到底有多少种转换方法呢?符合标准的大概有四种。即C数据转换函数族、sprintf/snprintf/sscanf函数族、字符串流std::stringstream、std::strsteam。不符合标准却又广为使用的包括CString和b...

weixin_30120827的博客 1211

通读《C++ primer plus》— C++中的5种数据类型转换方式

通读《C++ primer plus》—记录一 C++中的5种数据类型转换方式 1、始化和赋值时转换 比如 int a=1; long b=2147483647; a=b; 上面的代码并不会有问题,。然而将a更改为float类型,将会出现错误。 需要注意的一种情况是: 把0赋值给bool类型变...

choucong1919的博客 179

C++中各种数据类型之间的转换

C++中各种数据类型之间的转换:1.int 转 string: 1.使用sstream 编程: #include <sstream> #include <string> #include <iostream> using namespace std;

Jerry Lee の blog 1762

C++自学笔记33(数据类型总结与变量)

数据类型总结、变量区别

weixin_64418869的博客 1398

C#和C++数据类型对应表

/C++中的DLL函数原型为         //extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsigned char* 变量名2)         //extern "C" __declspec(dllexport) bool 方法名二(const unsigned char* 变量名1, char* 变量名2)

Stay hungry,stay foolish 789

C#与C++数据类型比较及结构体转换[整理]

C#与C++数据类型比较及结构体转换[整理] //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byte(unsigned char) ---- c#:System.Byte //c++:SHORT(short) ...

aboklh的博客 608

C++基本数据类型及类型转换

http://blog.csdn.net/pipisorry/article/details/25346379 c++基本数据类型 什么样的数据算是byte类型,int类型,float类型,double类型,long类型? byte类型,就是字符类型.这类数据是字符组成的 INT 类型,为整型数字,不同语言定义的范围不同 FLOAT,为数字浮点型,其小数点后面可以跟N个数字 D

皮皮blog 1万+

C++常用数据类型转换的区别

C++常用数据类型转换的区别,static_cast 、dynamic_cast、const_cast、 reinterpret_cast的使用方法以及区别。

CC_clear的博客 784

浅议C/C++数据类型转换

浅议C/C++数据类型转换 一、 何为数据类型 在C语言版的数据结构中我们就学过,数据类型表达了一个值的集合以及定义在这个值集上的一组操作的总称。每一种不同的数据类型都有各自不同的操作从而实现不同的功能。 比如在整形int上面就定义了一些列操作+,-,*,/,%等,并且经过计算后结果还是整形(数据类型值的封闭性)。在字符串string上定义了strcat,strcpy等操...

weixin_34015860的博客 79
上一篇: Socket编程指南及示例程序
下一篇: 关于原始输入--XP中的新技术
dylanlrp
博客等级 码龄19年 23粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值