一天一个CRT函数 atoi

这一阵子真忙~年关将至,人也累死!

前面已经说过,将字符串转换为数字其实就是做的字符串解析的工作,atoi也不例外。就是利用strtol函数来实现,若转换数字超过最大范围(LONG_MAX—LONG_MIN)则返回错误。原理如下:

  1. 1)解析空格  tIsspace
  2. 2)判断正负号  ‘-’or  ’+’
  3. 3)strtol判断转换进制  16进制、8进制、10进制
  4. 4)解析数字字符
  5. 5)对每个字符转换为相应数字  tIsdigit  tIsalpha
  6. 6) 判断转换后的数字是否超过最大值
  7. 7)累加,基于转换进制
  8. 8)如果超过最大值则出错处理,负数就返回相反数
  9. 9)返回转换后的数字

1.实现

   1: inline int tAtoi(const tChar *pStr)
   2: {
   3:     return tStrtol(pStr, NULL, 10);
   4: }
   5:  
   6: inline long tStrtol(const tChar *pStr, tChar **pEndPtr, int nBase)
   7: {
   8:     /*
   9:         Skip white space and pick up leading +/- sign if any.
  10:         If nBase is 0, allow 0x for hex and 0 for octal, else assume decimal
  11:         If nBase if already 16, allow 0x
  12:     */
  13:  
  14:     const tChar *pStrTmp = pStr;
  15:     int c = 0;
  16:  
  17:     
  18:     do 
  19:     {
  20:         c = *pStrTmp++;            /* skip whitespace */
  21:     } while (tIsspace(c));
  22:  
  23:     int nNegative = 0;            /* remember minus sign */
  24:     if( c == _T('-') )
  25:     {
  26:         nNegative = 1;
  27:         c = *pStrTmp++;
  28:     }
  29:     else if( c == _T('+') )
  30:     {
  31:         c = *pStrTmp++;            /* skip sign */
  32:     }
  33:  
  34:     if( nBase < 0 || nBase == 1 || nBase > 36) 
  35:     {
  36:         /* bad base! */
  37:         if( pEndPtr )
  38:             /* store beginning of string in endptr */
  39:             *pEndPtr = const_cast(reinterpret_cast<const tChar *>(pStr));
  40:         return 0L;              /* return 0 */
  41:     }
  42:  
  43:     // 判断当前是否转换为16进制
  44:     if( (nBase == 0 || nBase == 16) &&
  45:         (c == _T('0')) &&
  46:         (*pStrTmp == _T('x') || *pStrTmp == _T('X')) )
  47:     {
  48:         c = pStrTmp[1];
  49:         pStrTmp += 2;
  50:         nBase = 16;
  51:     }
  52:     // 是否转换为8进制
  53:     if( nBase == 0 )
  54:         nBase = (c == _T('0') ? 8 : 10);
  55:  
  56:  
  57:     /* if our number exceeds this, we will overflow on multiply */
  58:     unsigned long ulCutOff = 0;
  59:     int nCutLim = 0;
  60:  
  61:     ulCutOff    = nNegative ? -(unsigned long)(LONG_MIN) : LONG_MAX;
  62:     nCutLim        = ulCutOff % static_cast<unsigned long>(nBase);
  63:     ulCutOff    /= static_cast<unsigned long>(nBase);
  64:  
  65:  
  66:     unsigned long acc =0;
  67:     int any = 0;
  68:     for(acc = 0, any = 0; ; c = *pStrTmp++)
  69:     {
  70:         /* convert c to value */
  71:         if( tIsdigit(c) )
  72:             c -= _T('0');
  73:         else if( tIsalpha(c) )
  74:             c -= tIsupper(c) ? _T('A') - 10 : _T('a') - 10;
  75:         else
  76:             break;         /* exit loop if bad digit found */
  77:  
  78:         if( c >= nBase )
  79:             break;
  80:  
  81:         /*    we now need to compute number = number * base + digval,
  82:             but we need to know if overflow occured.  This requires
  83:             a tricky pre-check. 
  84:         */
  85:         if( any < 0 || acc > ulCutOff || acc == ulCutOff && c > nCutLim )
  86:             any = -1;
  87:         else    
  88:         {
  89:             any = 1;
  90:             acc *= nBase;
  91:             acc += c;
  92:         }
  93:     }
  94:  
  95:     if( any < 0 )
  96:     {
  97:         /* we would have overflowed */
  98:         acc = nNegative ? LONG_MIN : LONG_MAX;
  99:         //throw std::overflow_error("LONG_MIN or LONG MAX");
 100:     }
 101:     /* negate result if there was a neg sign */
 102:     else if( nNegative )
 103:         acc = -acc;
 104:  
 105:     if( pEndPtr != 0 )
 106:         *pEndPtr = const_cast(reinterpret_cast<const tChar *>(any ? pStrTmp - 1: pStr));
 107:  
 108:     return acc;
 109: }

测试代码为

   1: tChar    *str = NULL;
   2: int     value = 0;
   3:  
   4: // An example of the atoi function.
   5: str = _T("  -2309 ");
   6: value = CY_CRT::tAtoi( str );
   7: wcout << value << endl;
   8:  
   9: // Another example of the atoi function.
  10: str = _T("31412764");
  11: value = CY_CRT::tAtoi( str );
  12: wcout << value << endl;

 

怎么CSDN的Blog发图片一直被审核呢?莫非被最近的网络整风给怔住了?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值