⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zprintf.c

📁 打印解析处理函数, 含有浮点数处理, 无需浮点协处理器
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************/
/* 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 + -