在 C++ 标准库中,std::stoi
是一个常用的字符串转换函数,它能够将 std::string
或 std::wstring
转换为 int
类型的整数。尽管我们经常使用 std::stoi
,但它的内部实现往往被忽略。本文将从使用方法、异常处理到源码解析,深入剖析 std::stoi
,帮助你更好地理解它的工作原理。
1. std::stoi
的基本介绍
std::stoi
定义在 <string>
头文件中,并位于 std
命名空间下。它的主要功能是将字符串转换为 int
类型的整数,并且支持不同进制的转换(如二进制、十进制、十六进制等)。
1.1 std::stoi
的函数原型
int stoi(const std::string& str, size_t* pos = nullptr, int base = 10);
int stoi(const std::wstring& str, size_t* pos = nullptr, int base = 10);
1.2 参数解析
str
:要转换的字符串,必须是有效的整数格式。pos
(可选):如果提供pos
,stoi
会在*pos
中存储转换结束的位置(即最后一个转换的字符的下一个位置)。base
(可选):表示字符串所使用的进制,默认值为10
(十进制),支持2
到36
进制。
1.3 返回值
- 成功:返回转换后的
int
类型整数。 - 失败:如果字符串不是有效的数字或超出了
int
类型的范围,会抛出异常。
2. std::stoi
的实现原理
在 GCC 标准库的 string
头文件中,std::stoi
实际上是基于 std::strtol
实现的,它的实现如下:
inline int
stoi(const string& __str, size_t* __idx = 0, int __base = 10)
{
return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(), __idx, __base);
}
2.1 解析实现代码
- 调用
std::strtol
std::strtol
(String to Long)是 C 语言中的标准函数,它可以将 C 风格的字符串转换为long
类型的整数,同时支持进制转换。 - 使用
__gnu_cxx::__stoa
进行封装
这个函数的作用是将long
转换为int
,并进行错误检查。 __str.c_str()
std::string
的.c_str()
方法返回一个const char*
,将std::string
转换为 C 风格字符串,以便std::strtol
解析。
3. std::stoi
的实际用法
3.1 基础示例
#include <iostream>
#include <string>
int main() {
std::string str = "12345";
int num = std::stoi(str); // 默认10进制
std::cout << "转换结果: " << num << std::endl;
return 0;
}
输出:
转换结果: 12345
3.2 使用 pos
参数记录转换结束的位置
#include <iostream>
#include <string>
int main() {
std::string str = "123xyz";
std::size_t pos;
int num = std::stoi(str, &pos);
std::cout << "转换结果: " << num << std::endl;
std::cout << "转换结束位置: " << pos << std::endl;
return 0;
}
输出:
转换结果: 123
转换结束位置: 3
解析:
stoi
解析"123"
后遇到"xyz"
,停止转换,并将pos
设为3
。
3.3 处理不同进制的转换
#include <iostream>
#include <string>
int main() {
std::string str = "1A"; // 16进制
int num = std::stoi(str, nullptr, 16); // 以16进制解析
std::cout << "转换结果: " << num << std::endl;
return 0;
}
输出:
转换结果: 26
解析:
1A
在十六进制中等于26
,所以stoi
返回26
。
其他进制示例
std::stoi("1010", nullptr, 2); // 以二进制解析,返回 10
std::stoi("75", nullptr, 8); // 以八进制解析,返回 61
std::stoi("1F", nullptr, 16); // 以十六进制解析,返回 31
4. 处理异常情况
4.1 输入不是有效的数字
如果 str
不是有效的整数格式,std::stoi
会抛出 std::invalid_argument
异常:
#include <iostream>
#include <string>
#include <stdexcept>
int main() {
try {
std::string str = "abc";
int num = std::stoi(str);
std::cout << "转换结果: " << num << std::endl;
} catch (const std::invalid_argument& e) {
std::cerr << "错误: 无效的数字字符串 -> " << e.what() << std::endl;
}
return 0;
}
输出:
错误: 无效的数字字符串 -> stoi
4.2 数值超出 int
范围
如果字符串表示的数值超出 int
的范围,std::stoi
会抛出 std::out_of_range
异常:
#include <iostream>
#include <string>
#include <climits>
int main() {
try {
std::string str = "9999999999";
int num = std::stoi(str);
std::cout << "转换结果: " << num << std::endl;
} catch (const std::out_of_range& e) {
std::cerr << "错误: 数值超出范围 -> " << e.what() << std::endl;
}
return 0;
}
输出:
错误: 数值超出范围 -> stoi
5. std::stoi
相关函数
函数 | 作用 | 返回类型 |
---|---|---|
std::stoi | 转换为 int | int |
std::stol | 转换为 long | long |
std::stoll | 转换为 long long | long long |
std::stoul | 转换为 unsigned long | unsigned long |
std::stof | 转换为 float | float |
std::stod | 转换为 double | double |
6. 结论
std::stoi
是std::strtol
的封装,支持进制转换。- 提供
pos
参数记录转换位置。 - 可能抛出
std::invalid_argument
和std::out_of_range
异常。 - 适用于整数解析,若数值可能超大,建议使用
std::stol
或std::stoll
。
学会 std::stoi
,可以让你的 C++ 代码更加高效、健壮!