C语言为我们提供了数字和字符串之间的转换函数,这些函数有很多,常用的有:
整型数转字符串函数itoa():
char *itoa(int value,char *string,int radix);
//int value 被转换的整数,char *string 转换后储存的字符数组,int radix 转换进制数,如2,8,10,16 进制等
浮点数转字符串函数gcvt():
char *gcvt(double value, int ndigit, char *string);
//int value 被转换的浮点数,char *string 转换后存储的字符数组,int ndigit 有效位数
字符串转整型数函数atoi():
int atoi(const char *nptr);
//const char *nptr 字符串首地址,返回值为转换结果
double atof(const char *nptr);
//const char *nptr 字符串首地址,返回值为转换结果
下面通过一组测试用例说明几个函数的使用方法
#include
#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(): "<
在笔试面试过程中,用人单位可能要求我们自己实现这些转换函数,考虑到复杂度,在这里我们只实现整型数和字符串之间的转换函数。当然,代码不是重点,重点是解决问题的思路。
自己的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;
}
实现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. 递归向上传参数用引用或二级指针,用入口函数隔离实参
能力有限,如有问题,欢迎各位大神批评指正!