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