跨年夜干了个这——一个自适应字符窗口打印器

效果如下图,标题和版权信息,代码在文末

 


/*************************************************************************
** Desc     : PrintBlock
** Param    : [in] iStartEnd 两端偏移量
**          : [in] pString 要打印的字符,不能包含换行符
** Return   :
** Author   : hicker
*************************************************************************/
void PrintBlock(int nWindow, int nMaxChars, int iStartEnd, const char *pString)
{
	int nString = strlen(pString);
	int rString = (nString / (nMaxChars + 1)) + 1;
	for (int i = 0; i < rString; i++)
	{
		char strFmt[32] = { 0 };
		sprintf(strFmt, "%%-%dc", iStartEnd);
		printf(strFmt, '|');
		int cTitle = (i + 1 == rString && nString != nMaxChars) ? (nString % nMaxChars) : nMaxChars;
		for (int j = 0; j < cTitle; j++)
		{
			printf("%c", pString[i*nMaxChars + j]);
		}
		for (int x = 0; x < (nWindow - iStartEnd - cTitle - 1); x++) printf(" ");
		printf("|\n");
	}
}

/*************************************************************************
** Desc     : PrintW
**				+=================+
**				|      标题       |
**				|-----------------|
**				| 内容1           |
**				| 内容2           |
**				|-----------------|
**				|  1.确定         |
**              |  2.取消         |
**				|-----------------|
**				|      腾讯       |
**				^^^^^^^^^^^^^^^^^^^
** Param    : [in] pTitle 标题。自动居中,不可包含换行符,会自动换行
**          : [in] pContent 内容。最多不能超过16个换行符,且每行最多128个字符
**          : [in] pTips 提示。最多不能超过16个换行符,且每行最多128个字符
**          : [in] pAppVer 软件名或版权。不可包含换行符
**          : [in] nWidth 字符窗口宽度。小于5时取默认值,同时如果设置或最
**					终内部计算出的nWidth大于当前控制台窗口最大宽度,将会显示凌乱
** Return   :
** Author   : hicker
*************************************************************************/
void PrintW(const char *pTitle, const char *pContent, const char *pTips, const char *pAppVer = NULL, int nWidth = 0) {
	// 原始Title
	int nTitle = strlen(pTitle);

	// 内容宽度最小满足[| x |],即5个字符
	if (nWidth < 5)
	{
		nWidth = nTitle + 4;
	}
	const int nMaxTitle = nWidth - 4; // 调整后的窗口内可容纳的最大Title宽
	const int nMaxContent = nMaxTitle; // 调整后的窗口内可容纳的最大Content宽
	const int nMaxAppVer = nMaxTitle; // 调整后的窗口内可容纳的最大AppVer宽
	
	// 计算Title的起始位置和所需要的行数
	int rTitle = (nTitle / (nMaxTitle + 1)) + 1;
	int iTitle = 2; // 先假设一行容纳不下,所以应该等于2;
	if (nWidth >= nTitle + 4)
	{ // 若一行能够容纳
		iTitle = (nWidth - nTitle) / 2;
	}

	// 计算Content起点
	int iContent = 1;
	// 计算Tips起点
	int iTips = 2;

	// 原始AppVer
	int nAppVer = strlen(pAppVer);
	// 计算AppVer的起始位置和所需要的行数
	int rAppVer = (nAppVer / (nMaxTitle + 1)) + 1;
	int iAppVer = 2; // 先假设一行容纳不下,所以应该等于2;
	if (nWidth >= nAppVer + 4)
	{ // 若一行能够容纳
		iAppVer = (nWidth - nAppVer) / 2;
	}

	//**********依据以上值打印所有***********
	//打印上沿和Title
	printf("+");
	for (int i = 0; i<nWidth - 2; i++) printf("=");
	printf("+\n");
	PrintBlock(nWidth, nMaxTitle, iTitle, pTitle);

	//打印上沿和Content
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
	char szRowColContent[16][128] = { 0 }; // 此设置要求Content最多不能超过16个换行符,且每行最多128个字符
	int nRowContent = StrUtil::Split(pContent, "\n", (char**)szRowColContent, (16 << 16) | 128);
	for (int i = 0; i < nRowContent; i++) PrintBlock(nWidth, nMaxContent, iContent, szRowColContent[i]);

	//打印上沿和Tips
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
	char szRowColTips[16][128] = { 0 }; // 此设置要求Content最多不能超过16个换行符,且每行最多128个字符
	int nRowTips = StrUtil::Split(pTips, "\n", (char**)szRowColTips, (16 << 16) | 128);
	for (int i = 0; i < nRowTips; i++) PrintBlock(nWidth, nMaxContent, iTips, szRowColTips[i]);
	
	//打印上沿和szAppVer
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
	PrintBlock(nWidth, nMaxAppVer, iAppVer, pAppVer);

	// 打印下沿
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf("_");
	printf("|\n");
}


int main()
{
	PrintW("自适应字符窗口", "1.转发器;\n2.网站微服务;\n3.人生选择器;", "①确定\n②取消", "腾讯科技有限公司@2019", 70);

	getchar();
}

 

Guess you like

Origin blog.csdn.net/xk641018299/article/details/103789584