2026-10-04 00:04:20 +08:00
|
|
|
|
#pragma once
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
|
|
template <typename CharType>
|
|
|
|
|
|
class verifyNumberString
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
typedef std::basic_string<CharType> string;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
enum State
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
START, // 0: 起始状态(含前导空格)
|
|
|
|
|
|
SIGN, // 1: 符号位(正负号)
|
|
|
|
|
|
INTEGER, // 2: 整数部分
|
|
|
|
|
|
POINT_HEAD, // 3: 小数点(前面无数字)
|
|
|
|
|
|
POINT_AFTER_INT, // 4: 整数后的小数点
|
|
|
|
|
|
FRACTION, // 5: 小数部分
|
|
|
|
|
|
EXP, // 6: 指数标识(e/E)
|
|
|
|
|
|
EXP_SIGN, // 7: 指数符号
|
|
|
|
|
|
EXP_INT, // 8: 指数整数部分
|
|
|
|
|
|
SPACE // 9: 空格后缀
|
2026-09-28 15:28:50 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
verifyNumberString(const CharType *psz): m_string(psz){}
|
|
|
|
|
|
verifyNumberString(const string &str): m_string(str){}
|
|
|
|
|
|
bool verify();
|
|
|
|
|
|
bool operator !();
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
int getType(CharType c);
|
|
|
|
|
|
static const std::vector<std::vector<int>> &getStates();
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
string m_string;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename CharType>
|
|
|
|
|
|
int verifyNumberString<CharType>::getType(CharType c)
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
if (c == static_cast<CharType>(' ')) return 0; // 空格
|
2026-09-28 15:28:50 +08:00
|
|
|
|
if (c == static_cast<CharType>('+') ||
|
2026-10-04 00:04:20 +08:00
|
|
|
|
c == static_cast<CharType>('-')) return 1; // 符号
|
2026-09-28 15:28:50 +08:00
|
|
|
|
if (c >= static_cast<CharType>('0') &&
|
2026-10-04 00:04:20 +08:00
|
|
|
|
c <= static_cast<CharType>('9')) return 2; // 数字
|
|
|
|
|
|
if (c == static_cast<CharType>('.')) return 3; // 小数点
|
2026-09-28 15:28:50 +08:00
|
|
|
|
if (c == static_cast<CharType>('e') ||
|
2026-10-04 00:04:20 +08:00
|
|
|
|
c == static_cast<CharType>('E')) return 4; // 指数标识
|
|
|
|
|
|
return 5; // 其他字符
|
2026-09-28 15:28:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态转移表(延迟初始化,线程安全)
|
2026-09-28 15:28:50 +08:00
|
|
|
|
template <typename CharType>
|
|
|
|
|
|
const std::vector<std::vector<int>>& verifyNumberString<CharType>::getStates()
|
|
|
|
|
|
{
|
|
|
|
|
|
static std::vector<std::vector<int>> st;
|
|
|
|
|
|
if (st.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
st.resize(10, std::vector<int>(6, -1));
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态0: START
|
|
|
|
|
|
st[START][0] = START; // 空格 -> 保持START
|
|
|
|
|
|
st[START][1] = SIGN; // 符号 -> 进入SIGN
|
|
|
|
|
|
st[START][2] = INTEGER; // 数字 -> 进入INTEGER
|
|
|
|
|
|
st[START][3] = POINT_HEAD; // 小数点 -> 进入POINT_HEAD
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态1: SIGN
|
|
|
|
|
|
st[SIGN][2] = INTEGER; // 数字 -> 进入INTEGER
|
|
|
|
|
|
st[SIGN][3] = POINT_HEAD; // 小数点 -> 进入POINT_HEAD
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态2: INTEGER
|
|
|
|
|
|
st[INTEGER][2] = INTEGER; // 数字 -> 保持INTEGER
|
|
|
|
|
|
st[INTEGER][3] = POINT_AFTER_INT; // 小数点 -> POINT_AFTER_INT
|
|
|
|
|
|
st[INTEGER][4] = EXP; // 指数标识 -> 进入EXP
|
|
|
|
|
|
st[INTEGER][0] = SPACE; // 空格 -> 进入SPACE
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态3: POINT_HEAD
|
|
|
|
|
|
st[POINT_HEAD][2] = FRACTION; // 数字 -> 进入FRACTION
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态4: POINT_AFTER_INT
|
|
|
|
|
|
st[POINT_AFTER_INT][2] = FRACTION; // 数字 -> 进入FRACTION
|
|
|
|
|
|
st[POINT_AFTER_INT][4] = EXP; // 指数标识 -> 进入EXP
|
|
|
|
|
|
st[POINT_AFTER_INT][0] = SPACE; // 空格 -> 进入SPACE
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态5: FRACTION
|
|
|
|
|
|
st[FRACTION][2] = FRACTION; // 数字 -> 保持FRACTION
|
|
|
|
|
|
st[FRACTION][4] = EXP; // 指数标识 -> 进入EXP
|
|
|
|
|
|
st[FRACTION][0] = SPACE; // 空格 -> 进入SPACE
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态6: EXP
|
|
|
|
|
|
st[EXP][1] = EXP_SIGN; // 符号 -> 进入EXP_SIGN
|
|
|
|
|
|
st[EXP][2] = EXP_INT; // 数字 -> 进入EXP_INT
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态7: EXP_SIGN
|
|
|
|
|
|
st[EXP_SIGN][2] = EXP_INT; // 数字 -> 进入EXP_INT
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态8: EXP_INT
|
|
|
|
|
|
st[EXP_INT][2] = EXP_INT; // 数字 -> 保持EXP_INT
|
|
|
|
|
|
st[EXP_INT][0] = SPACE; // 空格 -> 进入SPACE
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 状态9: SPACE
|
|
|
|
|
|
st[SPACE][0] = SPACE; // 空格 -> 保持SPACE
|
2026-09-28 15:28:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return st;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 验证数字字符串
|
2026-09-28 15:28:50 +08:00
|
|
|
|
template <typename CharType>
|
|
|
|
|
|
bool verifyNumberString<CharType>::verify()
|
|
|
|
|
|
{
|
|
|
|
|
|
State current = START;
|
2026-10-04 00:04:20 +08:00
|
|
|
|
const std::vector<std::vector<int>> &states = getStates(); // 获取状态转移表
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
for (size_t i(0); i < m_string.size(); ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
int type = getType(m_string[i]);
|
|
|
|
|
|
int next = states[current][type];
|
|
|
|
|
|
if (next == -1) return false;
|
|
|
|
|
|
current = static_cast<State>(next);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 有效结束状态
|
2026-09-28 15:28:50 +08:00
|
|
|
|
return (current == INTEGER
|
|
|
|
|
|
|| current == POINT_AFTER_INT
|
|
|
|
|
|
|| current == FRACTION
|
|
|
|
|
|
|| current == EXP_INT
|
|
|
|
|
|
|| current == SPACE);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 重载 ! 操作符
|
2026-09-28 15:28:50 +08:00
|
|
|
|
template <typename CharType>
|
|
|
|
|
|
bool verifyNumberString<CharType>::operator!()
|
|
|
|
|
|
{
|
|
|
|
|
|
return !verify();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _UNICODE
|
|
|
|
|
|
typedef verifyNumberString<wchar_t> VNST;
|
|
|
|
|
|
#else
|
|
|
|
|
|
typedef verifyNumberString<char> VNST;
|
|
|
|
|
|
#endif
|