c语言字符串转数字

这是一个字符串转int的函数(libc 有同类函数strtol系列)

这虽然是个玩具函数,但在设计之初确定了如下目标:


1.函数原型模仿strtol,但是去掉strtol第二个参数

int str2int(char *str, int base); //玩具函数原型

long strtol(const char *restrict str, char **restrict endptr, int base);//libc库函数原型


2.扩展strtol函数(环境为mac libc)的进制猜测能力,当base为0时strtol函数会根据restric的前缀为0x推测为16进制,0为8进制,玩具函数加入0b前缀表示2进制


3.支持2-36之间的进制。例如:z是10进制中的35

4.支持负数

5.测试4个字节所能表示的最大值,最小值,包含2,8,10,16进制


code

#include <stdio.h>
#include <ctype.h>

/*
 * @param base 可以是0或者2-36之间的任意整数
 * 如果是0,函数会自己猜测要转的进制,如果str是以0x开头,等同base为16
 * 如果str是0b开头,等同base为2
 * 如果str是0开头,等同base为8
 */ 
int str2int(char *str, int base) {
    char sign;
    int rv = 0;
    char c;
    int newbase = -1;

    if ((base < 2 && base != 0) || base > 36)
        return 0;

    //跳过str开头的空白字符
    while(*str && isspace(*str))
        str++;

    //取得符号位
    sign = (*str == '-' || *str == '+') ? *str++ : '+';

    //猜测需要转换的类型
    if (*str == '0' && ++str) {
        if ((*str == 'x' || *str == 'X') && ++str) {
            newbase = 16;
        } else if ((*str == 'b' || *str == 'B') && ++str) {
            newbase = 2;
        } else {
            newbase = 8;
        }
    }

    //默认10进制
    if (base == 0) {
        base = newbase == -1 ? 10 : newbase;
    }

    //printf("base = %d:%s\n", base, str);
    for (;*str; str++) {
        //大写转小写
        c = *str | 0x20;
        if (c >= 'a' && c <= 'z') {
            rv = rv * base + c - 'a' + 10;
        } else if (c >= '0' && c <= '9') {
            rv = rv * base + c - '0';
        } else {
            break;
        }
        //printf("rv = %d\n", rv);
    }
    
    return sign == '-' ? -rv : rv;
}

#include <stdlib.h>
#include <limits.h>
#include <assert.h>
int main() {

    //test
    //==== max=====
    //2进制
    assert(str2int("0b11111111111111111111111111111111", 0) == 0xFFFFFFFF);
    printf("2 max:%x\n", str2int("0b11111111111111111111111111111111", 0));
    printf("2 max:%x\n", str2int("0b11111111111111111111111111111111", 2));

    assert(str2int("0777777777777", 0) == 0xFFFFFFFF);
    //8进制
    printf("8 max:%x\n", str2int("0777777777777", 0));
    printf("8 max:%u\n", str2int("0777777777777", 0));
    printf("8 max:%x\n", str2int("0777777777777", 8));
    printf("8 max:%u\n", str2int("0777777777777", 8));

    assert(str2int("4294967295", 0) == 0xFFFFFFFF);
    //10进制
    printf("10 max:%u\n", str2int("4294967295	", 0));
    printf("10 max:%u\n", str2int("4294967295	", 10));

    assert(str2int("0xffffffff", 0) == 0xFFFFFFFF);
    //16进制
    printf("16 max:%x\n", str2int("0xffffffff", 0));
    printf("16 max:%x\n", str2int("0XFFFFFFFf", 0));
    printf("16 max:%x\n", str2int("0xffffffff", 16));
    printf("16 max:%x\n", str2int("0XFFFFFFFf", 16));

    assert(str2int("0b10000000000000000000000000000000", 0) == 0x80000000);
    //=====min=====
    //2进制
    printf("2 min:%x\n", str2int("0b10000000000000000000000000000000", 0));
    printf("2 min:%x\n", str2int("0b10000000000000000000000000000000", 2));
    printf("2 min:%d\n", str2int("0b10000000000000000000000000000000", 0));
    printf("2 min:%d\n", str2int("0b10000000000000000000000000000000", 2));

    assert(str2int("020000000000", 0) == 0x80000000);
    //8进制
    printf("8 min:%d\n", str2int("020000000000", 8));
    printf("8 min:%d\n", str2int("020000000000", 0));
    printf("8 min:%x\n", str2int("020000000000", 8));
    printf("8 min:%x\n", str2int("020000000000", 8));

    //10进制
    printf("10 min:%d\n", str2int("-2147483648", 10));
    printf("10 min:%x\n", str2int("-2147483648", 10));

    //16进制
    printf("16 min:%d\n", str2int("0x80000000", 16));
    printf("16 min:%x\n", str2int("0x80000000", 16));

    //printf("%x", strtoul("-2147483648", NULL, ));
    //35进制
    printf("35:%d\n", str2int("z", 35));
    return 0;
}



你可能感兴趣的:(c语言字符串转数字)