atoi函数的实现(考虑不同进制、溢出)
2013-07-08 16:21:15
atio就是将ASCII码表示的字符为int型数据,看似简单的问题,实际上需要考虑的很多。对于简单的问题,考虑是否全面就显得特别重要。
小结:
对于该函数的实现要考虑一下几个方面:
- 输入字符串为NULL;
- 输入开始是否包含符号'+'、'-'
- 输入的字符是否合法(对十进制'0' ~'9'为合法的输入);
- 计算出的 数值必须为unsigned Int,才能判断溢出;
- 数据溢出的处理(上溢出时,返回最大正数;下溢出时,返回最大负数);
- 输入的字符包含前导的空格;
- 进制的考虑,考虑16进制以及8进制,通过开头的0或0x判断进制;
- 对于不同的进制判断的范围不同
对16进制0123456789ABCDEF或0123456789abcdef
对8进制01234567
对10进制0123456789
其中,前4点是最基本的功能,后面两点则算是功能的扩展,根据不同的要求还可以进行扩展,比如加上各种状态标志,表明是否溢出、输入是否合法,具体在函数_atoi_3中有体现。
另外,在编写代码时,还有几点需要注意:
判断是否溢出时,用到的最大数必须为unsigned long int,这样才能表示绝对值最大的负数。
在考虑进制时,比较繁琐,按照下面步骤来做:
根据首个非空字符判断符号:
if (0 == sign) //判断数值的符号
{
if ('+' == *str)
{
sign = 1;
++str;
}
else if('-' == *str)
{
sign = -1;
++str;
}
else if ( isdigit(*str) )
{
sign = 1;
}
}
接下来,判断进制:
if (0 == base) //判断数值的进制
{
if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
{
base = 16;
str = str + 2;
}
else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
{
base = 8;
str = str + 1;
}
else
{
base = 10; //不更新str
}
}
计算出数据后,判断溢出:
if (IsOverflow (IntNumber,sign) == 1)
{
return MaxPositive;
}
if (IsOverflow (IntNumber,sign) == -1)
{
return -( ( MaxPositive + 1) );
}
参考:http://blog.csdn.net/tianshuai11/article/details/7798698
代码(测试暂无发现问题,如发现问题,欢迎指正!):
#include <iostream>
#include <cmath>
using namespace std; #define SIZE 100 //没有区别输入0与\0
//只能对十进制数进行转换
//没有处理溢出
int _atoi_1(char *str)
{
if (NULL == str) //输入合法性检查
{
cout<<"NULL input"<<endl;
exit();
} int sign = ;
int IntNumber = ; while ( *str )
{
if ( == sign)
{
if ('-' == *str)
{
sign = -;
++str;
}
else if ('+' == *str)
{
sign = ;
++str;
}
else if (*str >= '' && *str <= '')
{
sign = ; //不更新str
}
else
{
cout<<"invalid input!"<<endl;
exit();
}
}
else if (*str >= '' && *str <= '')
{
IntNumber = IntNumber* + *str - '';
++str;
}
else
{
cout<<"invalid input!"<<endl;
exit();
}
} return (sign * IntNumber);
} //加上溢出处理
//并可对10进制、16进制以及8进制转换
//状态标志
bool IsNotNULL = true;
bool IsDigit = true;
bool IsNotOverflow = true; int IsOverflow (unsigned long int IntNumber,int sign)
{
unsigned long int MaxPositive = (long int) pow( (float),(int)( *sizeof(long int) - ) ) - ; if ( (sign == ) && !(IntNumber >= && IntNumber <= MaxPositive ) ) //判断是否溢出
{
IsNotOverflow = true;
return ;
} if ( (sign == -) && !(IntNumber > && IntNumber <= (MaxPositive + ) ) ) //判断是否溢出
{
IsNotOverflow = true;
return -;
} return ;
} long int _atoi_2(char *str)
{
if (NULL == str)
{
IsNotNULL = false;
return ;
} int sign = ;
unsigned long int MaxPositive = (long int) pow( (float),(int)( *sizeof(long int) - ) ) - ;
unsigned long int IntNumber = ; //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
unsigned int base = ; while ( *str )
{
while ( ' ' == *str || '\t' == *str) //忽略前导的空格或TAB
++str; if ( == sign) //判断数值的符号
{
if ('+' == *str)
{
sign = ;
++str;
}
else if('-' == *str)
{
sign = -;
++str;
}
else if ( isdigit(*str) )
{
sign = ;
}
}
else
{
if ( isdigit(*str) )
{
if ( == base) //判断数值的进制
{
if ( '' == *str && ( 'x' == *(str + ) || 'X' == *(str + ) ) )
{
base = ;
str = str + ;
}
else if ( '' == *str && !( 'x' == *(str + ) || 'X' == *(str + ) ) )
{
base = ;
str = str + ;
}
else
{
base = ; //不更新str
}
}
else
{
IntNumber = IntNumber * base + *str - ''; if (IsOverflow (IntNumber,sign) == )
{
return MaxPositive;
} if (IsOverflow (IntNumber,sign) == -)
{
return -( ( MaxPositive + ) );
} ++str;
}
}
else
{
IsDigit = false;
return ;
}
}
} return (sign * IntNumber); //如果为空串,也即第一个字符即为\0,返回值为0
}
//对不同的进制,判断的范围不同
//对16进制0123456789ABCDEF
//对8进制01234567
//对10进制0123456789
long int _atoi_3(char *str)
{
if (NULL == str) //输入合法性检查
{
IsNotNULL = false;
return ;
} int sign = ;
unsigned long int IntNumber = ; //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
unsigned long int MaxPositive = (long int) pow( (float),(int)( *sizeof(long int) - ) ) - ;
unsigned int base = ; while ( *str )
{
while ( ' ' == *str || '\t' == *str) //忽略前导的空格或TAB
++str; if ( == sign) //判断数值的符号
{
if ('+' == *str)
{
sign = ;
++str;
}
else if('-' == *str)
{
sign = -;
++str;
}
else if ( isdigit(*str) )
{
sign = ;
}
else
{
IsDigit = false;
return ;
}
}
else
{
if ( == base) //判断数值的进制
{
if ( '' == *str && ( 'x' == *(str + ) || 'X' == *(str + ) ) )
{
base = ;
str = str + ;
}
else if ( '' == *str && !( 'x' == *(str + ) || 'X' == *(str + ) ) )
{
base = ;
str = str + ;
}
else
{
base = ; //不更新str
}
}
else
{
if ( == base)
{
if ( isdigit(*str) )
{
IntNumber = IntNumber * base + *str - '';
if (IsOverflow (IntNumber,sign) == )
{
return MaxPositive;
} if (IsOverflow (IntNumber,sign) == -)
{
return -( ( MaxPositive + ) );
}
++str;
}
else
{
IsDigit = false;
return ;
}
}
else if ( == base)
{
if ( isdigit(*str) || (*str >= 'a'&& *str <= 'f') || (*str >= 'A'&& *str <= 'F'))
{
if ( isdigit(*str))
{
IntNumber = IntNumber * base + *str - '';
}
else if (*str >= 'a'&& *str <= 'f')
{
IntNumber = IntNumber * base + *str - 'a' + ;
}
else if (*str >= 'A'&& *str <= 'F')
{
IntNumber = IntNumber * base + *str - 'A' + ;
} if (IsOverflow (IntNumber,sign) == )
{
return MaxPositive;
} if (IsOverflow (IntNumber,sign) == -)
{
return -( ( MaxPositive + ) );
}
++str;
}
else
{
IsDigit = false;
return ;
}
}
else
{
if ( *str>= '' && *str <= '')
{
IntNumber = IntNumber * base + *str - '';
if (IsOverflow (IntNumber,sign) == )
{
return MaxPositive;
} if (IsOverflow (IntNumber,sign) == -)
{
return -( ( MaxPositive + ) );
}
++str;
}
else
{
IsDigit = false;
return ;
}
}
}
}
} return (sign * IntNumber); //如果为空串,也即第一个字符即为\0,返回值为0
} //测试程序
int main()
{
char str[SIZE]; cout<<"size of type int is : "<<sizeof(int)<<endl; //
cout<<"size of type long int is : "<<sizeof(long int)<<endl; //
cout<<"size of type float is : "<<sizeof(float)<<endl; //
cout<<"size of type long double is : "<<sizeof(long double)<<endl; //
/*char str[SIZE] = "100278";
char str[SIZE] = "+1267
char str[SIZE] = "-12";
char str[SIZE] = "+";
char str[SIZE] = "-";
char str[SIZE] = "";
char str[SIZE] = "z98";
char str[SIZE] = "-9s8";*/ //test _atoi_1...
cout<<"test _atoi_1..."<<endl;
cout<<"please enter the string :"<<endl;
while(cin>>str)
{
cout<<"the string is :"<<str<<endl;
cout<<"the int number is : "<<_atoi_1(str)<<endl;
cout<<"please enter the string :"<<endl;
} cin.clear();
cin.sync();
cout<<endl; //test _atoi_2...
cout<<"test _atoi_2..."<<endl;
cout<<"please enter the string :"<<endl;
while(cin>>str)
{
cout<<"the string is :"<<str<<endl;
cout<<"the int number is : "<<_atoi_2(str)<<endl;
cout<<"please enter the string :"<<endl;
} cin.clear();
cin.sync();
cout<<endl; //test _atoi_3...
cout<<"test _atoi_3..."<<endl;
cout<<"please enter the string :"<<endl;
while(cin>>str)
{
cout<<"the string is :"<<str<<endl;
cout<<"the int number is : "<<_atoi_3(str)<<endl;
cout<<"please enter the string :"<<endl;
} return ;
}
对代码的测试也要注意开头中提到的几点,运行结果:
size of type int is :
size of type long int is :
size of type float is :
size of type long double is :
test _atoi_1...
please enter the string : the string is :
the int number is :
please enter the string :
+
the string is :+
the int number is :
please enter the string :
-
the string is :-
the int number is : -
please enter the string : the string is :
the int number is :
please enter the string : the string is :
the int number is :
please enter the string : the string is :
the int number is : -
please enter the string :
-
the string is :-
the int number is :
please enter the string :
^Z test _atoi_2...
please enter the string : the string is :
the int number is :
please enter the string :
-
the string is :-
the int number is : -
please enter the string :
-
the string is :-
the int number is : -
please enter the string :
0x1a
the string is :0x1a
the int number is :
please enter the string : the string is :
the int number is :
please enter the string :
0x89
the string is :0x89
the int number is :
please enter the string :
0xaa
the string is :0xaa
the int number is :
please enter the string :
^Z test _atoi_3...
please enter the string : the string is :
the int number is :
please enter the string :
-
the string is :-
the int number is : -
please enter the string :
0x1a
the string is :0x1a
the int number is :
please enter the string :
-0xaa
the string is :-0xaa
the int number is : -
please enter the string : the string is :
the int number is :
please enter the string : the string is :
the int number is :
please enter the string :
^Z
请按任意键继续. . .
atoi函数的实现(考虑不同进制、溢出)的更多相关文章
- itoa函数的实现(不同进制)
2013-07-08 17:12:30 itoa函数相对于atoi函数,比较简单,还是要注意考虑的全面. 小结: 一下几点需要考虑: 对负数,要加上负号: 考虑不同进制,根据要求进行处理:对不同的进制 ...
- strtol函数 将字符串转换为相应进制的整数
转自http://hi.baidu.com/qwpsmile/blog/item/9bc44efa4f41018a9f514637.html +----------------+| strt ...
- Datediff函数 助你实现不同进制时间之间的运算
在VB开发环境中实现时间之间的加减运算有很多种方法,前不久自己无意中发现了Datediff函数,它能够比较简单.全面地实现我们比较常用的时间之间的运算,今由自己的研究,搞清了它的一些用法,拿来和大家分 ...
- 嵌入式开发之函数解析---ip地址2进制转字符inet_ntoa 调用中只生效一次
inet_addr() 简述:将一个点间隔地址转换成一个in_addr. #include <winsock.h> unsigned long PASCAL FAR inet_addr ...
- C++中的各种进制转换函数汇总及学习
一.指定格式输出 1.C中指定格式输出 printf(); //按八进制格式输出,保留5位高位补零 printf(); //按十进制格式输出,保留3位高位补零 printf(); //按十六进制格式输 ...
- Python中进制转换函数的使用
Python中进制转换函数的使用 关于Python中几个进制转换的函数使用方法,做一个简单的使用方法的介绍,我们常用的进制转换函数常用的就是int()(其他进制转换到十进制).bin()(十进制转换到 ...
- 【C/C++】任意进制转换
进制转换:R进制->10进制:10进制->R进制. #include<bits/stdc++.h> using namespace std; /*函数:r进制转换成10进制*/ ...
- 将16进制的颜色转为rgb颜色
在前端面试过程中,常常会遇到这样一种类型的题目: 使用js将16进制的颜色值转为rgb颜色! 反而在项目中,不怎么遇到这种问题,也很少有这种需求的项目. 但毕竟面试中常常遇到,我自己在之前的面试的时候 ...
- 轻松实现C/C++各种常见进制相互转换
其它进制转为十进制 在实现这个需求之前,先简单介绍一个c标准库中的一个函数: long strtol( const char *str, char **str_end, int base); 参数详细 ...
- leetcood学习笔记-67-二进制求和
题目描述: 第一次提交: class Solution: def addBinary(self, a: str, b: str) -> str: list_a,list_b=[],[] for ...
随机推荐
- 视酷即时通讯系统应用源码 V1.0
视酷即时通讯系统(原创),成熟稳定,拥有和微信一样强大的功能不再是梦,节省几个月研发时间迅速融合进项目中: 1.首家支持聊天室群聊 2.支持和微信一样的语音聊天,可以显示时长.未读状态,自动轮播未读语 ...
- linux开机启动增加tomcat启动项
需求:开发环境(linux)重启后,每次需手动启动相关应用较为繁琐,如设置为开机自动启动则可减少此工作量. google下,参考了以下博文较好解决了问题: 1. 简单说明 Centos下设置程序开机自 ...
- 记一个JAVA关于日期的坑
JAVA解析日期格式代码,之前一直写成:“yyyy-MM-dd hh:mm”,比如"2016-01-18 11:00"."2016-01-18 15:00"都可 ...
- Oracle 监听动态注册与静态注册
静态注册 静态注册是在启动listener时,listener会从listener.ora文件中获取服务名及相关信息.信息包括:实例名和服务名等. --静态注册时,listener.ora中的内容如下 ...
- 特定用户QQ群聊天记录导出的实现
一.把QQ群的聊天记录txt格式导出 消息管理器 -> 选择要导出的群 -> 右击.导出 这里要注意 : 导出之后的 文本是 unicode 编码的,需要转换 ==|| 之前不知道,搞 ...
- 【js】IE、FF、Chrome浏览器中的JS差异介绍
如何判断浏览器类型 转:http://www.cnblogs.com/carekee/articles/1854674.html 1.通过浏览器特有的对象 如ie 的ActiveXObject ff ...
- c# Oracle 远程连接方式 plsql 连接oracle 11g 64位
1.本地连接字符串: string connect = "Data Source=orcl;user=XXX;password=XXX;Persist Security Info=Tru ...
- IOS调用相机相册
#import "SendViewController.h" //只能打开,没有加载图片的代码,老代码,供参考 #import <MobileCoreServices/UT ...
- 为什么dubbo使用ZkClient作为zookeeper的客户端
本文内容并非原创,使用资料均来自互联网. dubbo使用了zkClient而不是使用zookeeper本身的客户端与zookeeper进行交互,为什么呢? 先看看zookeeper本身自带的客户端的问 ...
- 使用Compass制作雪碧图
遇见好的文章,笔者也会转载.但是正所谓好记性不如烂笔头,单纯的拿来主义也不如自己的亲自实践.所以每次需要转载的文章,我都会自己敲一遍,中间加入一些自己的思考. 这篇文章转载自:http://www.h ...