atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数,应用在计算机程序和办公软件中。int atoi(const char *nptr) 函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0 。特别注意,该函数要求被转换的字符串是按十进制数理解的。atoi输入的字符串对应数字存在大小限制(与int类型大小有关),若其过大可能报错-1。
那么简单来说atoi函数就是将一个字符串转换为整形的一个函数,他是由系统直接给定
那么我们要自己实现一个atoi函数应该如何实现
首先考虑最简单的情况,用字符串数储存一个正数整形,然后运行结果就会输出整形数字,那么我们要理解其中原理,首先是字符串变量中的1~9与整形变量的1~9相差48,然后我们的思路是获取到字符串中数字的每一位,然后得到整形的每一位再按照对于位置相加即可
这里是函数体的基本功能
int getnegative(const char* str) { assert(*str != NULL); int num1 = 0; while (*str != ' ') { if (*str == '-') { num1++; } str++; } return num1; } if (isdigit(*str)) { res += (*str - 48) * (int)pow(10, (count - 1)); count--; str++; }
其中的isdigit是判断是否为数字的函数,在头文件#include
那么接下来的改进我们就要针对一特殊情况
当遇到第一字符就是字母的时候,直接输出零
在遇到空格和加号的时候就继续运行程序
在遇到负号的时候统计负号的个数,为偶数就输出数据,为奇数就输出数据的相反数
那么我们将这些实现之得到最终代码
int GetBit(const char* str) { int bit = 0; while (*str != ' ') { if (isdigit(*str)) { bit++; } else if (isblank(*str) || *str == '-' || *str == '+') { str++; continue; } else { break; } str++; } return bit; } int my_atoi(const char* str) { //"---123" int bit = GetBit(str); //3 int result = 0; int flag = 1; while (*str != ' ') { if (*str == '-') { flag *= -1; } else if (*str == '+' || *str == ' ') { str++; continue; } else { result += (*str - '0') * (int)pow(10, --bit); } str++; } return result*flag; } int main() { int res = my_atoi("123abc4567"); printf("%dn",res);
在统计数字位数时,我们也是只统计字母的前面的数字字符
itoa函数itoa 为c语言的一个函数。itoa 函数是一个广泛应用的,从非标准扩展到标准的C语言。它不能被移植,因为它不是标准定义下的C语言,但是,编译器通常在一个不遵循程式标准的模式下允许其通过header ,因为它是一个从逻辑对应到标准库的函数。itoa 取整数输入值,并将其转换为相应进制数字的字符串。
系统给定的有固定的参数
char *itoa( int value, char *string,int radix);
原型说明:
value:欲转换的数据。
string:目标字符串的地址。
radix:转换后的进制数,可以是10进制、16进制等。
那么我们也会遇到这类问题
我们先只关注简单的正数字符串,我们的想法是对radix取余,然后在对原数据除radix,这样循环下去我们就会得到反向的数据,即123放入itoa函数实现之后在这一步之后就会得到321,然后我们在对这个字符串逆转,这里可以看到3个数据我们只需要逆转一次
for (int j = 0; j < (index + 1) / 2; j++) { //-321 321 int temp = buff[j+flag]; buff[j+flag] = buff[index - j-1]; buff[index - j-1] = temp;
这里就可以得到逆转函数,然后我们再获取到获取位数的函数体
left = unsigned_value % radix; //余数存放buff合适位置存放 buff[index++] = temp[left]; //-321 unsigned_value /= radix;
其次我们再为得到的数字赋值时我们这里采用查表法,就是提前建立一个表格存储数据,这就可以降低代码运行的时间
const char* temp = "0123456789abcdefghijklmnopqrstuvwxyz";
然后我们再考虑负数,负数的话我们就要先把负号拿出来,然后再将剩下的正数部分获取到。
这里我们就要提到一个新概念,无符号的数据类型unsigned int,用这个类型去重定义之前的数据类型,后面的数据就都可以与符号无关,只用关注数值位的运算
// unsigned int unsigned_value = (unsigned int)value; //将value 从有符号数据类型转换为无符号数据类型 // // while (unsigned_value != 0) { //left = unsigned_value % radix; 余数存放buff合适位置存放 //buff[index++] = temp[left]; //-321 //unsigned_value /= radix; // } //
其次得到负号之后,我们获取到之后的数据应该是要从负号的后一位开始
那么我们就可以做一个标记
// if (value < 0 && radix == 10) { //"-" // buff[index++] = '-'; // value *= -1; //123 // flag = 1; // }
这样我们就得到了my_itoa函数的代码
char* my_itoa(int value, char* buff, int radix) { assert(buff != NULL); int left = 0,index = 0,flag = 0; const char* temp = "0123456789abcdefghijklmnopqrstuvwxyz"; if (value < 0 && radix == 10) { //"-" buff[index++] = '-'; value *= -1; //123 flag = 1; } unsigned int unsigned_value = (unsigned int)value; //将value 从有符号数据类型转换为无符号数据类型 while (unsigned_value != 0) { left = unsigned_value % radix; //余数存放buff合适位置存放 buff[index++] = temp[left]; //-321 unsigned_value /= radix; } //数组元素逆转 1 2 3 4 5 for (int j = 0; j < (index + 1) / 2; j++) { //-321 321 int temp = buff[j+flag]; buff[j+flag] = buff[index - j-1]; buff[index - j-1] = temp; } return buff; //数组尾巴 } int main() { char buff[100] = { 0 }; printf("%sn", my_itoa(-100, buff, 16)); //"1111" //unsigned int a = -1; //+-21 //printf("%dn",a); //%d 有符号数据类型 -1 %u //printf("%sn",my_itoa(1000,buff,16)); //012...9abcdef.......z //100 10进制 -> "100" //100 8 -> "144" //1000 16 -> "a" return 0; }