这是一个字符串转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;
}