文档章节

c语言数字转字符串

guonaihong
 guonaihong
发布于 2015/09/08 08:10
字数 952
阅读 135
收藏 2

对下面代码的一些细节,解释下为什么那么做。

1. 

char buf[sizeof(int) * 8 + 1] = "";

这个buf的作用是缓存中间结果,长度没有写死。好处是不同的平台上这段代码都可以执行。

2.

if (base < 2 || base > 36)

该判断检查用户传入的进制数是否合法。base < 2 主要过滤负数和0和1。base > 36的意义是在超过10进制的数里,是用字母a表示10的。以此类推z可以表示36。在只使用ascii字符表示大于10的数时,最大的表示值是36,超过这个值就不能表示。

3.

uval = -val;

这各写法可以避免一个潜在的坑。当val为int值为INT_MIN时 -val会溢出。表象为-val 的值还是INT_MIN,还是个负数

4.至于为什么用一个无符号整数与一个>0的int进行整除与取余

uval % base
uval /= base

因为c语言的标准里没有规定x / y当有一个值为负数时,结果该向x坐标轴的左侧靠近(向0取整) 还是向侧靠近(负无穷)

它只规定了 (x / y) * y + (x % y) = x 

-14 /5 的结果可以是 -2 或者 -3

至为正数为啥没有两个结果。本人只是用了几个值进行了验证。。


好了贴代码:

#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <string.h>

char *int2str(int val, char *str, int base) {
    static char tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    char buf[sizeof(int) * 8 + 1 + 1] = "";
    char *p = buf;
    char *p2 = str;
    unsigned uval = val;

    //检查base的范围
    if (base < 2 || base > 36) {
        *str = '\0';
        return str;
    }

    //负数
    uval = val;
    if (val < 0 && base == 10) {
        uval = -val;
    }

    do {
        *p++ = tab[uval % base];
        //printf("%d:%d:%d\n", uval, uval % base, base);
    } while (uval /= base);

    if (val < 0 && base == 10) {
        *p++ = '-';
    }

    p--;
    while (p >= buf && (*p2++ = *p) != '\0')
        p--;
    *p2 = '\0';

    return str;
}

void tst_max_2() {
    char buf_int2str[34] = "";
    printf("max 2#%s\n", int2str(CHAR_MAX, buf_int2str, 2));

    printf("max 2#%s\n", int2str(SHRT_MAX, buf_int2str, 2));

    printf("max 2#%s\n", int2str(INT_MAX, buf_int2str, 2));
}

void tst_max_8() {
    char buf_int2str[34] = "";
    printf("max 8#%s\n", int2str(CHAR_MAX, buf_int2str, 8));

    printf("max 8#%s\n", int2str(SHRT_MAX, buf_int2str, 8));

    printf("max 8#%s\n", int2str(INT_MAX, buf_int2str, 8));

}

