std::stoi解析含非数字字符字符串不抛异常,求纯数字专属解析函数
好问题!C++标准库本身并没有直接提供这种「严格匹配纯数字字符串」的转换函数,但我们可以基于现有工具轻松实现这个需求,给你分享几种常用的靠谱方案:
方案1:先校验字符合法性再调用std::stoi
这个思路最直观:先检查字符串是否完全由数字组成(可选支持负号),确认合法后再调用std::stoi转换。
#include <string> #include <stdexcept> int strict_stoi(const std::string& str) { // 处理空字符串的情况 if (str.empty()) { throw std::invalid_argument("输入字符串为空"); } size_t start_idx = 0; // 支持负整数:如果首字符是'-',从第二个字符开始检查 if (str[0] == '-') { start_idx = 1; // 单独一个'-'属于非法输入 if (start_idx == str.size()) { throw std::invalid_argument("仅包含负号,不是合法整数"); } } // 检查从start_idx开始的所有字符是否都是数字 if (str.find_first_not_of("0123456789", start_idx) != std::string::npos) { throw std::invalid_argument("字符串包含非数字字符"); } // 确认合法后调用stoi转换 return std::stoi(str); }
如果只需要支持正整数,直接去掉负号相关的逻辑即可。
方案2:用std::strtol检查解析结束位置
C标准库的strtol函数会返回解析终止的指针,我们可以通过判断这个指针是否指向字符串末尾,来确认是否所有字符都被解析为数字,同时还能处理整数溢出的情况。
#include <string> #include <cstdlib> #include <stdexcept> #include <climits> #include <cerrno> int strict_stoi(const std::string& str) { char* end_ptr = nullptr; errno = 0; // 重置错误标记 // 解析字符串为长整数 long parsed_val = std::strtol(str.c_str(), &end_ptr, 10); // 检查四种非法情况: // 1. 没有任何有效数字被解析 // 2. 解析结束后还有剩余字符 // 3. 解析结果超出long的范围 // 4. 解析结果超出int的范围 if (end_ptr == str.c_str() || *end_ptr != '\0' || (errno == ERANGE && (parsed_val == LONG_MAX || parsed_val == LONG_MIN)) || parsed_val < INT_MIN || parsed_val > INT_MAX) { throw std::invalid_argument("不是合法的整数字符串"); } return static_cast<int>(parsed_val); }
这个方案的优势是对错误情况的处理更全面,适合对稳定性要求高的场景。
方案3:用std::stringstream做流式解析
利用C++的输入流特性,尝试读取整数后,检查流是否到达末尾,以此判断是否有剩余的非数字字符。
#include <string> #include <sstream> #include <stdexcept> int strict_stoi(const std::string& str) { std::istringstream iss(str); int parsed_val; char leftover_char; // 尝试读取整数,同时检查是否还有未读取的字符 if (!(iss >> parsed_val) || (iss >> leftover_char)) { throw std::invalid_argument("不是合法的整数字符串"); } return parsed_val; }
注意:默认情况下,输入流会跳过开头的空白字符(比如空格、换行),如果你的场景不允许字符串包含任何空白,需要额外加入空白字符的校验逻辑。
内容的提问来源于stack exchange,提问作者D.Fonkaz
相关产品推荐
相关产品推荐

