atoi函数的实现(考虑不同进制、溢出)

 2013-07-08 16:21:15

 atio就是将ASCII码表示的字符为int型数据,看似简单的问题,实际上需要考虑的很多。对于简单的问题,考虑是否全面就显得特别重要。

小结:

对于该函数的实现要考虑一下几个方面:

  1. 输入字符串为NULL;
  2. 输入开始是否包含符号'+'、'-'
  3. 输入的字符是否合法(对十进制'0' ~'9'为合法的输入);
  4. 计算出的 数值必须为unsigned Int,才能判断溢出;
  5. 数据溢出的处理(上溢出时,返回最大正数;下溢出时,返回最大负数);
  6. 输入的字符包含前导的空格;
  7. 进制的考虑,考虑16进制以及8进制,通过开头的0或0x判断进制;
  8. 对于不同的进制判断的范围不同
    对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与
  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 || '	' == *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
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 || '	' == *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
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
请按任意键继续. . .
原文地址:https://www.cnblogs.com/youngforever/p/3178379.html