提交 3697be00 编写于 作者: 小代码2016's avatar 小代码2016

feat(calc_lib): decimal 初始化

上级 6172deb5
......@@ -75,6 +75,6 @@
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"*.in": "cpp"
"*.in": "plaintext"
}
}
\ No newline at end of file
/**
* @file khl_calc.h
* @brief 外部使用包含文件
*/
#ifndef _KHL_CALC_H_
#define _KHL_CALC_H_
#include "khl_calc/khl_calc_exception.hpp"
#include "khl_calc/khl_calc_decimal.h"
#include "khl_calc/khl_calc_util.h"
// C/C++ 跨平台时预处理判断平台环境
// 参考: https://www.cnblogs.com/Forgenvueory/p/12757271.html
......
/**
* @file khl_calc_util.h
* @brief 工具类
*/
#ifndef _KHL_CALC_UTIL_H_
#define _KHL_CALC_UTIL_H_
#include "khl_calc_common.h"
#include <string>
KHL_CALC_NAMESPACE_BEGIN
/**
* @brief 工具类
*/
class CalcUtil
{
private:
/**
* @brief 是否 +
* @param ch 符号
*/
static bool isPlusSign(char ch);
/**
* @brief 是否 -
* @param ch 符号
*/
static bool isSubstractSign(char ch);
/**
* @brief 是否 .
* @param ch 符号
*/
static bool isDotSign(char ch);
/**
* @brief 是否 e 或 E
* @param ch 符号
*/
static bool isScientificSign(char ch);
/**
* @brief 是否 空格
* @param ch 符号
*/
static bool isSpace(char ch);
/**
* @brief 检查数字空格.
* @param s 数字
*/
static bool isNumberTrimValid(std::string s);
public:
/**
* @brief 是否数字. 支持科学计数法
* @param s 数字
*/
static bool isNumber(std::string s);
};
KHL_CALC_NAMESPACE_END
#endif // _KHL_CALC_UTIL_H_
\ No newline at end of file
/**
* @file khl_calc_decimal.cpp
* @brief Decimal 实现
*/
#include <iostream>
#include <memory>
#include <algorithm>
#include "khl_calc/khl_calc_exception.hpp"
#include "khl_calc/khl_calc_decimal.h"
#include "khl_calc/khl_calc_util.h"
KHL_CALC_NAMESPACE_BEGIN
......@@ -13,15 +18,11 @@ Decimal::Decimal(int val)
Decimal::Decimal(std::string val)
{
// 输入字符串不能为空
if( val.empty())
if( !CalcUtil::isNumber(val))
{
throw CalcDecimalInitException("Init error: input string can't be empty string.");
throw CalcDecimalInitException("Init error: the input is not a number.");
}
// 输入字符串必须为合法的数字
auto chars = val.c_str();
init(val);
}
Decimal::Decimal(long val)
......
/**
* @file khl_calc_util.cpp
* @brief CalcUtil 工具类实现
*/
#include "khl_calc/khl_calc_util.h"
#include <cctype>
KHL_CALC_NAMESPACE_BEGIN
bool CalcUtil::isPlusSign(char ch)
{
return ch == '+';
}
bool CalcUtil::isSubstractSign(char ch)
{
return ch == '-';
}
bool CalcUtil::isDotSign(char ch)
{
return ch == '.';
}
bool CalcUtil::isScientificSign(char ch)
{
return ch == 'e' || ch == 'E';
}
bool CalcUtil::isSpace(char ch)
{
return ch == ' ';
}
bool CalcUtil::isNumberTrimValid(std::string s)
{
int len = s.size();
auto chars = s.c_str();
int i = 0;
for (; i < len; i++)
{
char ch = chars[i];
if (!isSpace(ch))
{
break;
}
}
if (i == (len - 1))
{
return false;
}
int j = 0;
for (j = len - 1; j >= 0; j++)
{
char ch = chars[i];
if (!isSpace(ch))
{
break;
}
}
if (j <= i)
{
return false;
}
return true;
}
bool CalcUtil::isNumber(std::string s)
{
// 空字符串直接返回 false
if (s.empty())
{
return false;
}
// 检查空格
if (!isNumberTrimValid(s))
{
return false;
}
// 空格处理
int plusSignCount = 0;
int substractSignCount = 0;
int dotSignCount = 0;
int scientificSignCount = 0;
int digitCount = 0;
auto chars = s.c_str();
const int len = s.size();
bool flag = true;
char prev = 0;
int scientificSignIndex = 0;
// +00123.456e-789
for (int i = 0; i < len; i++)
{
char ch = chars[i];
if (i >= 1)
{
prev = chars[i - 1];
}
if (isdigit(ch))
{
digitCount += 1;
}
else
{
if (isPlusSign(ch))
{
plusSignCount += 1;
// 如果 + 存在, 那么最多存在两个
if (plusSignCount > 2)
{
flag = false;
break;
}
// 如果 + 不在首位,那么前一个字符必须是 [e,E], 并且不能出现在最后以为
if (i > 0 && (!isScientificSign(prev) || i == (len - 1)))
{
flag = false;
break;
}
}
else if (isSubstractSign(ch))
{
substractSignCount += 1;
// 如果 - 存在, 那么最多存在两个
if (plusSignCount > 2)
{
flag = false;
break;
}
// 如果 - 不在首位,那么前一个字符必须是 [e,E]
if (i > 0 && (!isScientificSign(prev) || i == (len - 1)))
{
flag = false;
break;
}
}
else if (isDotSign(ch))
{
// 不能只包含一个 .
if (0 == i && 1 == len)
{
flag = false;
break;
}
dotSignCount += 1;
// 如果 . 存在, 则只能存在一个
if (dotSignCount > 1)
{
flag = false;
break;
}
// . 不能在 [e,E] 之后
if (scientificSignCount > 0)
{
flag = false;
break;
}
}
else if (isScientificSign(ch))
{
// [e,E] 不能出现在首位
if (0 == i)
{
flag = false;
break;
}
// [e,E] 不能出现在最后一位
if (i == (len - 1))
{
flag = false;
break;
}
// 如果 [e,E] 在第二位, 首位必须是数字
if (1 == i && (isPlusSign(prev) || isSubstractSign(prev) || isDotSign(prev) || !isdigit(prev)))
{
flag = false;
break;
}
scientificSignIndex = i;
scientificSignCount += 1;
// 如果 [e,E] 存在, 则只能存在一个
if (scientificSignCount > 1)
{
flag = false;
break;
}
}
else
{
// 非法字符
flag = false;
break;
}
}
}
// 必须包含数字
if (0 == digitCount)
{
flag = false;
}
return flag;
}
KHL_CALC_NAMESPACE_END
\ No newline at end of file
......@@ -4,6 +4,8 @@
#include <memory>
#include <cstring>
#include <sstream>
#include <cctype>
#include <vector>
#include "doctest/doctest.h"
#include "spdlog/spdlog.h"
......@@ -15,10 +17,20 @@ TEST_CASE("test_init")
spdlog::info("test init");
try
{
auto decimal = std::make_unique<khl::calc::Decimal>("");
auto d1 = std::make_unique<khl::calc::Decimal>("");
}
catch(khl::calc::CalcDecimalInitException e)
catch (khl::calc::CalcDecimalInitException e)
{
std::cerr << e.msg() << std::endl;;
std::cerr << e.msg() << std::endl;
}
try
{
auto d2 = std::make_unique<khl::calc::Decimal>(" ");
}
catch (khl::calc::CalcDecimalInitException e)
{
std::cerr << e.msg() << std::endl;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册