void tst_max_10() {
    char buf_int2str[34] = "";
    char buf_snprintf[34] = "";

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", CHAR_MAX);
    assert(!strcmp(int2str(CHAR_MAX, buf_int2str, 10), buf_snprintf));

    printf("max 10#%d:%s:%s\n", CHAR_MAX, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", SHRT_MAX);
    assert(!strcmp(int2str(SHRT_MAX, buf_int2str, 10), buf_snprintf));
    printf("max 10#%d:%s:%s\n", SHRT_MAX, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", INT_MAX);
    assert(!strcmp(int2str(INT_MAX, buf_int2str, 10), buf_snprintf));
    printf("max 10#%d:%s:%s\n", INT_MAX, buf_int2str, buf_snprintf);
}

void tst_max_16() {
    char buf_int2str[34] = "";
    char buf_snprintf[34] = "";
    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", CHAR_MAX);
    assert(!strcmp(int2str(CHAR_MAX, buf_int2str, 16), buf_snprintf));
    printf("max 16#%d:%s:%s\n", CHAR_MAX, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", SHRT_MAX);
    assert(!strcmp(int2str(SHRT_MAX, buf_int2str, 16), buf_snprintf));
    printf("max 16#%d:%s:%s\n", SHRT_MAX, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", INT_MAX);
    assert(!strcmp(int2str(INT_MAX, buf_int2str, 16), buf_snprintf));
    printf("max 16#%d:%s:%s\n", INT_MAX, buf_int2str, buf_snprintf);
}

void tst_min_2() {
    char buf_int2str[34] = "";
    printf("min 2#%s\n", int2str(CHAR_MIN, buf_int2str, 2));

    printf("min 2#%s\n", int2str(SHRT_MIN, buf_int2str, 2));

    printf("min 2#%s\n", int2str(INT_MIN, buf_int2str, 2));
}

void tst_min_8() {
    char buf_int2str[34] = "";
    printf("min 8#%s\n", int2str(CHAR_MIN, buf_int2str, 8));

    printf("min 8#%s\n", int2str(SHRT_MIN, buf_int2str, 8));

    printf("min 8#%s\n", int2str(INT_MIN, buf_int2str, 8));
}

void tst_min_10() {
    char buf_int2str[34] = "";
    char buf_snprintf[34] = "";
    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", CHAR_MIN);
    assert(!strcmp(int2str(CHAR_MIN, buf_int2str, 10), buf_snprintf));
    printf("min 10#%d:%s:%s\n", CHAR_MIN, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", SHRT_MIN);
    assert(!strcmp(int2str(SHRT_MIN, buf_int2str, 10), buf_snprintf));
    printf("min 10#%d:%s:%s\n", SHRT_MIN, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%d", INT_MIN);
    assert(!strcmp(int2str(INT_MIN, buf_int2str, 10), buf_snprintf));
    printf("min 10#%d:%s:%s\n", INT_MIN, buf_int2str, buf_snprintf);
}

void tst_min_16() {
    char buf_int2str[34] = "";
    char buf_snprintf[34] = "";

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", CHAR_MIN);
    assert(!strcmp(int2str(CHAR_MIN, buf_int2str, 16), buf_snprintf));
    printf("min 16#%d:%s:%s\n", CHAR_MIN, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", SHRT_MIN);
    assert(!strcmp(int2str(SHRT_MIN, buf_int2str, 16), buf_snprintf));
    printf("min 16#%d:%s:%s\n", SHRT_MIN, buf_int2str, buf_snprintf);

    snprintf(buf_snprintf, sizeof(buf_snprintf), "%x", INT_MIN);
    assert(!strcmp(int2str(INT_MIN, buf_int2str, 16), buf_snprintf));
    printf("min 16#%d:%s:%s\n", INT_MIN, buf_int2str, buf_snprintf);
}

void tst_0() {
    char buf_int2str[34] = "";
    int2str(0, buf_int2str, 16);
    printf("0 #%s\n", buf_int2str);
}

int main() {
    tst_max_2();
    tst_max_8();
    tst_max_10();
    tst_max_16();

    tst_min_2();
    tst_min_8();
    tst_min_10();
    tst_min_16();

    tst_0();
#if 0
    int val = INT_MIN;
    printf("##%d:%d:%u\n", val, -val, -val);
    //printf("%d:%d:%u\n", INT_MIN, -INT_MIN, -INT_MIN);
#endif
    return 0;
}


© 著作权归作者所有

共有 人打赏支持
guonaihong
粉丝 4
博文 76
码字总数 23503
作品 0
徐汇
程序员
私信 提问
GNU C和ANSI C函数库的区别

glibc和libc都是Linux下的C函数库, libc是Linux下的ANSI C的函数库; glibc是Linux下的GUN C的函数库; ANSI C和GNU C有什么区别呢? ANSI C是基本的C语言函数库,包含了C语言最基本的库函数...

新年
2014/12/19
0
0
汇编总结:无符号除法,有符号除法,取余,无符号乘法,有符号乘法指令

本文分为3个模块。 示例---该指令的示例 解释---为指令不好理解的地方 练习---为了更熟悉该指令 1.1 有符号除法指令及取余example: 在c语言里要完成 8 / 2的汇编指令如下: 在c语言里要完成 ...

guonaihong
2015/10/07
988
0
STM32开发 -- 进制与字符串间的转换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29350001/article/details/82117432 上一篇文章最后留下一个任务,字符串函数和进制间转换、进制和字符串间...

聚优致成
2018/08/27
0
0
PHP 变量及常量

一、PHP5.4的基本语法格式 1、PHP的分割符 $php=true; //分号结束语句 ?> 2、PHP注释与语法标识 (1)、单行注释 // 来源于C++的注释 # 来源于C语言的注释 (2)、多行注释 / / 来源于C语言的...

ufo00001
2017/06/27
0
0
超有用函数:字符串转整型数组函数分析

众所周知,C语言中并没有字符串变量,只能用字符型数组表示,这或多或少的会有一些trouble,但是,对于字符串转整型数组来说,其实没有多大影响,下面看一下这个函数的流程图: 看完这个流程...

材大难为用
2017/11/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

第11章 多线程

程序、进程、线程 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程或是正在运行的一个程序。动...

流小文
9分钟前
0
0
SpringBoot引入第三方jar包或本地jar包的处理方式

在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 - 第一种是将本地jar包安装在本地maven库 - 第二种是将本地j...

独钓渔
今天
2
0
五、MyBatis缓存

一、MyBatis缓存介绍 缓存的使用可以明显的加快访问数据速度,提升程序处理性能,生活和工作中,使用缓存的地方很多。在开发过程中,从前端-->后端-->数据库等都涉及到缓存。MyBatis作为数据...

yangjianzhou
今天
2
0
最近研究如何加速UI界面开发,有点感觉了

最近在开发JFinal学院的JBolt开发平台,后端没啥说的,做各种极简使用的封装,开发者上手直接使用。 JBolt开发平台包含常用的用户、角色、权限、字典、全局配置、缓存、增删改查完整模块、电...

山东-小木
今天
3
0
《月亮与六便士》的读后感作文3000字

《月亮与六便士》的读后感作文3000字: 看完英国作家威廉.萨默塞特.毛姆所著《月亮与六便士》(李继宏译),第一疑问就是全书即没提到“月亮”,也没提到“六便士”。那这书名又与内容有什么...

原创小博客
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部