📄 zprintf.c
字号:
/****************************************************************************/
/* Module Name: COMMON File Name: zprintf.c */
/* Create Date: 2003-5-20 11:57 Author : R.Z.Tian */
/* Function : print function from memory by format string */
/* Version : 1.0 */
/*--------------------------------------------------------------------------*/
/* History : */
/* Date Version Person Activies */
/* 2003.05.20 1.0.0 RZ.Tian Create */
/*--------------------------------------------------------------------------*/
/*==========================================================================*/
/* 支持的百分符"%"打印控制格式说明: */
/*--------------------------------------------------------------------------*/
/* a - 取数控制符(不在打印输出中处理) */
/* b - 二进制数 */
/* c - 一个字符 */
/* d - 带符号的十进制数 */
/* e,E - 科学计数法形式的浮点数输出,指数符'e'小写或大写 */
/* f - 浮点数输出,默认小数点后6位精度 */
/* g,G - 选择进行的浮点数输出,采用"e,E"格式时指数符相应改变 */
/* i - 带符号的十进制数 */
/* k - 从参数列中跳过数个字节或者比特位数据 */
/* n - 向给定的内存地址填充当前打印了的字符计数 */
/* o - 八进制数 */
/* u - 无符号的十进制数 */
/* p - 指针 */
/* s - 字符串 */
/* x,X - 十六进制数,'a-f'根据'x,X'决定是采用小写还是大写 */
/* zI - 自定义IP地址 */
/* zM - 自定义IMSI */
/*--------------------------------------------------------------------------*/
/* 前缀使用说明: */
/*--------------------------------------------------------------------------*/
/* h - 整数长度限定 */
/* 两字节长度,当数据值超过65535时截掉高位部分 */
/* l,L - 整数长度限定 */
/* 四字节长度,作为默认值,填与不填造成的结果一样 */
/* ddd - 数据宽度或精度长度定义 */
/* 非'0'字符前导的连续数值 */
/* . - 精度描述指示, */
/* 依赖于其后面的数值确定精度显示宽度:当显示的数值是浮点数据时,*/
/* 即小数长度,如果数据不是浮点而是整数时,则以前缀"0"补足精度长 */
/* 度,这一点与普通意义上的精度定义不一样,普通意义上显示整数时 */
/* 精度符不起作用 */
/* * - 从参数表中取打印数据宽度或精度定义 */
/* 0 - 输出字符串以0作为前缀。对于数值串,精度限定符可以起到相同作用 */
/* - 空格,仅对十进制整数或者浮点数据有效,当结果为正时前导1个空格 */
/* + - 打印符号或者提示符,如十进制整数或浮点数据的"+"、"-"号,八进 */
/* 制数的"O ",十六进制数的"0x " IMSI的"IMSI ", IP的"IP: "等,这 */
/* 与普通意义上的定义略有不同,普通意义上"+"对非十进制整数或浮点 */
/* 数不起作用,八进制数或十六进制数据要打印提示符使用"#"号标识 */
/* - - 左对齐符,打印出的数据默认是靠右对齐的,以'-'切换为左对齐 */
/* # - 切换标识,这个前缀的使用含义是,当实际输出的字符宽度超出限定 */
/* 宽度时,就突破限制原样打印。否则就会依据对齐符在左端或右端打 */
/* 上"*"号,表明数据不可打印。左对齐时高位的数据是有效的,右对齐 */
/* 时低位的数据是有效的(在输出宽度超出宽度限定时),在宽度未限定 */
/* 时该控制符不起作用 */
/* "#"还有的一个作用是在宽度正常没有超出范围时,限定提示符的位置 */
/* 向左对齐,而不是紧靠在数据串的前面 */
/*--------------------------------------------------------------------------*/
/* 补充说明: */
/*--------------------------------------------------------------------------*/
/* 1. 鉴于我们使用的打印格式控制前缀,大多限在"-","0","+",宽度精度等,*/
/* 对于我所补充的异常情况处理大多数是使用不到的,所以有部分更正,这样 */
/* 的定义更为直观,更容易为大家理解和接受 */
/* 2. 增强的功能体现在"a"控制符。即我所要打印输出的参数不是按通常意义上 */
/* 系统的默认值处理的。比如我知道我要输出的这个参数在参数列表中只占几 */
/* 个字节或比特位,那么我就限定从参数表中取出这么多个字节数据或者比特 */
/* 位并进行打印输出。当"a"格式符前没有"."点时,就按字节取,至于按比特 */
/* 取数据的规则,请参照可能存在的文档。另外,对于当前数据存储字节序与 */
/* 本机不同的情况,还可以通过取数格式声明"+"或者"-"号指明是高阶字节序 */
/* (高阶字节低地址)还是低阶字节序(低阶字节低地址),甚至还可以通过"+" */
/* 和"-"确定位阶序 */
/* 3. "*"号控制符及"n"控制符相信是大家不常用的,没有对其功能作任何增强, */
/* 即没有取数定义,一律按系统默认值处理 */
/*==========================================================================*/
/*--------------------------------------------------------------------------*/
/* 参数列表取数默认值,与机型及编译系统有关,可根据需要进行宏定义或切换 */
/*--------------------------------------------------------------------------*/
#define PrnTakeDataBytesDft_M 4 /* 默认取数据的字节长度 */
#define PrnTakeFloatBytesDft_M 8 /* 默认取浮点数的字节数 */
#define PrnTakePtrBytesDft_M 4 /* 默认取指针数据字节数 */
#define PrnTakeCharBytesDft_M 4 /* 默认取字符数据字节数 */
#define PrnTakeImsiBytesDft_M 8 /* 默认取IMSI的字节数 */
#define PrnTakeIpBytesDft_M 4 /* 默认取IP地址的字节数 */
/*--------------------------------------------------------------------------*/
/* 浮点数移码定义,可根据需要进行宏定义或切换 */
/*--------------------------------------------------------------------------*/
#define MostSigBitHiden_M 1 /* 隐含最高有效位 */
#define FloatZeroShift_M 0x7f /* 浮点数指数0移码数 */
#define FloatPowerBits_M 8 /* 浮点数指数有效比特数 */
#define FloatMantisBits_M 23 /* 浮点数尾数有效比特数 */
#define DoublePowerBits_M 11 /* 双精度数指数有效比特数 */
#define DoubleZeroShift_M 0x3ff /* 双精度数指数0移码数 */
#define DoubleMantisBits_M 52 /* 浮点数尾数有效比特数 */
/*--------------------------------------------------------------------------*/
/* 数据串长度限制定义 */
/*--------------------------------------------------------------------------*/
#define MaxPrnBufDftLen_M 1600 /* 最大的打印缓存长度 */
#define MaxPrnDataArrayLen_M 1024 /* 默认数据参数列表长度 */
#define MaxBinDigitLen_M 70 /* 最大的二进制数串长度 */
#define MaxOctDigitLen_M 30 /* 最大的八进制数串长度 */
#define MaxDecDigitLen_M 22 /* 最大的十进制数串长度 */
#define MaxHexDigitLen_M 16 /* 最大的十六进制数串长度 */
#define MaxFltDigitLen_M 30 /* 最大的浮点数串长度 */
#define MaxCharDigitLen_M 4 /* 最大的字符值数串长度 */
#define MaxImsiDigitLen_M 20 /* 最大IMSI数值串长度 */
#define MaxIpDigitLen_M 40 /* 最大IP数值串长度 */
#define FltE_FmtPowerLen_M 3 /* 浮点数科学计数法指数长度*/
/*--------------------------------------------------------------------------*/
/* 数据宽度输出限制定义 */
/*--------------------------------------------------------------------------*/
#define PrnWidthDft_M -1 /* 默认输出数据宽度,不限 */
#define PrnPreciDft_M 6 /* 默认输出数据(小数)精度 */
/*--------------------------------------------------------------------------*/
/* 普通数据类型定义 */
/*--------------------------------------------------------------------------*/
#define LONG long
#define BYTE unsigned char
#define DWORD unsigned long
#define ULONG unsigned long
#define USHORT unsigned short
#define WORD unsigned short
#define SHORT short
#define NULL 0
/*--------------------------------------------------------------------------*/
/* 格式化打印声明相关标志量及取得待打印操作数的相关控制变量结构 */
/*--------------------------------------------------------------------------*/
typedef struct
{
BYTE bType; /* 显示数据格式 */
BYTE bSubType; /* 显示数据子格式 */
BYTE bMod; /* 采用半长型或者长型打印标识 */
BYTE bTakeDataDecl; /* 取数据格式声明 */
LONG lWidth; /* 打印数据宽度 */
LONG lPrecision; /* 数据精度 */
BYTE bPreChar; /* 前导字符, ' '或'0'或无填充 */
BYTE bRight; /* 右对齐标志 */
BYTE bAlter; /* 提示符显示功能标识 */
BYTE bPlus; /* 打印正负号标识 */
BYTE bBigEndian; /* 取数阶标志 */
BYTE bBitTake; /* 按位取数标志 */
WORD wTakeBytes; /* 取数的字节数 */
BYTE bBitBigEndian; /* 按位取数阶标志 */
BYTE bRemainBits; /* 按位取数时剩余值有效比特数 */
WORD wTakeBits; /* 取数的比特数 */
DWORD dwRemainVal; /* 按位取数时剩余未用的值 */
DWORD dwReadVal; /* 待打印的数据值 */
} PrnFormatGlb_T;
typedef struct
{
DWORD dwH; /* 高阶字段值 */
DWORD dwL; /* 低阶字段值 */
} QWORD;
typedef struct
{
BYTE bNegtive; /* 正负数标识 */
BYTE bMantisBits; /* 尾数有效长度 */
LONG lPower; /* 数值阶 */
QWORD qwMantis; /* 尾数 */
} PFLOAT;
/*--------------------------------------------------------------------------*/
/* 宏函数 */
/*--------------------------------------------------------------------------*/
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define isDigit(a) \
(((a) <= '9') && ((a) >= '0'))
#define isLetter(a) \
((((a) <= 'z') && ((a) >= 'a')) || (((a) <= 'Z') && ((a) >= 'A')))
#define isPermitSpace(a) \
(((a) == ' ') || ((a) == '\t') || ((a) == '\n') || ((a) == '\v'))
#define isFormatEndChar(a) \
(((a) == 'd') || ((a) == 'u') || ((a) == 'x') || ((a) == 'X') || \
((a) == 'p') || ((a) == 's') || ((a) == 'k') || ((a) == 'z') || \
((a) == 'o') || ((a) == 'b') || ((a) == 'c') || ((a) == 'f') || \
((a) == 'e') || ((a) == 'E') || ((a) == 'g') || ((a) == 'G') || \
((a) == 'n') || ((a) == 'i'))
/*--------------------------------------------------------------------------*/
/* Function name : tranBits() */
/* Description : 将数据按比特位逆序转换 */
/* Input : dwTranVal - 待转换的数据 */
/* : bBits - 数据的有效位数(待转换位数) */
/* Output : 无 */
/* Return : 无 */
/* Global Var : 转换后的数 */
/* Author/Date : R.Z.Tian/2003-5-22 08:22下午 */
/* Note : 从低阶往高阶数比特位有效 */
/*--------------------------------------------------------------------------*/
static DWORD tranBits(DWORD dwTranVal, BYTE bBits)
{
BYTE bCount;
DWORD dwTempVal = 1, dwRetVal = 0;
for (bCount = 0; bCount < bBits / 2; bCount++, dwTempVal <<= 1)
{
dwRetVal += (dwTranVal & dwTempVal) << (bBits - 1 - bCount * 2);
dwRetVal += (dwTranVal >> (bBits - 1 - bCount * 2)) & dwTempVal;
}
return dwRetVal;
}
/*--------------------------------------------------------------------------*/
/* Function name : isBigEndian() */
/* Description : 测试本机的字节阶是否大数阶(低地址更高阶) */
/* Input : 无 */
/* Output : 无 */
/* Return : 真或假 */
/* Global Var : 无 */
/* Author/Date : R.Z.Tian/2003-5-19 20:11 */
/* Note : */
/*--------------------------------------------------------------------------*/
LONG isBigEndian(void)
{
union
{
BYTE cChar[2];
WORD wShort;
} u1;
u1.cChar[0] = 1, u1.cChar[1] = 2;
if (u1.wShort == (1 << 8) + 2)
{
return 1;
}
return 0;
}
/*--------------------------------------------------------------------------*/
/* Function name : GetTakeDataFormat() */
/* Description : 获取从参数表中取数方式到打印控制结构 */
/* Input : pbFmtStr - 格式控制串的起始地址 */
/* : ppbData - 参数列表指针 */
/* Output : ptFmt - 控制格式结构地址 */
/* : ppbData - 参数列表指针 */
/* Return : 下一个打印控制字符指针. */
/* Global Var : 无 */
/* Author/Date : R.Z.Tian/2003-5-20 11:57下午 */
/* Note : */
/*--------------------------------------------------------------------------*/
static char *GetTakeDataFormat(char *pbFmtStr, PrnFormatGlb_T *ptFmt, BYTE **ppbData)
{
BYTE bTakeStep = 0, bTakeBytesDecl = 0, bTakeBitsDecl = 0;
char *pbRead = pbFmtStr;
LONG lFmtVal;
ptFmt->bBigEndian = isBigEndian() ? 1 : 0;
ptFmt->wTakeBytes = PrnTakeCharBytesDft_M;
ptFmt->bTakeDataDecl= 1;
ptFmt->bBitTake = 0;
ptFmt->bBitBigEndian= 1;
ptFmt->wTakeBits = 0;
/*----------------------------------------------------------------------*/
/* 获得取数格式 ...(-,+)(ddd)(. (-,+)(ddd))(a )... */
/* 取数步骤: s0 s1 s2 s3 s4 s5 s6 s7 */
/* 格式串最多有5个部分,在相应的状态如果取得的格式串与期望不符就退出 */
/*----------------------------------------------------------------------*/
while (pbRead[0] != '\0')
{
if (pbRead[0] == 'a')
{
pbRead++; break;
}
if (pbRead[0] == '-' || pbRead[0] == '+')
{
if (bTakeStep == 0)
{
bTakeStep = 1;
ptFmt->bBigEndian = (pbRead[0] == '-') ? 0 : 1;
}
else if (bTakeStep == 3)
{
bTakeStep = 4;
ptFmt->bBitBigEndian = (pbRead[0] == '-') ? 0 : 1;
}
else
{
break;
}
pbRead++; continue;
}
if (pbRead[0] == '.')
{
if (bTakeStep < 3)
{
bTakeStep = 3, ptFmt->bBitTake = 1;
}
else
{
break;
}
pbRead++; continue;
}
if (pbRead[0] == '*' || isDigit(pbRead[0]))
{
/*--------------------------------------------------------------*/
/* 取得数据长度,从格式串中取或者从参数列表中取 */
/*--------------------------------------------------------------*/
if (pbRead[0] == '*')
{
lFmtVal = (LONG)(*(char *)(*ppbData)), *ppbData++, pbRead++;
}
else for (lFmtVal = 0; isDigit(pbRead[0]); pbRead++)
{
lFmtVal = lFmtVal * 10 + (pbRead[0] - '0');
}
if (bTakeStep < 3)
{
bTakeStep == 2, bTakeBytesDecl = 1, ptFmt->bTakeDataDecl |= 2;
if (lFmtVal < 0)
{
ptFmt->wTakeBytes = (WORD)(-lFmtVal), ptFmt->bBigEndian = 0;
}
else
{
ptFmt->wTakeBytes = (WORD)lFmtVal;
}
ptFmt->wTakeBytes = min(ptFmt->wTakeBytes, 0x1000);
}
else /* if (bTakeStep >= 3 && bTakeStep < 5) */
{
bTakeStep = 5, bTakeBitsDecl = 1, ptFmt->bTakeDataDecl |= 4;
if (lFmtVal < 0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -