在C++程序开发中,经常需要处理用户输入、文件读取或网络传输得到的字符串数据,从中提取有效的数字信息是高频操作。标准库提供的stoi和stod函数可以快速完成字符串到整数、浮点数的转换,但若不做好异常处理,遇到非法格式的字符串时程序会直接抛出异常终止运行。

stoi与stod基本用法
stoi用于将字符串转换为int类型整数,stod用于将字符串转换为double类型浮点数,二者都定义在<string>头文件中,基础使用方式如下:
#include <iostream>
#include <string>
using namespace std;
int main() {
string int_str = "123";
string double_str = "45.67";
// 转换字符串为整数
int num1 = stoi(int_str);
// 转换字符串为浮点数
double num2 = stod(double_str);
cout << "整数结果:" << num1 << endl;
cout << "浮点数结果:" << num2 << endl;
return 0;
}
这两个函数会自动忽略字符串开头的空白字符,转换到第一个无法识别为数字字符的位置停止,比如字符串"123abc"用stoi转换会得到123,后面的"abc"会被忽略。
常见异常场景
直接使用stoi和stod时,遇到以下情况会抛出异常:
- 字符串中没有任何有效的数字字符,比如"abc"、"中文123"
- 转换结果超出对应类型的表示范围,比如用
stoi转换"9999999999",超出int的最大值范围 - 字符串格式不符合数字规则,比如"12.3.4"用
stod转换时会出现格式错误
异常处理实现方式
可以通过try-catch块捕获stoi和stod抛出的异常,常见的异常类型有两种:
invalid_argument:字符串中没有可转换的有效数字字符时抛出out_of_range:转换结果超出目标类型范围时抛出
完整的异常处理示例如下:
#include <iostream>
#include <string>
#include <stdexcept> // 包含异常类型定义
using namespace std;
int main() {
string test_str1 = "abc123";
string test_str2 = "9999999999";
string test_str3 = "45.6";
// 处理stoi转换
try {
int num1 = stoi(test_str1);
cout << "stoi转换结果:" << num1 << endl;
} catch (const invalid_argument& e) {
cout << "stoi转换失败:字符串无有效数字字符" << endl;
} catch (const out_of_range& e) {
cout << "stoi转换失败:结果超出int范围" << endl;
}
// 处理stoi超范围场景
try {
int num2 = stoi(test_str2);
cout << "stoi转换结果:" << num2 << endl;
} catch (const invalid_argument& e) {
cout << "stoi转换失败:字符串无有效数字字符" << endl;
} catch (const out_of_range& e) {
cout << "stoi转换失败:结果超出int范围" << endl;
}
// 处理stod转换
try {
double num3 = stod(test_str3);
cout << "stod转换结果:" << num3 << endl;
} catch (const invalid_argument& e) {
cout << "stod转换失败:字符串无有效数字字符" << endl;
} catch (const out_of_range& e) {
cout << "stod转换失败:结果超出double范围" << endl;
}
return 0;
}
提升转换健壮性的补充技巧
如果希望更精准地控制转换过程,还可以使用stoi和stod的带参数重载版本,通过第二个参数获取转换结束的位置,判断整个字符串是否都被有效转换:
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
int main() {
string str = "123abc";
size_t pos; // 用于存储转换结束的位置
try {
int num = stoi(str, &pos);
// 判断转换结束后是否到达字符串末尾,若没有说明存在无效后缀
if (pos == str.length()) {
cout << "完整转换结果:" << num << endl;
} else {
cout << "转换部分结果:" << num << ",未转换部分:" << str.substr(pos) << endl;
}
} catch (const exception& e) {
cout << "转换失败:" << e.what() << endl;
}
return 0;
}
这种写法可以在转换部分成功时,进一步校验字符串的剩余内容,避免将"123abc"这类混合字符串误判为合法的数字输入,让字符串数字提取的逻辑更加严谨。