Description:
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
Note:
- 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为
[
−
2
31
,
2
31
−
1
]
[-2^{31},2^{31}-1]
[−231,231−1] 。如果数值超过这个范围,请返回
INT_MAX
( 2 31 − 1 2^{31}-1 231−1) 或INT_MIN
( − 2 31 -2^{31} −231) 。
Example
Input: "42"
Output: 42
Input: " -42"
Output: -42
Input: "4193 with words"
Output: 4193
Input: "words and 987"
Output: 0
Input: "-91283472332"
Output: -2147483648
题目之我见
题目的要求类似于 string 类中 stoi()
函数的实现,但是又比 stoi() 函数考虑到的状况更多,比如可能转换后整数会远远超出范围,或者 stoi() 根本无法转换,所以 solution 1的思路就是基于 stoi() 函数,再对其他 stoi() 不能处理的情况进行处理。
Solution 1(函数实现在 26 到 62 行)
#include <iostream>
#include <climits> // INT_MAX, INT_MIN
#include <stdexcept> // try,catch
using namespace std;
int myAtoi(string str);
int main(void)
{
string s = "";
string s1 = "+; 1";
string s2 = "+1-";
string s3 = " -222222222222222222222";
string s4 = "-00";
cout << myAtoi(s) << endl;
cout << myAtoi(s1) << endl;
cout << myAtoi(s2) << endl;
cout << myAtoi(s3) << endl;
cout << myAtoi(s4) << endl;
return 0;
}
int myAtoi(string str)
{
int res;
if (str.empty())
return 0;
else
{ // 其实可以使用 find_first_not_of 优化
while (!str.empty() && str.at(0) == ' ') {str.erase(0, 1);} // 去除串首空格符
if (str.empty())
return 0;
else if (!isdigit(str.at(0)) && str.at(0) != '+' && str.at(0) != '-')
return 0; // 第一个非空字符不是数字也不是'+' / '-'
else if (str == "+" || str.at(0) == '+'&& str.length()>1 && !isdigit(str.at(1)))
return 0; // 第一个非空字符是 '+',但第二个字符不是数字
else if (str == "-" || str.at(0) == '-'&& str.length()>1 && !isdigit(str.at(1)))
return 0; // 第一个非空字符是 '-',但第二个字符不是数字
else
{
try
{
res = stoi(str);
}
catch (std::out_of_range &exc) // 异常处理,若果抛出异常说明转换后整数已超出 int 范围
{ // 这时在对异常进行处理
//std::cerr << exc.what() << endl;
if ('-' == str.at(0))
return INT_MIN;
else
return INT_MAX;
}
return res;
}
}
}
复杂度
我觉得海星。
自己做完之后又去看了 discussion,几乎全是对字符串进行逐字符处理(逃,还是我太赖了。。
Solution 2:
int myAtoi(string str)
{
long res = 0;
int sign = 1;
size_t index = 0;
if(str.find_first_not_of(' ') != string::npos)
index = str.find_first_not_of(' ');
if(str[index] == '+' || str[index] == '-')
sign = str[index++] == '-' ? -1 : 1;
while(index<str.length() && isdigit(str[index]))
{
res = res * 10 + (str[index++] - '0');
if(res*sign > INT_MAX)
return INT_MAX; //Check for INT_MAX & INT_MIN bounds
if(res*sign < INT_MIN)
return INT_MIN;
}
return res * sign;
}