simple_strtoul函数简介

Linux内核中提供的一些字符串转换函数:

lib/vsprintf.c

 1. unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)    
 2. unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)    
 3. long simple_strtol(const char *cp, char **endp, unsigned int base)    
 4. long long simple_strtoll(const char *cp, char **endp, unsigned int base)    
 5. int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)    
 6. int strict_strtol(const char *cp, unsigned int base, long *res)    
 7. int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)    
 8. int strict_strtoll(const char *cp, unsigned int base, long long *res)    
 9. int sprintf(char *buf, const char *fmt, ...)    
10. int snprintf(char *buf, size_t size, const char *fmt, ...)    
11. int sscanf(const char *buf, const char *fmt, ...)   

unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)

功能:将一个字符串转换成unsigend long型数据。

返回:返回转换后数据。

参数:cp指向字符串的开始,endp指向分析的字符串末尾的位置,base为要用的基数(进制数),base为0表示通过cp来自动判断基数,函数自动可识别的基数:‘0x’表示16进制,‘0’表示8进制,其它都认定为10进制。函数可转换成数字的有效字符为:[0,f]。举例:cp = “0x12str”,base = 0,则返回unsigned long long为18,*endp = “str”。 参数下同。

unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
{
    unsigned long result = 0,value;
    //对于base,首先如果*cp以0x开头且下来是数字,则一定为16进制。然后如果用户指定了一个非0的进制,则
    //遵循用户输入的进制。如果用户输入了0进制,则根据是否0开头来确定是8进制还是10进制
    if (*cp == '0') {
        cp++;
        if ((*cp == 'x') && isxdigit(cp[1])) {
           base = 16;    //如果cp是0x开头的,下面一个又是数字,那么base一定为16。
           cp++;            //此时即使用户输入了一个base,也忽略这个base而强制其为16。
        }
        if (!base) {
            base = 8;    //如果用户输入base为0,cp是0开头,接下来不是x,那么强制为8进制
        }                        
    }
    if (!base) {
        base = 10;    //如果用户输入base为0,cp是非0开头,则使用10进制。
    }
    //while循环里value<base是精髓所在。这个解析停止的条件不能是null,而应该是str中
    //第一个不是数字的字母。这个字母的范围取决于base,譬如如果是16进制那么f也算是数字。
    //而如果是8进制那么9都不算是数字了。因此解析结束的范围只能和base比较来限定。
    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
        ? toupper(*cp) : *cp)-'A'+10) < base) {
        result = result*base + value;
        cp++;
    }
    if (endp)                          //此处if判断的作用是:用户在使用这个函数时,如果不关心endp则可以直接
        *endp = (char *)cp;    //使用null,而不必担心程序运行会出错。这种处理技巧很实用,用户可以
        return result;              //自行决定是否使用这个函数提供的参数式返回值。
}

此函数有以下几点值得注意:

  1. 第一个参数中的const。一般在函数的形参中,如果我们只是希望调用者使用该参数,而不会去改变该参数内容(一般是指针指向的内容),则可以声明为const。
  2. 第二个参数。C语言中函数只能有一个返回值,但是有时候我们希望从函数中得到不止一个返回内容怎么办呢?只能通过参数了。一般的参数是用来向函数输入信息的,但是指针型参数可以间接用来从函数输出信息。使用时用户只需传入一个相应的指针,函数中会把需要输出的信息地址传给这个指针,这样在函数调用完成后,用户即可到endp指针处去取函数传出的值了。这就是用参数实现返回值的方式。但是要注意,在函数中千万不可把局部变量的地址传给输出型指针,因为局部变量存在栈里,函数调用结束后即释放了,传出的指针指向的内容是栈上已经被释放的部分,因此是无效的。(PS:高级语言中譬如C#有ref,out关键字,以明确指明该引用为输出型)
  3. 第三个参数base。要注意这个base的机制,本函数中是按照这样的理念来设计的。即如果str中有0x开头且接下来是数字则忽略用户调用时输入的base,强制为16进制。如果str不是上面情况然后才看用户输入的base。用户输入非0则使用用户指定的base,若用户输入0则自动判断是8进制还是10进制。
  4. 注意if(endp)这里,在输出型参数使用中,函数内首先判断endp是否为NULL,并以此来决定是否输出这个机制来自于一个理念:这个输出参数有可能是用户关注的,也有可能是用户不在意的。这样处理可以给用户自由,即用户如果在意就传一个有效指针过来接收;如果不在意调用时直接给个NULL就行。提供服务但不强迫,这样很好。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值