题目要求
代码
#define MaxValue pow(2,31)
class Solution {
public:
int myAtoi(string s) {
bool hasNumber = false;
char sigh = '+';
int number;
for (unsigned i = 0; i < s.size(); i++)
{
//跳过开头空格
if (s[i] == ' ')
{
continue;
}
else
{
//匹配符号
if (s[i] == '+' || s[i] == '-')
{
sigh = s[i++];
}
//匹配数字
if (charIsNumber(s[i]))
{
hasNumber = true;
number = numberFun(s, i);
}
break;
}
}
//有效数字判断
if (hasNumber)
{
if (sigh == '+')
{
if (number == -MaxValue)
{
return MaxValue - 1;
}
return -number;
}
else
{
if (sigh == '-')
{
return number;
}
}
}
return 0;
}
bool charIsNumber(char c)
{
if (c >= '0' && c <= '9')
return true;
else
return false;
}
int numberFun(string& s, unsigned index)
{
int number = 0;
while (charIsNumber(s[index]) && index < s.size())
{
//2147483648是2的31次方,需要判断当前数字是否超出界限
if (number < - static_cast<int>( MaxValue / 10))
{
return -MaxValue;
}
else if (number == static_cast<int>(-MaxValue / 10))
{
//往前看一位:如果下一位还是数字,则肯定超了
if (charIsNumber(s[index+1]))
{
return -MaxValue;
}
else
{
if (s[index] > '8')
{
return -MaxValue;
}
else
{
return number*10 - (s[index] - '0');
}
}
}
number = number * 10 - (s[index] - '0');
++index;
}
return number;
}
};
预先准备
写了两个子函数
bool charIsNumber 函数判断字符是不是一个数字。
int numberFun 函数 输入一个字符串和头数字开始的位置。该函数会自动将字符串中以该位置为开头的一串连续的数字字符串输出。输出结果为负数
整体思路
1、首先先读取并抛弃字符串开头的空格字符。
2、读取第一个非空字符
如果第一个字符为+或者为-,则将该符号记录下来。接着调用numberFun函数读取符号后面的连续数字串。
如果第一个字符为数字,则直接调用numberFun函数读取以此字符开头的连续数字串。
如果第一个字符为其它,则返回0.
3、子函数numberFun:读取数字字符串
此处选择将负数作为返回值,因为负数能表示的范围比正数多1,如果选择正数作为返回值,则无法表示-2的31次方这个数字
首先需要知道-2的31次方结果为2147483648,将其作为负数边界值的判断基准
- 如果本轮的值小于-214748364,则该值乘10必定会超出界限。所以直接返回 -2的31次方
- 如果本轮的值等于-214748364,则向前再看一位字符:
- 如果下一个字符仍然为数字,则肯定超界,直接返回-2的31次方
- 如果下一个字符不为数字,则再继续判断:
- 如果本次读取的字符数字x<=8,输出-214748364x
- 如果本次读取的字符数字x=9 , 超出负上限,输出-2的31次方
- 如果本轮的值大于-214748364, 为一般情况。num = num*10 - x; (x为本轮字符表示的数字)
4、综合符号和数字number,得出结果:
-
如果符号为正
- 当number<=-2的31次方时,返回2的31次方 - 1
- 其它情况返回-number
-
如果符号为负
- 返回number
学到了什么
1、更加深刻的理解了int占4个字节的含义。4个字节为32位,即int的表达范围为:
2、处理边界值时应该更加细致(这题的边界处理弄了一个早上)