145 lines
3.9 KiB
C++
145 lines
3.9 KiB
C++
#pragma once
|
||
|
||
#include <vector>
|
||
#include <string>
|
||
|
||
template <typename CharType>
|
||
class verifyNumberString
|
||
{
|
||
public:
|
||
typedef std::basic_string<CharType> string;
|
||
|
||
private:
|
||
enum State
|
||
{
|
||
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: 空格后缀
|
||
};
|
||
|
||
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)
|
||
{
|
||
if (c == static_cast<CharType>(' ')) return 0; // 空格
|
||
if (c == static_cast<CharType>('+') ||
|
||
c == static_cast<CharType>('-')) return 1; // 符号
|
||
if (c >= static_cast<CharType>('0') &&
|
||
c <= static_cast<CharType>('9')) return 2; // 数字
|
||
if (c == static_cast<CharType>('.')) return 3; // 小数点
|
||
if (c == static_cast<CharType>('e') ||
|
||
c == static_cast<CharType>('E')) return 4; // 指数标识
|
||
return 5; // 其他字符
|
||
}
|
||
|
||
// 状态转移表(延迟初始化,线程安全)
|
||
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));
|
||
|
||
// 状态0: START
|
||
st[START][0] = START; // 空格 -> 保持START
|
||
st[START][1] = SIGN; // 符号 -> 进入SIGN
|
||
st[START][2] = INTEGER; // 数字 -> 进入INTEGER
|
||
st[START][3] = POINT_HEAD; // 小数点 -> 进入POINT_HEAD
|
||
|
||
// 状态1: SIGN
|
||
st[SIGN][2] = INTEGER; // 数字 -> 进入INTEGER
|
||
st[SIGN][3] = POINT_HEAD; // 小数点 -> 进入POINT_HEAD
|
||
|
||
// 状态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
|
||
|
||
// 状态3: POINT_HEAD
|
||
st[POINT_HEAD][2] = FRACTION; // 数字 -> 进入FRACTION
|
||
|
||
// 状态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
|
||
|
||
// 状态5: FRACTION
|
||
st[FRACTION][2] = FRACTION; // 数字 -> 保持FRACTION
|
||
st[FRACTION][4] = EXP; // 指数标识 -> 进入EXP
|
||
st[FRACTION][0] = SPACE; // 空格 -> 进入SPACE
|
||
|
||
// 状态6: EXP
|
||
st[EXP][1] = EXP_SIGN; // 符号 -> 进入EXP_SIGN
|
||
st[EXP][2] = EXP_INT; // 数字 -> 进入EXP_INT
|
||
|
||
// 状态7: EXP_SIGN
|
||
st[EXP_SIGN][2] = EXP_INT; // 数字 -> 进入EXP_INT
|
||
|
||
// 状态8: EXP_INT
|
||
st[EXP_INT][2] = EXP_INT; // 数字 -> 保持EXP_INT
|
||
st[EXP_INT][0] = SPACE; // 空格 -> 进入SPACE
|
||
|
||
// 状态9: SPACE
|
||
st[SPACE][0] = SPACE; // 空格 -> 保持SPACE
|
||
}
|
||
|
||
return st;
|
||
}
|
||
|
||
// 验证数字字符串
|
||
template <typename CharType>
|
||
bool verifyNumberString<CharType>::verify()
|
||
{
|
||
State current = START;
|
||
const std::vector<std::vector<int>> &states = getStates(); // 获取状态转移表
|
||
|
||
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);
|
||
}
|
||
|
||
// 有效结束状态
|
||
return (current == INTEGER
|
||
|| current == POINT_AFTER_INT
|
||
|| current == FRACTION
|
||
|| current == EXP_INT
|
||
|| current == SPACE);
|
||
}
|
||
|
||
// 重载 ! 操作符
|
||
template <typename CharType>
|
||
bool verifyNumberString<CharType>::operator!()
|
||
{
|
||
return !verify();
|
||
}
|
||
|
||
#ifdef _UNICODE
|
||
typedef verifyNumberString<wchar_t> VNST;
|
||
#else
|
||
typedef verifyNumberString<char> VNST;
|
||
#endif |