📄 z_func.c
字号:
/************ 常用函数汇总 ************/# include <stdio.h># include <string.h># include <stdlib.h># include <stdarg.h># include <time.h># include <fcntl.h> static struct s_log { /* 日志结构 */ FILE *fp; /* 描述符 */ unsigned int msize; /* 字节上限 */ unsigned char path[256]; /* 路径 */ } LOG;/**************************** 判断字符串是否全部为数字字符 ****************************/int z_adigit(char *s){ if( s == NULL ) return(0); while( *s ) if( ! isdigit( *( s++ ) ) ) return(0); return(1);}/**************** 字符串转换为大写 ****************/int z_atoupper(char *s){ if( s == NULL || *s == 0 ) return(0); while( *s ) *(s++) = toupper(*s); return(0);}/**************** 剔除头部空白字符 ****************/int z_ltrim(char *s){ int f = 0; char *p1, *p2; if( s == NULL || *s == 0 ) return(0); p1 = s; p2 = s; while( *p1 ) { if( f == 1 || ! isspace(*p1) ) { if( f == 0 ) f = 1; if( *p2 != *p1 ) *p2 = *p1; p2++; } p1++; } *p2 = 0; return(0);}/**************** 剔除尾部空白字符 ****************/int z_rtrim(char *s){ char *p; if( s == NULL || *s == 0 ) return(0); p = &s[ strlen(s) - 1 ]; while( 1 ) { if( isspace(*p) ) *p -- = 0; else break; } return(0);}/**************** 剔除头尾空白字符 ****************/int z_lrtrim(char *s){ z_ltrim(s); z_rtrim(s); return(0);}/**************** 剔除全部空白字符 ****************/int z_atrim(char *s){ char *p1, *p2; if( s == NULL || *s == 0 ) return(0); p1 = s; p2 = s; while( *p1 ) { if( isspace(*p1) == 0 ) { *p2 = *p1; p2++; } p1++; } *p2 = 0; return(0);}/********** 字符串反序 **********/int z_revs(char *s){ char *p1, *p2, c; if( s == NULL || *s == 0 ) return(0); p1 = s; p2 = &s[ strlen(s) - 1 ]; while( 1 ) { if( p2 - p1 == 0 ) break; else { c = *p1; *p1 = *p2; *p2 = c; if( p2 - p1 == 1 ) break; } p1++; p2--; } return(0);}/*********************************************** 函数描述: 转换double值为以千分符','分隔的字符串 参数说明: double d 数值 int n 结果小数点后位数(<=8) ***********************************************/char *z_dcomma(double d, int n){ int i, j, flag = 0; /* 整数部分 */ char *p, t[50]; static char s[50]; if( n > 8 ) n = 8; else if( n < 0 ) n = 0; if( n == 0 ) flag = 1; memset(t, 0, sizeof(t)); memset(s, 0, sizeof(s)); sprintf(t, "%.*lf", n, d); p = t + strlen(t) - 1; for( i = 49, j = 0; p - t >= 0; p-- ) { if( flag == 1 ) j++; else if( *p == '.' ) flag = 1; s[i--] = *p; if( j == 3 && p - t && *(p-1) != '-' ) { j = 0; s[i--] = ','; } } return( s + i + 1);}/******************************************** 函数描述:替换字符串中指定的子串 入口参数:char *t 目标串 char *s 源串 char *a 被替换子串 char *b 替换子串 int n 替换次数(0表示全部替换) 备注 :当替换串的长度<=被替换串的长度时, 可置目标串为NULL,结果存放于源串; ********************************************/int z_sswap(char *t, char *s, char *a, char *b, int n){ char *p; int len1, len2; len1 = strlen(a); len2 = strlen(b); if( len1 < 1 || n < 0 ) return(-1); /* 参数无效 */ if( t == NULL ) { if( len2 > len1 ) return(-2); /* 参数无效 */ p = s; } else p = t; if( n == 0 ) n = -1; while( *s ) { if( n && strncmp(s, a, len1) == 0 ) { /* 匹配 */ strcpy(p, b); s += len1; p += len2; if( n > 0 ) n--; } else { *p = *s; s++; p++; } } *p = 0; return(0);}/**************************************************** 函数描述:从分隔符分隔的字符串中依次读取各域的值; 入口参数:char **s 由分隔符分隔的字符串 char *d 存放读取的当前域值 int *n 当前域实际字符数 int l 限定当前域长度,丢弃多余字符 char *b 分隔串 返回值 :0 至串尾 1 有后续域 备注 :无需改变参数,循环调用可顺序读取各域的值; ****************************************************/int z_get_fieldv(char **s, char *d, int *n, int l, char *b){ int i, bl; if( (bl = strlen(b)) < 1) return(-1); /* 参数无效 */ for(i = 0, *n = 0; *(*s); (*s)++, (*n)++ ) { if( strncmp((*s), b, bl) == 0 ) { (*s) += bl; break; } if( i < l ) { d[i] = *(*s); i++; } } d[i] = 0; if( *(*s) == 0 ) return(0); return(1);}/**************************************************** 函数描述:以字符串形式表示系统日期(或指定的time_t值) 入口参数:char *s 结果字符串 int l 指定结果值长度(含结尾空字符) char *dt 转换格式 time_t now 待转换日期值(0=当前系统日期) 预定义格式: "t" HH:MI:SS "Y" YYYY "y" YY "m" MM "d" DD "f" YYYYMMDDHHMISS "l" YYYY/MM/DD HH:MI:SS "i" YYMMDDHHMISS032+ smpp3.3 ****************************************************/int z_get_dt(char *s, int l, char *dt, time_t now){ int len; time_t tv; char format[16]; struct tm tm; len = strlen(dt); if( l < 1 || len < 1 ) return(-1); memset(&tm, 0, sizeof(tm)); memset(format, 0, sizeof(format));/* ** 设置时区、夏时制等全局变量 ** tzset();*/ if( now == 0 ) tv = time( (time_t *) 0 ); else tv = now; localtime_r(&tv, &tm); if( len == 1 ) switch( dt[0] ) { case 't': strcpy(format, "%T"); break; case 'Y': strcpy(format, "%Y"); break; case 'y': strcpy(format, "%y"); break; case 'm': strcpy(format, "%m"); break; case 'd': strcpy(format, "%d"); break; case 'f': strcpy(format, "%Y%m%d%H%M%S"); break; case 'l': strcpy(format, "%Y/%m/%d %T"); break; case 'i': strcpy(format, "%y%m%d%H%M%S032+"); break; default: strcpy(format, dt); break; } else strcpy(format, dt); return( strftime(s, l+1, format, &tm) );}/****************************************** 函数描述:转换时间形式,并返回时间的秒表示 字符串 => tm 结构 入口参数:char *s 字符串形式的时间值 出口参数:struct tm *tm 转换后的结构 返回值 :time_t 时间的秒表示 ******************************************/time_t z_secs_dt(char *s, struct tm *tm){ int b; char v[8]; struct tm tm1; /* 如果 tm 为空,分配一临时空间 */ if( tm == (struct tm *)NULL ) tm = &tm1; /* 设置时区、夏时制等全局变量 */ tzset(); /* 分解字符串日期值 */ memset(tm, 0, sizeof(struct tm)); strncpy(v, s, 4); v[4] = 0; /* 年 */ tm->tm_year = atoi(v) - 1900; strncpy(v, s + 4, 2); v[2] = 0; /* 月 */ tm->tm_mon = atoi(v) - 1; strncpy(v, s + 6, 2); v[2] = 0; /* 日 */ tm->tm_mday = atoi(v); strncpy(v, s + 8, 2); v[2] = 0; /* 时 */ tm->tm_hour = atoi(v); strncpy(v, s + 10, 2); v[2] = 0; /* 分 */ tm->tm_min = atoi(v); strncpy(v, s + 12, 2); v[2] = 0; /* 秒 */ tm->tm_sec = atoi(v); tm->tm_isdst = -1; /* 由 mktime 自行决定夏时制的使用 */ return( mktime(tm) );}/**************************************************** 函数描述:验证时间合法性 入口参数:char *s 字符串形式的时间(yyyymmddhh24miss) ****************************************************/int z_valid_dt(char *s){ char t[16]; struct tm tm; /* 查验字符串长度 */ if( strlen(s) != 14 ) return(-1); /* 判断是否全部为数字字符 */ if( ! z_adigit(s) ) return(-2); /* 转换时间形式 */ if( z_secs_dt(s, &tm) < 0 ) return(-3); /* 转换后的字符串形式 */ memset(t, 0, sizeof(t)); sprintf(t, "%04d%02d%02d%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); /* 比较调整前后的 tm 结构值 */ return( strncmp(t, s, 14) );}/************************************************************ 函数描述:计算某一时间点在指定间隔后的表示(yyyymmddhh24miss) 入口参数:char *s 字符串形式的时间值 int itv 时间间隔(秒) ************************************************************/time_t z_next_dt(char *s, int itv){ time_t b; if( (b = z_secs_dt(s, NULL)) < 0 ) return(b); z_get_dt(s, 14, "f", b + itv); return(b + itv);}/****************** 计算进程已运行时间 ******************/int z_pastime(char *s, time_t t){ time_t tv; struct tm tm1; tzset(); tv = time( (time_t *) 0 ); tv -= t; tv += timezone; localtime_r(&tv, &tm1); if( tm1.tm_isdst ) { tv += 3600; localtime_r(&tv, &tm1); } sprintf(s, "%d年%d天%d时%d分%d秒", tm1.tm_year - 70, tm1.tm_yday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); return(0);}/******************************************* 函数描述:验证路径的合法性;并剔除尾部/符号 入口参数:char *pdir 路径名称 返回值 : 0 合法 -1 路径空 -2 路径不可访问 -3 非目录 -4 不可读(或进入) *******************************************/int z_valid_dir(char *pdir){ struct stat st; if( pdir == NULL || pdir[0] == 0 ) return(-1); memset(&st, 0, sizeof(st)); if( stat(pdir, &st) < 0 ) return(-2); if( ! S_ISDIR(st.st_mode) ) return(-3); if( access(pdir, R_OK | X_OK ) < 0 ) return(-4);/* if( level > 0 ) { if( access(pdir, W_OK) < 0 ) { printf("错误:目录 %s 不可写.\n", pdir); return(-5); } } if( st.st_uid != geteuid() ) { printf("错误:%s 非属主.\n", pdir); return(-6); } if( (st.st_mode & S_IRWXU) != S_IRWXU ) { printf("错误:%s 权限不足.\n", pdir); return(-7); }*/ if( pdir[ strlen(pdir) - 1 ] == '/' ) pdir[ strlen(pdir) - 1 ] = 0; return(0);}/************ 统计文件行数 ************/int z_filelines(char *file){ int i = 0; FILE *fp; if( (fp = fopen(file, "r")) == NULL ) return(-1); while( ! feof(fp) ) if( fgetc(fp) == '\n' ) i++; fclose(fp); return(i);}/****************************************** 函数描述:从配置文件中读取关键字对应的值; 并剔除关键字后紧随的一个字符 入口参数:char *file 文件 char *key 关键字(长度上限127) char *v 值 int l 值长度 返回值 : 0 成功 1 关键字无效 2 长度无效 3 文件打开失败 -1 无匹配关键字 ******************************************/int z_getkeyv(char *file, char *key, char *v, int l){ int klen, found = -1; char buf[128]; FILE *fp; klen = strlen(key); if( klen < 1 || klen > 127 ) return(1); if( l < 1 ) return(2); if( (fp = fopen(file, "r")) == NULL ) return(3); while( ! feof(fp) ) { memset(buf, 0, 128); if( fgets(buf, klen + 1, fp) == NULL ) break; if( buf[0] == '#' || buf[ strlen(buf) - 1 ] == '\n' ) continue; if( strcmp(buf, key) == 0 ) { found = 0; if( fgetc(fp) == '\n' ) break; /* 剔除紧随字符,并检查空值 */ while( l-- > 0 ) { *v = fgetc(fp); if( *v == '\n' ) break; /* 读至行尾 */ v++; } break; } /* 定位至下一行 */ while( ! feof(fp) ) if( fgetc(fp) == '\n' ) break; } *v = 0; fclose(fp); return(found);}/****************************************************** 函数描述:限制性拷贝;适用于多个源串到目标串的循环拷贝 入口参数:char *d 目标字符串 char *s 源字符串 int *l 目标串当前长度(初次调用时应置0) int m 目标串最大长度 ******************************************************/int z_limit_cp(char *d, char *s, int *l, int m){ d += *l; while( *s ) { if( *l < m ) { *(d++) = *s; (*l)++; } else break; s++; } *d = 0; return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -