From e558ee378867ca492ee9cecde20f28a352154ba9 Mon Sep 17 00:00:00 2001 From: rangersly <2281598291@qq.com> Date: Wed, 14 May 2025 19:39:08 +0800 Subject: [PATCH] merge usingfix ansi.md fix ADD: pro/tool/makefile add example one FIX: libs.md self log .vimrc fix auto makefile use Tab lib.md string delete --- program/c_cpp/library/libs.md | 9 +- program/c_cpp/library/self/log/log.c | 167 +++++++++++++++++++++++++++ program/c_cpp/library/self/log/log.h | 71 ++++++++++++ program/c_cpp/universal/ansi.md | 91 +++++++++++---- program/tool/makefile.md | 31 +++++ 5 files changed, 342 insertions(+), 27 deletions(-) create mode 100644 program/c_cpp/library/self/log/log.c create mode 100644 program/c_cpp/library/self/log/log.h diff --git a/program/c_cpp/library/libs.md b/program/c_cpp/library/libs.md index 701cf7b..2ec1a36 100644 --- a/program/c_cpp/library/libs.md +++ b/program/c_cpp/library/libs.md @@ -5,7 +5,7 @@ ## index - [C](#c) - - [输入/输出 stdio](#stdio) + - [输入/输出 stdio](../universal/io.md) - [资源管理和系统交互 stdlib](#stdlib) - [字符串处理 string](../universal/cstring.md) - [数学函数 math](#math) @@ -34,12 +34,7 @@ - [string hash](./self/string_hash.c) - [thread pool](./self/thread-pool.cpp) - [BIT](./self/bit.h) - ---- - -## **stdio** - -大部分内容已经完善,请参阅这里[IO](../universal/io.md) + - [LOG](./self/log/log.h) --- diff --git a/program/c_cpp/library/self/log/log.c b/program/c_cpp/library/self/log/log.c new file mode 100644 index 0000000..de43d04 --- /dev/null +++ b/program/c_cpp/library/self/log/log.c @@ -0,0 +1,167 @@ +#include "log.h" + +#ifdef NDEBUG + #define POINT_STR(str) + #define PERROR(str) +#else + #define POINT_STR(str) for(int i = 0; i < strlen(str); i++) { \ + printf("%c --- %d\n", (char)str[i], (int)str[i]);} + #define PERROR(str) printf(str);return +#endif + +static int low_show_level = LOG_INFO; +static int log_number = 1; +static FILE *log_out_fp = NULL; +static char log_head_format[LOG_HEAD_MAX_FORMAT] = "[%y-%m-%d-%n]"; +static char log_head[LOG_HEAD_MAX_FORMAT << 3]; + + +static int +get_loghead(void); +// 根据 log_head_format 生成日志头 log_head +// 有无法识别的符号返回 -1 成功返回0 + +static void +int_to_str(int num, char *restrict str); +// 将int 型数据转换成str +// 需要注意 str 要大于 int 的位数,否则将溢出 + + +void +log_setoutfile(const char *restrict filename) { + if((log_out_fp = fopen(filename, "w")) == NULL) + PERROR("LOG: log_setoutfile open file fail !\n"); + return; +} + +void +log_setlevel(int level) { + if(level < LOG_INFO || level > LOG_FATAL) { // 检测最低日志等级 + low_show_level = LOG_INFO; + PERROR("LOG: log_setlevel level is > LOG_FATAL or < LOG_INFO\n"); + } + low_show_level = level; + return; +} + +void +log_sethead(const char *restrict head) { + if(strlen(head) >= LOG_HEAD_MAX_FORMAT) + PERROR("LOG: log_sethead head so long!\n"); + strncpy(log_head_format, head, LOG_HEAD_MAX_FORMAT); + if(get_loghead()) + PERROR("LOG: log_sethead have fail char !\n"); + return; +} + +void +log_print(int level, const char *restrict message) { + if(log_out_fp == NULL) // 未设置输出文件 + log_out_fp = stdout; + if(level < LOG_INFO || level > LOG_FATAL) // 日志等级不在范围内 + PERROR("LOG: log_print level out of range !\n"); + if(level < low_show_level) // 低于最低等级的log不进行打印 + return; + + if(get_loghead() != 0) // 生成日志头 + PERROR("LOG: log_print get_loghead error\n"); + if(!fputs(log_head, log_out_fp)) // 打印日志头 + PERROR("LOG: log_print fputs_head error\n"); + + switch(level) { // 打印错误等级 + case LOG_INFO: + if(fputs("INFO:", log_out_fp)) + break; + case LOG_WARNING: + if(fputs("WARNING:", log_out_fp)) + break; + case LOG_ERROR: + if(fputs("ERROR:", log_out_fp)) + break; + case LOG_FATAL: + if(fputs("FATAL:", log_out_fp)) + break; + default: + PERROR("LOG: log_print out level is untrue !\n"); + } + + if(!fputs(message, log_out_fp)) // 打印message + PERROR("LOG: log_head fputs fail !\n"); + fputc('\n', log_out_fp); + log_number++; // 日志计数++ + return; +} + +int +get_loghead(void) { + char buf[64]; + time_t now_time = time(NULL); + clock_t core_time = clock() / CLOCKS_PER_SEC; // 以 s 为单位的 cpu 时间 + struct tm *tm_time = localtime(&now_time); + int temp; + + memset(log_head, '\0', sizeof(log_head)); // 重置日志头 + + for(int i = 0; i < strlen(log_head_format); i++) { + if(log_head_format[i] != '%') { // 非特殊字符则按正常复制 + log_head[strlen(log_head)] = log_head_format[i]; + continue; + } + + i++; + switch(log_head_format[i]) { // 特殊字符转换 + case 'y' : + strftime(buf, 64, "%Y", tm_time); + break; + case 'm' : + strftime(buf, 64, "%m", tm_time); + break; + case 'd' : + strftime(buf, 64, "%d", tm_time); + break; + case 'h' : + strftime(buf, 64, "%H", tm_time); + break; + case 'M' : + strftime(buf, 64, "%M", tm_time); + break; + case 's' : + strftime(buf, 64, "%S", tm_time); + break; + case 'n' : + int_to_str(log_number, buf); + break; + case 'c' : + int_to_str(core_time, buf); + break; + default: + return -1; + } + strcat(log_head, buf); + } + return 0; +} + +void +int_to_str(int num, char *restrict str) { + if(num < 0) + return; // 日志编号不可能小于 0 + + // 逐位提取数字(反向存储) + int start = 0; + do { + str[start++] = num % 10 + '0'; + num /= 10; + } while (num > 0); + str[start] = '\0'; + + // 反转数字部分 + char buf[16]; + strncpy(buf, str, 16); + for(int i = 0; i < strlen(buf); i++) + str[--start] = buf[i]; + return; +} + +#undef POINT_STR +#undef PERROR diff --git a/program/c_cpp/library/self/log/log.h b/program/c_cpp/library/self/log/log.h new file mode 100644 index 0000000..ad7aef4 --- /dev/null +++ b/program/c_cpp/library/self/log/log.h @@ -0,0 +1,71 @@ +// Copyright(c) 2025 Rangersly All rights reserved. +// +// function : +// Output log +// +// Author: +// Rangersly +// +// Versions: +// - 1.0 base function + +#pragma once + +#include +#include +#include + +#define LOG_INFO 0 +#define LOG_WARNING 1 +#define LOG_ERROR 2 +#define LOG_FATAL 3 + +#define LOG_HEAD_MAX_FORMAT 32 + +// 如果未定义 NDEBUG 宏,错误发生时将打印错误信息 + +extern void +log_setoutfile(const char *restrict filename); +// 设置输出文件 +// 默认输出为 stdout + +extern void +log_setlevel(int level); +// 设置最低输出日志等级,低于最低等级的日志将忽略 + +extern void +log_sethead(const char *restrict head); +// 设置日志头,最大不可超过15个字符 +// 符号表 +// %y year +// %m month +// %d day +// %h hour +// %M minute +// %s second +// %n number +// %c core time .3f + +extern void +log_print(int level, const char *restrict message); +// 输出日志 ^---等级 ^---输出信息 + + + +// EXAMPLE +/* +#include +#include "log.h" + +int main(void) { + log_setoutfile("log.out"); + log_setlevel(LOG_ERROR); + log_sethead("#%d-%h-%M-%s-%n-%c#"); + + log_print(LOG_INFO, " hello"); + log_print(LOG_WARNING, " hello"); + log_print(LOG_ERROR, " hello"); + log_print(LOG_FATAL, " hello"); + return 0; +} +*/ diff --git a/program/c_cpp/universal/ansi.md b/program/c_cpp/universal/ansi.md index 1004a2a..54dbf24 100644 --- a/program/c_cpp/universal/ansi.md +++ b/program/c_cpp/universal/ansi.md @@ -5,7 +5,7 @@ --- -## **1. 文本样式控制** +## **文本样式控制** | 转义码 | 效果 | 说明 | |---------------|--------------------|--------------------------| | `\033[0m` | 重置所有样式 | 关闭所有颜色和特效 | @@ -20,7 +20,7 @@ --- -## **2. 前景色(文本颜色)** +## **前景色** | 转义码 | 颜色 | 转义码(亮色) | |---------------|-----------|----------------| | `\033[30m` | 黑色 | `\033[90m` | @@ -34,7 +34,7 @@ --- -## **3. 背景色** +## **背景色** | 转义码 | 颜色 | 转义码(亮色) | |---------------|-----------|----------------| | `\033[40m` | 黑色 | `\033[100m` | @@ -48,23 +48,7 @@ --- -## **4. 光标控制** -| 转义码 | 作用 | -|-------------------------|--------------------------| -| `\033[A` | 光标上移 `` 行 | -| `\033[B` | 光标下移 `` 行 | -| `\033[C` | 光标右移 `` 列 | -| `\033[D` | 光标左移 `` 列 | -| `\033[;H` | 光标移动到第 `` 行、第 `` 列 | -| `\033[2J` | 清屏(整个屏幕) | -| `\033[K` | 清除从光标到行尾的内容 | -| `\033[2K` | 清除全行的内容 | -| `\033[s` | 保存光标位置 | -| `\033[u` | 恢复光标位置 | - ---- - -## **5. RGB 颜色(部分终端支持)** +## **RGB 颜色** 如果终端支持 **24-bit 真彩色**,可以使用: ```c printf("\033[38;2;;;m"); // 设置前景色(RGB) @@ -74,3 +58,70 @@ printf("\033[48;2;;;m"); // 设置背景色(RGB) ```c printf("\033[38;2;255;100;0m这是橙红色文字\033[0m\n"); ``` + +--- + +## **光标控制** +| 转义码 | 作用 | +|-------------------------|--------------------------| +| `\033[A` | 光标上移 `` 行 | +| `\033[B` | 光标下移 `` 行 | +| `\033[C` | 光标右移 `` 列 | +| `\033[D` | 光标左移 `` 列 | +| `\033[;H` | 光标移动到第 `` 行、第 `` 列 | +| `\033[J` | 清屏(光标以后) | +| `\033[1J` | 清屏(光标以前) | +| `\033[2J` | 清屏(整个屏幕) | +| `\033[K` | 清除从光标到行尾的内容 | +| `\033[1K` | 清除从光标到行首的内容 | +| `\033[2K` | 清除全行的内容 | +| `\033[s` | 保存光标位置 | +| `\033[u` | 恢复光标位置 | + +## **example** +``` +#include + +#if __STDC__ != 1 + #error "NO ansi !" +#endif + +int main(void) { + printf("-----TEXT STYLE-----\n"); + printf("\033[0m\\033[0m\033[0m\n"); + printf("\033[1m\\033[1m\033[0m\n"); + printf("\033[2m\\033[2m\033[0m\n"); + printf("\033[3m\\033[3m\033[0m\n"); + printf("\033[4m\\033[4m\033[0m\n"); + printf("\033[5m\\033[5m\033[0m\n"); + printf("\033[6m\\033[6m\033[0m\n"); + printf("\033[7m\\033[7m\033[0m\n"); + printf("\033[8m\\033[8m\033[0m\n"); + printf("\033[9m\\033[9m\033[0m\n"); + + + printf("\n-----COLOR-----\n"); + printf("\033[30m\\033[30m\033[0m - \033[90m\\033[90m\033[0m\n"); + printf("\033[31m\\033[31m\033[0m - \033[91m\\033[91m\033[0m\n"); + printf("\033[32m\\033[32m\033[0m - \033[92m\\033[92m\033[0m\n"); + printf("\033[33m\\033[33m\033[0m - \033[93m\\033[93m\033[0m\n"); + printf("\033[34m\\033[34m\033[0m - \033[94m\\033[94m\033[0m\n"); + printf("\033[35m\\033[35m\033[0m - \033[95m\\033[95m\033[0m\n"); + printf("\033[36m\\033[36m\033[0m - \033[96m\\033[96m\033[0m\n"); + printf("\033[37m\\033[37m\033[0m - \033[97m\\033[97m\033[0m\n"); + printf("\033[38;2;112;223;234m\\033[38;2;112;223;234m\033[0m\n"); + + printf("\033[40m\\033[40m\033[0m - \033[100m\\033[100m\033[0m\n"); + printf("\033[41m\\033[41m\033[0m - \033[101m\\033[101m\033[0m\n"); + printf("\033[42m\\033[42m\033[0m - \033[102m\\033[102m\033[0m\n"); + printf("\033[43m\\033[43m\033[0m - \033[103m\\033[103m\033[0m\n"); + printf("\033[44m\\033[44m\033[0m - \033[104m\\033[104m\033[0m\n"); + printf("\033[45m\\033[45m\033[0m - \033[105m\\033[105m\033[0m\n"); + printf("\033[46m\\033[46m\033[0m - \033[106m\\033[106m\033[0m\n"); + printf("\033[47m\\033[47m\033[0m - \033[107m\\033[107m\033[0m\n"); + printf("\033[48;2;112;223;234m\\033[48;2;112;223;234m\033[0m\n"); + + printf("\033[0m\n"); + return 0; +} +``` diff --git a/program/tool/makefile.md b/program/tool/makefile.md index aa9ec3e..f26df45 100644 --- a/program/tool/makefile.md +++ b/program/tool/makefile.md @@ -22,6 +22,7 @@ - [使用循环](#使用循环) - [执行外部命令](#执行外部命令) - [](#) +- [EXAMPLE](#example) --- @@ -471,3 +472,33 @@ FILE = ../file.c REAL_PATH = $(realpath $(FILE)) ``` + +--- + +## **example** + +1. 通用模板 + +```makefile +# 定义编译器和编译选项 +CC = gcc +CFLAGS = -c +LDFLAGS = + +# 定义目标可执行文件名 +TARGET = main + +# 获取所有.c文件对应的.o文件 +OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) $^ -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $< -o $@ + +clean: + rm -f *.o *.out $(TARGET) +```