数字转换成字符串,int 转换成const char*

来源:互联网 发布:波尔代热斯现象知乎 编辑:程序博客网 时间:2024/06/08 01:16
Question:将一个int类型转换成字符串。函数原型:
const char* itoa(int val)


负数前面要添个负号,正数不用。


写了15min……


const char* itoa(int val){    char* s=(char*)malloc(35);    if(!s) return NULL;    int sign=val&0x80000000;    if(sign) val=-val;    int len=0;    do{        s[len++]=val%10+'0';val/=10;    }while(val);    if(sign) s[len++]='-';    char* result=(char*)malloc(35);    if(!result) return NULL;    int i;    for(i=0;i<len;i++) result[i]=s[len-i-1];    return result;}

Q:你的int是多少位的?

A:(难道int不是都是32位的吗?)我的64位机上的int是32位的。

Q:你真的是按照32位来计算的吗?

(他把代码拿回来给我)

A:额。不是。差了4个0。(以前汇编写多了,都是16位寄存器,后遗症啊!)(注:当时我把0x80000000写成0x8000了)


Q:里面涉及到了负数转正数。请问int负数和整数的范围是一样的吗?

A:(啊!-2147483648取负还是它自己!边界值没考虑到!)……不一样。


在涉及到负数的求余操作时会有一些麻烦。所以应该使用它的绝对值。而求-2147483648的绝对值时,应该转换成unsigned int再求。为什么要用do while呢?用while的话,val初始值为0时,result就没输出了。

而且,不应该假设int是32位的。虽然现实如此。因为以前的int是16位的,而且未来的int可能不是32位的。


Q:你用了动态内存。请问这段内存应该由谁来释放呢?

A:(当然是)调用者。

Q:有没有不需要用户去管理的方法呢?

A:(内存泄漏!第一次深深地体验到了C/C++的不便啊。当我第一眼看到返回值时带const的时候,我就觉得怪怪的了)除非传一个字符串进来。

Q:假如不允许呢?

A:(函数内部申请的数组又不能返回,难道static?怎么可能!你坑我啊!)……


后来上网找到一个外国人的代码。它用了static char 数组。第一次发现还有这种用法的。涨知识了。还有十分简洁明了的result[i]="0123456789"[tempval%10];,非常容易改造成其他进制的。


const char* itoa1(int val){    static char result[sizeof(int)<<3+2];    unsigned int tempval=val;    if(val<0) tempval=-val;    int i=sizeof(int)<<3+1;    do{        result[i]="0123456789"[tempval%10];        tempval/=10;--i;    }while(tempval);    if(val<0) result[i--]='-';    return &result[i+1];}

这个才是比较好的。。。


还有更加简洁的。不得不感叹sprintf的强大。

const char* itoa2(int val){    static char result[sizeof(int)<<3+2];    sprintf(result,"%d",val);    return result;}

然而,自己写的效率是sprintf的2倍多。

完整代码如下:

#include<stdio.h>#include<stdlib.h>#include<limits.h>const char* itoa(int val){    char* s=(char*)malloc(35);    if(!s) return NULL;    int sign=val&0x80000000;    if(sign) val=-val;    int len=0;    do{        s[len++]=val%10+'0';val/=10;    }while(val);    if(sign) s[len++]='-';    char* result=(char*)malloc(35);    if(!result) return NULL;    int i;    for(i=0;i<len;i++) result[i]=s[len-i-1];    return result;}const char* itoa1(int val){    static char result[sizeof(int)<<3+2];    unsigned int tempval=val;    if(val<0) tempval=-val;    int i=sizeof(int)<<3+1;    do{        result[i]="0123456789"[tempval%10];        tempval/=10;--i;    }while(tempval);    if(val<0) result[i--]='-';    return &result[i+1];}const char* itoa2(int val){    static char result[sizeof(int)<<3+2];    sprintf(result,"%d",val);    return result;}int main(){    printf("%s\n",itoa(0));    printf("%s\n",itoa(-945638543));    printf("%s\n",itoa(INT_MIN));    printf("%s\n",itoa(INT_MAX));    printf("%s\n\n",itoa(2333));    printf("%s\n",itoa1(0));    printf("%s\n",itoa1(-945638543));    printf("%s\n",itoa1(INT_MIN));    printf("%s\n",itoa1(INT_MAX));    printf("%s\n\n",itoa1(23333));    printf("%s\n",itoa2(0));    printf("%s\n",itoa2(-945638543));    printf("%s\n",itoa2(INT_MIN));    printf("%s\n",itoa2(INT_MAX));    printf("%s\n\n",itoa2(223333));    //test itoa2's efficiency: 8.306s    //int i;    //for(i=0;i<100000000;i++) itoa2(i);    //test itoa1's efficiency: 3.514s    //int i;    //for(i=0;i<100000000;i++) itoa1(i);    return 0;}

输出:

0-945638543-./,),(-*,(214748364723330-945638543-21474836482147483647233330-945638543-21474836482147483647223333


0 0