函数 | 作用 |
atof | 把字符串转换为float型数字 |
atoi | 把字符串转换为int型数字 |
atol | 把字符串转换为long型数字 |
__toascii | 把字符转换为ascii码 |
tolower | 把字符转换为小写字符 |
toupper | 把字符转换为大写字符 |
abs | 取绝对值 |
strtod | |
strtol |
二.atof
其实,这种字符串转换的函数,都无非做的同一件事情--解析字符串,根据不同的解析规则,执行不同的转换方式。
atof是借助strtod来实现的,主要步骤为:
- 1).解析空格 isspace
- 2).解析正负号 ‘+’or ‘-’
- 3).解析整数部分数字 isdigit
- 4).解析小数点及其后小数部分
- 5).解析科学计数部分
- 6).解析科学计数的正负号
- 7).还原组合数字
2.实现
1: inline double tAtof(const tChar *pStr)
2: {
3: return tStrtod(pStr, NULL);
4: }
5:
6: inline double tStrtod(const tChar *pStr, tChar **pEndStr)
7: {
8: // advance beyond any leading whitespace
9: while( ::isspace(*pStr) )
10: ++pStr;
11:
12: // check for optional '+' or '-'
13: unsigned short uNegative = 0;
14: if( *pStr == _T('-') )
15: {
16: uNegative = 1;
17: ++pStr;
18: }
19: else if( *pStr == _T('+') )
20: ++pStr;
21:
22:
23: double dRet = 0.0;
24: int e = 0;
25: int c = 0;
26:
27: // 解析整数部分
28: while((c = *pStr) != _T('/0') && isdigit(c) )
29: {
30: dRet = dRet * 10.0 + (c - _T('0'));
31: ++pStr;
32: }
33:
34: // 解析小数部分
35: if( c == _T('.') )
36: {
37: ++pStr;
38: while((c = *pStr) != _T('/0') && isdigit(c) )
39: {
40: dRet = dRet * 10.0 + (c - _T('0'));
41: e -= 1;
42:
43: ++pStr;
44: }
45: }
46:
47: // 解析科学计数
48: if( c == 'e' || c == 'E' )
49: {
50: int nSign = 1;
51: int nExponet = 0;
52:
53: c = *++pStr;
54:
55: // 解析正负号
56: if( c == _T('+') )
57: c = *++pStr;
58: else if( c == _T('-') )
59: {
60: nSign = -1;
61: c = *++pStr;
62: }
63:
64: while( isdigit(c) )
65: {
66: nExponet = nExponet * 10 + (c - _T('0'));
67: c = *pStr++;
68: }
69:
70: e += nExponet * nSign;
71: }
72:
73: // 还原组合数字
74: while(e > 0)
75: {
76: dRet *= 10.0;
77: --e;
78: }
79: while(e < 0)
80: {
81: dRet *= 0.1;
82: ++e;
83: }
84:
85: return uNegative ? -dRet : dRet;
86: }
其实,思想挺简单的,只是有点长~。具体多琢磨琢磨就更清楚了。
3.测试
1: tChar *str = NULL;
2: double value = 0;
3:
4: // An example of the atof function
5: // using leading and training spaces.
6: str = _T(" 3336402735171707160320 ");
7: value = CY_CRT::tAtof( str );
8: cout << value << endl;
9:
10: // Another example of the atof function
11: // using the 'd' exponential formatting keyword.
12: str = _T("3.1412764583d210");
13: value = CY_CRT::tAtof( str );
14: cout << value << endl;
15:
16: // An example of the atof function
17: // using the 'e' exponential formatting keyword.
18: str = _T("-2309.12E-15");
19: value = CY_CRT::tAtof( str );
20: cout << value << endl;
21:
22:
23: str = _T("-0.123e-10");
24: value = CY_CRT::tAtof( str );
25: cout << value << endl;
三、atoi
原理如下:
- 1)解析空格 tIsspace
- 2)判断正负号 ‘-’or ’+’
- 3)strtol判断转换进制 16进制、8进制、10进制
- 4)解析数字字符
- 5)对每个字符转换为相应数字 tIsdigit tIsalpha
- 6) 判断转换后的数字是否超过最大值
- 7)累加,基于转换进制
- 8)如果超过最大值则出错处理,负数就返回相反数
- 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;