日期 | 新增或改进 |
---|---|
2024.3.30 | 1. 增加了一个对元素为数字类型的 STL 容器进行测试的新库 simpleContainerOperator 。2. 将所有的库都放入 MyLib 命名空间之中 |
2024.4.18 | 1. 修改函数名为 loger 避免和 std::log 混淆 |
2024.4.28 | 1. 在 myLogerDef.h 上增加了几个预设宏函数,可以完成简单的日志操作,避免频繁使用 loger 函数的繁琐 2. 增加一个新库: cinCheck.h 用于对 C++ 标准输入流 std::cin 进行检查 |
能完成基本的日志功能,原理就是将字符串拼凑成 ANSI
转义序列发送到标准输出流,
从而改变文本颜色,在 Windwos
和 Linux
操作系统的终端均可使用。
/**
* @brief 用户可以通过该函数简便的使用该日志库(函数名使用 loger 避免和 std::log 混淆)
*
* @tparam OutPutType 需要输出的类型
*
* @param __os 标准输出流的引用
* @param __logLevel 日志等级
* @param __out 要输出的数据,会被打包成形参包
*
* @return non-return
*/
template <typename... OutPutType>
static inline void loger(std::ostream &__os, const TerminalTextColor __logLevel, OutPutType... __out)
{
__os << __logLevel;
/*
在 WARNING 或 ERROR 类别的日志下需要带上时间信息
*/
if (__logLevel == WARNING || __logLevel == ERROR)
{
__os << '[' << getCurrentTime() << ']';
}
/**
* 通过 C++17 标准推出的折叠表达式功能,可以将形参包解包然后依次完美转发,
* 逐个向标准输出流发送数据。
*/
(void)(__os << ... << std::forward<OutPutType>(__out));
__os.flush();
__os << ORIGINAL;
}
它们可以往标准输出发送不同日志等级的字符流,避免频繁调用 loger
函数。
#define ORIGINAL_LOG(__message) loger(std::cout, ORIGINAL, __message);
#define CORRECT_LOG(__message) loger(std::cout, CORRECT, __message);
#define NOTIFY_LOG(__message) loger(std::cout, NOTIFY, __message);
#define WARNING_LOG(__message) loger(std::clog, WARNING, __message);
#define ERROR_LOG(__message) loger(std::cerr, ERROR, __message);
#define DONE loger(std::cerr, CORRECT, "Done.\n");
通过 clock()
以及 while
循环消耗掉用户指定的时间以达到延时的效果,
在 Windwos
和 Linux
操作系统的终端均可使用。
/**
* @brief 自制延时函数,用于代替 windows 库中的 Sleep()
*
* @param __millisSeconds 延时时间(毫秒)
*
* @return non-return
*/
static void delay(long int __millisSeconds)
{
clock_t startTime = clock();
while (clock() < (startTime + __millisSeconds)) {}
}
#endif // _MY_DELAY_H_
主要是在一些针对 STL 容器或仿 STL 容器的编写、学习和测试中,不用重复的编写遍历,插入容器数据等操作, 目前就只有两个函数(配合前两个库使用):
/**
* @brief 往指定标准输出流发送 Container 容器的相关信息和数据(只适用于元素为数字类型的 STL 容器)。
*
* @tparam Container STL 容器类型
*
* @param __os 标准输出流的引用
* @param __container 要发送给输出流的容器的引用
* @param __eachLineCount 每一行输出 `__eachLineCount` 个元素后换行,默认为 5
*
* @return non-return
*/
template <typename Container>
void showContainerToStream(std::ostream &__os, const Container &__container, std::size_t __eachLineCount = 5)
{
using namespace MyLoger;
using MyDelay::delay;
loger(__os, NOTIFY, "This Container size = ", __container.size(), '\n');
std::size_t containerIndex = 0L;
std::for_each(__container.cbegin(), __container.cend(),
[&__os, &containerIndex, &__eachLineCount](const decltype((*__container.cbegin())) &n)
{
__os << n << ' ';
delay(45);
if (containerIndex % __eachLineCount == __eachLineCount - 1)
{
__os << std::endl;
}
++containerIndex;
});
__os << std::endl;
}
/**
* @brief 往一个容器里面插入随机的数据,只适用于元素为数字类型的 STL 容器。
*
* @tparam __Container STL 容器类型
*
* @param __container 一个 STL 容器的引用,但这个容器的元素最好是数字类型
* @param __limit 随机数生成的返回不超过这个值
* @param __randomCount 生成的次数(默认为 10 次)
* @param __deviationVal 误差值,用于随机生成小数,不填就为 0
*
* @return non-return
*/
template <typename __Container>
void pushRandomValue(__Container &__container, int __limit, std::size_t __randomCount = 10, double __deviationVal = 0.0)
{
for (std::size_t randomIndex = 0; randomIndex < __randomCount; ++randomIndex)
{
__container.push_back(std::rand() % __limit + __deviationVal);
}
}
主要是为了防止使用 >>
运算符往 std::cin
发送数据时,因输入不符合数据类型导致的程序错误(比如意外终止或进入不一致状态),核心函数如下所示:
/**
* @brief 在对数字类型的数据使用 >> 运算符进行输入时,对标准输入流进行检查,
* 若不符合数据格式的输入(比如用户输入非数字字符)就清理标志位并忽略此次输入。
*
* @param __is 标准输入流的引用
* @param __errMessage 当出现意外输入时所报的错误消息
*
* @return 输入数据是否合规
*/
static inline bool istreamStateCheck(std::istream &__is, const std::string &__errMessage)
{
using namespace MyLib::MyLoger;
if (__is.fail())
{
ERROR_LOG(__errMessage);
__is.clear();
__is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return false;
}
return true;
}
/**
* @brief 封装对数字类型输入格式和范围的检查,
* 用来过滤输入垃圾数据避免程序意外终止或进入不一致状态。
*
* @tparam DataType 输入数据的类型
* @tparam InputRule 用户为输入的数字范围所指定的规则,通常是 `Lamba` 表达式
*
* @param __is 标准输入流的引用
* @param __member 要输入的数据类型
* @param __messages 针对不同的情况输出的消息结构体,需要在外部实例化
* @param __rangeRule 为输入的数字范围所指定的规则,默认情况下永远返回 true
*
* @return non-return
*/
template <typename DataType, typename InputRule = std::function<bool(DataType)>>
static inline void istreamInputAndCheck(
std::istream &__is, DataType &__member,
const MessageStrings &__messages, InputRule __rangeRule = [](DataType) { return true; }
)
{
using namespace MyLib::MyLoger;
using MyDelay::delay;
while (true)
{
NOTIFY_LOG(__messages.promptMessage);
__is >> __member;
if (!istreamStateCheck(__is, __messages.errorMessage))
{
delay(800); continue;
}
if (!__rangeRule(__member))
{
ERROR_LOG(__messages.outRangeMessage);
eatLine();
continue;
}
break;
}
}