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 ...
随机推荐
- Qt5.4生成安装包过程
所需工具: 1. HM NIS Edit 2. windeployqt.exe 第一个工具需要自己去网上下载,第二个工具可以在qt安装目录下找到:D:\qtopengl\5.4\mingw491_ ...
- 全面理解BFC
BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...
- ios 数字禁止变成电话号码
1.使用meta来限制页面不转换电话号码 <meta name="format-detection"content="telphone=no"/> ...
- 使用XFire+Spring构建Web Service
XFire是与Axis 2并列的新一代Web Service框架,通过提供简单的API支持Web Service各项标准协议,帮助你方便快速地开发Web Service应用. 相 对于Axis来说,目 ...
- 从 Typecho 自定义字段的调用代码看去
千呼万唤,Typecho 的"自定义字段"功能终于在 0.9 中出来了.然而,多数人还蒙在这样一个鼓里--该怎么在模板调用已经设置好的自定义字段呢?让我们从这里开始说下去: Typ ...
- 2W/月和1W/月的工作,你会怎么选?
只看标题的话,肯定有不少人会选择月薪 2W 的工作,很明显,钱多嘛!但实际上,这里是有前提的,完整的问题如下: 一份月薪 2W,但加班无底线,基本没有自由时间的工作,和一份月薪 1W,但正常工作时长, ...
- Beaglebone Back学习一(开发板介绍)
随着开源软件的盛行.成熟,开源硬件也迎来了春天,先有Arduino,后有Raspherry Pi,到当前的Beaglebone .相信在不久的将来,开源项目将越来越多,越来越走向成熟. ...
- opencv学习笔记(02)——遍历图像(指针法)
#include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <ope ...
- Postgresql 技巧
备份 pg_dump -f "F:/dump.sql"<file name> -U postgres<database name> -h 10.38.197 ...
- RAC环境下SCAN IP可以PING通,1521端口也可以TELNET,但是无法建立数据库连接
昨天用户请求帮助处理一个问题:有个厂家需要连某个业务系统的数据库,网络上已经开通了权限,SCAN IP可以PING通,测试TELNET 1521端口也是正常.但是想通过SQLPLUS连接,总是会提示连 ...