C++整数输入验证:构建仅匹配单组数字的正则表达式
整数输入验证器的正则匹配优化问题
我在学习C++课程时自制了一个整数输入验证器(非作业,属个人探索),用于处理各类数据源的未清洗松散输入并转换为整数。现有实现代码如下:
#include <cmath> #include <iostream> #include <regex> #include <string> using namespace std; ... ... int validate_integer(const string& input) { return round(stof(regex_replace(input, regex(R"([^\-0-9.]+)"), ""))); }
该函数可将<2112>、{2112}、2112.0等输入解析为整数2112返回。
我希望添加正则匹配逻辑,当输入过于混乱(如含多组数字)时抛出std::invalid_argument异常,但构建合适正则表达式遇阻,已测试多个正则:
([0-9]+^0-9\.-\d+) (.*[\.\-0-9.]*[^\d]+[^\d].*) (.+|[\-\.0-9]+[^0-9]+(?![0-9]+)) ((.+^[\-\.]*[0-9]+)|(^[\-\.]*[0-9]))+[^0-9]+[^0-9]+ (([^0-9]+[\-\.]*[0-9]+)|(^[\-\.]*[0-9]+)(?![^0-9]+[0-9]+)) .*[\d]+(?<![^0-9]+).*
有效输入
<2112> [(2112)] "2112," 2112.0 -2112 <span style = "numeral">2112</span>
偏好有效输入
.2112 (应返回0) 21.12 (应返回21) 98.89 (应返回99)
无效输入
21,12 "21","12," <span style = "font-size:18.0pt">2112</span> 21TwentyOne12
你的核心思路是对的:先过滤非数字相关字符再转换,但当前实现的问题在于,过滤后可能会把多组数字合并成一个错误的数值(比如21,12过滤后变成2112,但这属于无效输入),所以需要先做有效性校验,再执行过滤转换。
解决方案
先通过正则判断输入是否仅包含一组可解析为数字的内容(即所有数字、-、.不能被非允许字符分割成多组),再进行后续处理:
- 校验用正则表达式
^[^0-9\-]*([\-]?(\d+\.?\d*|\.\d+))[^0-9]*$
^[^0-9\-]*:开头允许任意非数字、非负号的字符([\-]?(\d+\.?\d*|\.\d+)):匹配合法数字(可选负号,支持整数、小数、纯小数格式,至少包含一个数字)[^0-9]*$:结尾允许任意非数字的字符
- 修改后的函数实现
#include <cmath> #include <iostream> #include <regex> #include <string> using namespace std; int validate_integer(const string& input) { // 前置校验:仅允许一组合法数字 regex valid_pattern(R"(^[^0-9\-]*([\-]?(\d+\.?\d*|\.\d+))[^0-9]*$)"); if (!regex_match(input, valid_pattern)) { throw invalid_argument("Input contains multiple number groups or invalid format"); } // 过滤无关字符 string cleaned = regex_replace(input, regex(R"([^\-0-9.]+)"), ""); // 处理纯小数点特殊情况(如".2112"转换后round为0) if (cleaned == "." || cleaned == "-.") { return 0; } return round(stof(cleaned)); }
- 测试验证
- 有效输入:全部匹配正则,过滤转换后结果符合预期
- 偏好有效输入:
.2112匹配正则,转换后round为0;21.12round为21;98.89round为99,满足需求 - 无效输入:均不匹配正则,会抛出
invalid_argument异常,符合要求
整体思路方向没问题,补上前置的正则校验步骤,就能准确识别多组数字的无效输入,避免错误转换。
内容的提问来源于stack exchange,提问作者Stephan Peters
相关产品推荐
相关产品推荐

