数字与字符串之间的转换

来源:互联网 发布:ubuntu 下载器推荐 编辑:程序博客网 时间:2024/06/11 10:50

C语言为我们提供了数字和字符串之间的转换函数,这些函数有很多,常用的有:

整型数转字符串函数itoa():

<pre name="code" class="cpp"><span style="font-size:18px;">char *itoa(int value,char *string,int radix);//int value 被转换的整数,char *string 转换后储存的字符数组,int radix 转换进制数,如2,8,10,16 进制等</span>

浮点数转字符串函数gcvt():

char *gcvt(double value, int ndigit, char *string);//int value 被转换的浮点数,char *string 转换后存储的字符数组,int ndigit 有效位数
字符串转整型数函数atoi():

int atoi(const char *nptr);//const char *nptr 字符串首地址,返回值为转换结果

字符串转浮点数函数atof():

double atof(const char *nptr);//const char *nptr 字符串首地址,返回值为转换结果
下面通过一组测试用例说明几个函数的使用方法

#include <iostream>#include "stdlib.h"using namespace std;int main(){int i = -1234;double d = -1.23456;char *p_dst = new char[16];char *p_src1 = "-4321";char *p_src2 = "-4.321";//itoa()测试itoa(i, p_dst, 10);cout<<"itoa(): "<<p_dst<<endl;//gcvt()测试gcvt(d, 4, p_dst);cout<<"gcvt(): "<<p_dst<<endl;//atoi()测试i = atoi(p_src1);cout<<"atoi(): "<<i<<endl;//atof()测试d = atof(p_src2);cout<<"atof(): "<<d<<endl;system("pause");return 0;}
在笔试面试过程中,用人单位可能要求我们自己实现这些转换函数,考虑到复杂度,在这里我们只实现整型数和字符串之间的转换函数。当然,代码不是重点,重点是解决问题的思路。

自己的iToa()函数:

实现1:转换索引表的使用

char* itoa(int num,char *str,int radix){/*索引表*/char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";unsigned unum;/*中间变量*/int i=0,j,k;/*确定unum的值*/if(radix==10 && num<0)/*十进制负数*/{unum=(unsigned)-num;str[i++]='-';}else unum=(unsigned)num;/*其他情况*//*转换*/do{str[i++]=index[unum%(unsigned)radix];unum/=radix;}while(unum);str[i]='\0';/*逆序*/if(str[0]=='-')k=1;/*十进制负数*/else k=0;char temp;for(j=k;j<=(i-1)/2;j++){temp=str[j];str[j]=str[i-1+k-j];str[i-1+k-j]=temp;}return str;}

这份代码是百度百科上的实现,完全实现了标准itoa函数的功能。采用的是一般的临时字符串加翻转的方法,这里逻辑并不是很复杂,值得学习的地方索引表的使用。一般的转换过程,比如字符数字与整型数字之间、大小写字母之间的转换,其转换规则都是固定的,都可以利用加减一个字符的方法实现。但此处由于ASCII表中9和A并没有相邻,所以会存在两种转换规则。这时候可以采用转换索引表的方法,人工组织一个转换规则。转换表的构造非常灵活,可以满足各种各样的转换规则。

实现2:递归算法中的引用与非引用

static void do_iToa(int i, char* &a){//功能:将整形数字转换为字符串//说明:要求字符串内存已分配//传引用以保证递归退出时指针正确偏移if(i < 0){*a = '-';do_iToa(-1*i, ++a);return;}if(i == 0){return;}else{char tmp_c = i%10 + '0';do_iToa(i/10, a);*a = tmp_c;a++;}}void iToa(int i, char* a){//功能:将整型数转换为字符串//说明:调用递归子函数完成转换,添加'\0'//传值以保证实参指针不发生变化//负责指针非空判断if(a==NULL){return;}do_iToa(i, a);*a = '\0';}
这份代码是本人自己实现的,没有采用上面的临时字符串加翻转的方法,而是采用了递归。在实现过程的主要问题是参数a的向上传递,由于无法事先得知数字长度,所以利用递归过程中的临时变量将其一个一个存储起来,但a所指位置是和长度有关的。所以在递归过程中a的移动规则是不能确定的,只有在递归返回时才可以移动a,但这就要求a的改变必须可以向上层函数传递,否则只是改变了下层a的值,上层的a无法移动就会造成错误。

解决办法就是采用指针引用或者二级指针了,但这样又会改变实参值,导致调用完iToa()后指针参数改变,这对使用者来说简直是一场噩梦,这里采用的方法是中间加一层传值函数,以此来隔离实参。

由于转换长度有限,这种递归貌似有华而不实的嫌疑甚至可能会弄巧成拙,因为递归本身的调用时间很可能会比那个常数项因子更费时间。但这种设计思路还是值得学习的,一是利用引用向上传递参数变化,而是利用入口函数传值隔离实参。

自己的aToi()函数:

这个函数不存在“回溯”的过程,可以用一次遍历来解决问题。

int aToi(char *a){//功能:将字符串转换为整数//说明:字符串可以带"+"、"-"号,默认为正数int res = 0;int flag = 1;if(*a == '-'){flag = -1;a++;}if(*a == '+'){a++;}while(*a != '\0'){res *= 10;res += *a-'0';a++;}return res*flag;}

最后总结一下:

1. C库函数itoa()、gcvt()、atoi()、atof()的使用方法

2. 转换表解决问题的思路

3. 递归向上传参数用引用或二级指针,用入口函数隔离实参

能力有限,如有问题,欢迎各位大神批评指正!

2 0