题目
编写程序,演示现代 C++ 中数值与字符串的互转。重点使用 std::stoi 和 std::stod 进行解析,并通过 try-catch 块对两类经典异常进行严格防御捕获:非法字符导致的 std::invalid_argument,以及数值超限溢出导致的 std::out_of_range,并利用 pos 指针参数检测尾部是否存在未被消费的非法垃圾字符。
输入格式:无需外部输入(内置非法、溢出与尾部杂质测试串)。
输出格式:对每个输入给出转换成功数值或精确捕获的异常分类提示。
数据范围与约定:C++ 异常安全与类型转换健壮性。
思路与算法
1. C 语言 atoi 的缺陷
C 语言的 atoi 在转换失败时静默返回 0,无法区分是用户真的输入了 "0" 还是输入了非法字符 "abc",且不提供任何溢出保护。
2. stoi 的异常体系
C++11 的 std::stoi / std::stod 在格式非法时抛出 std::invalid_argument;当数字超过 int 边界时抛出 std::out_of_range,具有完整的异常类型语义。
3. pos 尾部消耗检测
通过 std::size_t idx = 0; int val = std::stoi(str, &idx);,若 idx != str.length(),说明字符串末尾带有未被解析的杂质字符(如 "123xyz"),可实现极高要求的格式校验。
完整程序
#include <iostream>
#include <string>
#include <stdexcept>
void safeConvertToInt(const std::string& input) {
std::cout << "解析文本: [\"" << input << "\"] -> ";
try {
std::size_t processedIdx = 0;
int result = std::stoi(input, &processedIdx);
if (processedIdx < input.length()) {
std::cout << "部分成功解析: " << result
<< " (警告: 尾部存在未解析残留字符: \""
<< input.substr(processedIdx) << "\")\n";
} else {
std::cout << "完全成功解析整型: " << result << "\n";
}
} catch (const std::invalid_argument& e) {
std::cout << "【捕获异常】输入非数字内容,无法转换 (invalid_argument)\n";
} catch (const std::out_of_range& e) {
std::cout << "【捕获异常】数值过大超出 int 存储范围溢出 (out_of_range)\n";
}
}
int main() {
safeConvertToInt("2026");
safeConvertToInt("99999999999999999999"); // 溢出
safeConvertToInt("abc_test"); // 非法字符
safeConvertToInt("1024_suffix"); // 尾部杂质
// 数值转字符串
double pi = 3.1415926;
std::string piStr = std::to_string(pi);
std::cout << "\nstd::to_string 转换浮点数结果: " << piStr << "\n";
return 0;
}运行示例
输出:
解析文本: ["2026"] -> 完全成功解析整型: 2026
解析文本: ["99999999999999999999"] -> 【捕获异常】数值过大超出 int 存储范围溢出 (out_of_range)
解析文本: ["abc_test"] -> 【捕获异常】输入非数字内容,无法转换 (invalid_argument)
解析文本: ["1024_suffix"] -> 部分成功解析: 1024 (警告: 尾部存在未解析残留字符: "_suffix")
std::to_string 转换浮点数结果: 3.141593