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
代码(测试暂无发现问题,如发现问题,欢迎指正!):
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 5 #define SIZE 100 6 7 //没有区别输入0与\0 8 //只能对十进制数进行转换 9 //没有处理溢出 10 int _atoi_1(char *str) 11 { 12 if (NULL == str) //输入合法性检查 13 { 14 cout<<"NULL input"<<endl; 15 exit(0); 16 } 17 18 int sign = 0; 19 int IntNumber = 0; 20 21 while ( *str ) 22 { 23 if (0 == sign) 24 { 25 if ('-' == *str) 26 { 27 sign = -1; 28 ++str; 29 } 30 else if ('+' == *str) 31 { 32 sign = 1; 33 ++str; 34 } 35 else if (*str >= '0' && *str <= '9') 36 { 37 sign = 1; //不更新str 38 } 39 else 40 { 41 cout<<"invalid input!"<<endl; 42 exit(0); 43 } 44 } 45 else if (*str >= '0' && *str <= '9') 46 { 47 IntNumber = IntNumber*10 + *str - '0'; 48 ++str; 49 } 50 else 51 { 52 cout<<"invalid input!"<<endl; 53 exit(0); 54 } 55 } 56 57 return (sign * IntNumber); 58 } 59 60 //加上溢出处理 61 //并可对10进制、16进制以及8进制转换 62 //状态标志 63 bool IsNotNULL = true; 64 bool IsDigit = true; 65 bool IsNotOverflow = true; 66 67 int IsOverflow (unsigned long int IntNumber,int sign) 68 { 69 unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 70 71 if ( (sign == 1) && !(IntNumber >= 0 && IntNumber <= MaxPositive ) ) //判断是否溢出 72 { 73 IsNotOverflow = true; 74 return 1; 75 } 76 77 if ( (sign == -1) && !(IntNumber > 0 && IntNumber <= (MaxPositive + 1) ) ) //判断是否溢出 78 { 79 IsNotOverflow = true; 80 return -1; 81 } 82 83 return 0; 84 } 85 86 long int _atoi_2(char *str) 87 { 88 if (NULL == str) 89 { 90 IsNotNULL = false; 91 return 0; 92 } 93 94 int sign = 0; 95 unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 96 unsigned long int IntNumber = 0; //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31 97 unsigned int base = 0; 98 99 while ( *str ) 100 { 101 while ( ' ' == *str || '\t' == *str) //忽略前导的空格或TAB 102 ++str; 103 104 if (0 == sign) //判断数值的符号 105 { 106 if ('+' == *str) 107 { 108 sign = 1; 109 ++str; 110 } 111 else if('-' == *str) 112 { 113 sign = -1; 114 ++str; 115 } 116 else if ( isdigit(*str) ) 117 { 118 sign = 1; 119 } 120 } 121 else 122 { 123 if ( isdigit(*str) ) 124 { 125 if (0 == base) //判断数值的进制 126 { 127 if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) ) 128 { 129 base = 16; 130 str = str + 2; 131 } 132 else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) ) 133 { 134 base = 8; 135 str = str + 1; 136 } 137 else 138 { 139 base = 10; //不更新str 140 } 141 } 142 else 143 { 144 IntNumber = IntNumber * base + *str - '0'; 145 146 if (IsOverflow (IntNumber,sign) == 1) 147 { 148 return MaxPositive; 149 } 150 151 if (IsOverflow (IntNumber,sign) == -1) 152 { 153 return -( ( MaxPositive + 1) ); 154 } 155 156 ++str; 157 } 158 } 159 else 160 { 161 IsDigit = false; 162 return 0; 163 } 164 } 165 } 166 167 return (sign * IntNumber); //如果为空串,也即第一个字符即为\0,返回值为0 168 } 169 //对不同的进制,判断的范围不同 170 //对16进制0123456789ABCDEF 171 //对8进制01234567 172 //对10进制0123456789 173 long int _atoi_3(char *str) 174 { 175 if (NULL == str) //输入合法性检查 176 { 177 IsNotNULL = false; 178 return 0; 179 } 180 181 int sign = 0; 182 unsigned long int IntNumber = 0; //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31 183 unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 184 unsigned int base = 0; 185 186 while ( *str ) 187 { 188 while ( ' ' == *str || '\t' == *str) //忽略前导的空格或TAB 189 ++str; 190 191 if (0 == sign) //判断数值的符号 192 { 193 if ('+' == *str) 194 { 195 sign = 1; 196 ++str; 197 } 198 else if('-' == *str) 199 { 200 sign = -1; 201 ++str; 202 } 203 else if ( isdigit(*str) ) 204 { 205 sign = 1; 206 } 207 else 208 { 209 IsDigit = false; 210 return 0; 211 } 212 } 213 else 214 { 215 if (0 == base) //判断数值的进制 216 { 217 if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) ) 218 { 219 base = 16; 220 str = str + 2; 221 } 222 else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) ) 223 { 224 base = 8; 225 str = str + 1; 226 } 227 else 228 { 229 base = 10; //不更新str 230 } 231 } 232 else 233 { 234 if (10 == base) 235 { 236 if ( isdigit(*str) ) 237 { 238 IntNumber = IntNumber * base + *str - '0'; 239 if (IsOverflow (IntNumber,sign) == 1) 240 { 241 return MaxPositive; 242 } 243 244 if (IsOverflow (IntNumber,sign) == -1) 245 { 246 return -( ( MaxPositive + 1) ); 247 } 248 ++str; 249 } 250 else 251 { 252 IsDigit = false; 253 return 0; 254 } 255 } 256 else if (16 == base) 257 { 258 if ( isdigit(*str) || (*str >= 'a'&& *str <= 'f') || (*str >= 'A'&& *str <= 'F')) 259 { 260 if ( isdigit(*str)) 261 { 262 IntNumber = IntNumber * base + *str - '0'; 263 } 264 else if (*str >= 'a'&& *str <= 'f') 265 { 266 IntNumber = IntNumber * base + *str - 'a' + 10; 267 } 268 else if (*str >= 'A'&& *str <= 'F') 269 { 270 IntNumber = IntNumber * base + *str - 'A' + 10; 271 } 272 273 if (IsOverflow (IntNumber,sign) == 1) 274 { 275 return MaxPositive; 276 } 277 278 if (IsOverflow (IntNumber,sign) == -1) 279 { 280 return -( ( MaxPositive + 1) ); 281 } 282 ++str; 283 } 284 else 285 { 286 IsDigit = false; 287 return 0; 288 } 289 } 290 else 291 { 292 if ( *str>= '0' && *str <= '7') 293 { 294 IntNumber = IntNumber * base + *str - '0'; 295 if (IsOverflow (IntNumber,sign) == 1) 296 { 297 return MaxPositive; 298 } 299 300 if (IsOverflow (IntNumber,sign) == -1) 301 { 302 return -( ( MaxPositive + 1) ); 303 } 304 ++str; 305 } 306 else 307 { 308 IsDigit = false; 309 return 0; 310 } 311 } 312 } 313 } 314 } 315 316 return (sign * IntNumber); //如果为空串,也即第一个字符即为\0,返回值为0 317 } 318 319 //测试程序 320 int main() 321 { 322 char str[SIZE]; 323 324 cout<<"size of type int is : "<<sizeof(int)<<endl; //4 325 cout<<"size of type long int is : "<<sizeof(long int)<<endl; //4 326 cout<<"size of type float is : "<<sizeof(float)<<endl; //4 327 cout<<"size of type long double is : "<<sizeof(long double)<<endl; //8 328 /*char str[SIZE] = "100278"; 329 char str[SIZE] = "+1267 330 char str[SIZE] = "-12"; 331 char str[SIZE] = "+"; 332 char str[SIZE] = "-"; 333 char str[SIZE] = ""; 334 char str[SIZE] = "z98"; 335 char str[SIZE] = "-9s8";*/ 336 337 //test _atoi_1... 338 cout<<"test _atoi_1..."<<endl; 339 cout<<"please enter the string :"<<endl; 340 while(cin>>str) 341 { 342 cout<<"the string is :"<<str<<endl; 343 cout<<"the int number is : "<<_atoi_1(str)<<endl; 344 cout<<"please enter the string :"<<endl; 345 } 346 347 cin.clear(); 348 cin.sync(); 349 cout<<endl; 350 351 //test _atoi_2... 352 cout<<"test _atoi_2..."<<endl; 353 cout<<"please enter the string :"<<endl; 354 while(cin>>str) 355 { 356 cout<<"the string is :"<<str<<endl; 357 cout<<"the int number is : "<<_atoi_2(str)<<endl; 358 cout<<"please enter the string :"<<endl; 359 } 360 361 cin.clear(); 362 cin.sync(); 363 cout<<endl; 364 365 //test _atoi_3... 366 cout<<"test _atoi_3..."<<endl; 367 cout<<"please enter the string :"<<endl; 368 while(cin>>str) 369 { 370 cout<<"the string is :"<<str<<endl; 371 cout<<"the int number is : "<<_atoi_3(str)<<endl; 372 cout<<"please enter the string :"<<endl; 373 } 374 375 return 0; 376 }
对代码的测试也要注意开头中提到的几点,运行结果:
size of type int is : 4 size of type long int is : 4 size of type float is : 4 size of type long double is : 8 test _atoi_1... please enter the string : 12 the string is :12 the int number is : 12 please enter the string : +12 the string is :+12 the int number is : 12 please enter the string : -12 the string is :-12 the int number is : -12 please enter the string : 2147483647 the string is :2147483647 the int number is : 2147483647 please enter the string : 2147483628 the string is :2147483628 the int number is : 2147483628 please enter the string : 2147483648 the string is :2147483648 the int number is : -2147483648 please enter the string : -2147483649 the string is :-2147483649 the int number is : 2147483647 please enter the string : ^Z test _atoi_2... please enter the string : 2147483648 the string is :2147483648 the int number is : 2147483647 please enter the string : -2147483648 the string is :-2147483648 the int number is : -2147483648 please enter the string : -2147483649 the string is :-2147483649 the int number is : -2147483648 please enter the string : 0x1a the string is :0x1a the int number is : 0 please enter the string : 089 the string is :089 the int number is : 73 please enter the string : 0x89 the string is :0x89 the int number is : 137 please enter the string : 0xaa the string is :0xaa the int number is : 0 please enter the string : ^Z test _atoi_3... please enter the string : 2147483648 the string is :2147483648 the int number is : 2147483647 please enter the string : -2147483649 the string is :-2147483649 the int number is : -2147483648 please enter the string : 0x1a the string is :0x1a the int number is : 26 please enter the string : -0xaa the string is :-0xaa the int number is : -170 please enter the string : 089 the string is :089 the int number is : 0 please enter the string : 077 the string is :077 the int number is : 63 please enter the string : ^Z 请按任意键继续. . .
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步