一天一个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发图片一直被审核呢?莫非被最近的网络整风给怔住了?

你可能感兴趣的:(一天一个CRT函数 atoi)