C++实现字符串转整数(atoi)详解
字符串转整数(atoi)的实现与解析
在C++编程中,实现字符串转整数的函数(类似标准库的atoi)是一个经典问题。该函数的作用是将一个字符串解析为整数,处理前导空白、正负号、数字序列,并处理整数溢出等边缘情况。下面我将逐步介绍实现方法,并提供完整的C++代码和详细解析。
1. 函数功能描述
- 输入:一个字符串,可能包含前导空白、正负号(可选)和数字序列。
- 输出:解析后的整数值。
- 行为:
- 忽略字符串开头的前导空白字符(如空格、制表符)。
- 如果遇到正号('+')或负号('-'),记录符号。
- 解析后续的数字字符('0'到'9'),直到遇到非数字字符。
- 如果数字序列为空或无效,返回0。
- 处理整数溢出:如果解析值超出
int范围(即小于INT_MIN或大于INT_MAX),则返回INT_MIN或INT_MAX。
2. C++代码实现
以下是完整的myAtoi函数实现,包含注释以帮助理解。
#include <climits> #include <string> int myAtoi(const std::string& str) { int i = 0; // 字符串索引 int sign = 1; // 符号,默认为正 long result = 0; // 累积结果,使用long处理溢出 // 1. 跳过前导空白字符 while (i < str.size() && (str[i] == ' ' || str[i] == '\t')) { i++; } // 2. 检查正负号 if (i < str.size() && (str[i] == '+' || str[i] == '-')) { sign = (str[i] == '-') ? -1 : 1; i++; } // 3. 解析数字序列 while (i < str.size() && str[i] >= '0' && str[i] <= '9') { int digit = str[i] - '0'; // 当前字符转换为数字 // 4. 检查溢出:在累积前判断是否超出int范围 // 正溢出条件:result > INT_MAX / 10 或 (result == INT_MAX / 10 && digit > INT_MAX % 10) // 负溢出类似,但需考虑符号 if (result > INT_MAX / 10 || (result == INT_MAX / 10 && digit > INT_MAX % 10)) { return (sign == 1) ? INT_MAX : INT_MIN; } // 累积结果:result = result * 10 + digit result = result * 10 + digit; i++; } // 5. 返回最终结果,应用符号 return static_cast<int>(result * sign); }http://my.tv.sohu.com/us/442520045/709689066.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTA2Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689312.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTMxMi5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689079.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTA3OS5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689268.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTI2OC5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689085.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTA4NS5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689333.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTMzMy5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689090.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTA5MC5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689099.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTA5OS5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689293.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTI5My5zaHRtbA==.html
http://my.tv.sohu.com/us/442520045/709689409.shtml
https://tv.sohu.com/v/dXMvNDQyNTIwMDQ1LzcwOTY4OTQwOS5zaHRtbA==.html
3. 代码解析
以下分步解释关键逻辑,确保实现健壮性。
步骤1: 跳过前导空白
- 代码使用
while循环跳过空格和制表符,直到遇到非空白字符。 - 例如,输入" 123"会被解析为123。
步骤2: 处理正负号
- 如果遇到'+'或'-',设置
sign变量(1表示正,-1表示负)。 - 例如,输入"-456"会设置
sign = -1。
步骤3: 解析数字序列
- 循环读取字符,只处理'0'到'9'之间的数字字符。
- 每个字符转换为数字值:
digit = str[i] - '0'。 - 累积公式:$$ \text{result} = \text{result} \times 10 + \text{digit} $$
- 例如,输入"789"逐步累积:$$ \text{result} = (0 \times 10 + 7) = 7, (7 \times 10 + 8) = 78, (78 \times 10 + 9) = 789 $$
步骤4: 溢出处理
- 这是关键部分,避免累积值超出
int范围(INT_MIN到INT_MAX)。 - 使用
long类型存储中间结果,以容纳更大值。 - 溢出检查条件:
- 正溢出:如果当前
result已大于$ \frac{\text{INT_MAX}}{10} $,或者等于$ \frac{\text{INT_MAX}}{10} $但digit大于$ \text{INT_MAX} % 10 $,则返回INT_MAX。 - 负溢出:类似逻辑,但需结合符号返回
INT_MIN。
- 正溢出:如果当前
- 数学不等式表示:
- 对于正数:$$ \text{如果 } \text{result} > \left\lfloor \frac{\text{INT_MAX}}{10} \right\rfloor \text{ 或 } \left( \text{result} = \left\lfloor \frac{\text{INT_MAX}}{10} \right\rfloor \text{ 和 } \text{digit} > \text{INT_MAX} \mod 10 \right) $$
- 负数同理,但边界为
INT_MIN。
- 例如,输入"2147483648"(大于INT_MAX=2147483647),在累积到214748364后,digit=8,满足溢出条件,返回INT_MAX。
步骤5: 返回结果
- 最终结果应用符号:
return result * sign。 - 如果数字序列为空(如输入"abc"),则result保持0,返回0。
4. 边缘案例处理
- 空字符串或无效输入:如"", "abc",返回0。
- 溢出:如"9999999999",返回INT_MAX或INT_MIN。
- 混合字符:如"123abc",解析到'c'停止,返回123。
- 极端值:如"-2147483649",返回INT_MIN。
5. 总结
这个实现模拟了标准atoi行为,但增加了溢出检查,使其更健壮。时间复杂度为$ O(n) $(n为字符串长度),空间复杂度$ O(1) $。在实际应用中,可以进一步优化或添加错误处理机制。如果您有具体测试案例或疑问,我可以提供更多解释!
