MFC实现lua printf函数

lua脚本格式:

printf('123,x=%0.3f, y=%d, z=%d,%s,%c\n',x,y,z,'Hello word','A') -- 打印函数

MFC实现:

// 解析格式化数据,需要手动释放内存
void CRunLuaDlg::FmtDecode(const char* strFmt,CArgList *pArgList,char *lpFmtstr)
{
	int len = strlen(strFmt);
	int nDoublePos=1;
	int nStrPos=1;
	int nBoolPos=1;
	memset(lpFmtstr,0,sizeof(lpFmtstr));
	for(int i=0;i<len;i++)
	{
		if(strFmt[i] == '%')
		{
			for(int j=i+1;j<len && strFmt[j];j++)
			{
				char ch = strFmt[j];

				if(CArgList::IsFormatChar(ch))
				{
					int n = j-i+1;
					char buf[32] = { 0 };
					int k = 0;
					for(k=0;k<n;k++)
					{
						buf[k] = strFmt[i+k];
					}
					buf[k] = 0;
					i = j;
					char tmp[32] = { 0 };
					switch (ch)
					{
					case 'd':
						{
							double dVal = 0;
							if(pArgList->GetArgu(nDoublePos,dVal))
							{
								//printf(buf,(int)dVal);
								sprintf_s(tmp,32,buf,(int)dVal);
								nDoublePos++;
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case 'u':
						{
							double dVal = 0;
							if(pArgList->GetArgu(nDoublePos,dVal))
							{
								//printf(buf,(unsigned)dVal);
								sprintf_s(tmp,32,buf,(unsigned)dVal);
								nDoublePos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case 'c':
					case 'C':
						{
							char* str = pArgList->GetArgu(nStrPos);
							if(str != NULL)
							{
								//printf(buf,str[0]);
								sprintf_s(tmp,32,buf,str[0]);
								nStrPos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case 's':
						{
							char* str = pArgList->GetArgu(nStrPos);
							if(str != NULL)
							{
								//printf(buf,str);
								sprintf_s(tmp,32,buf,str);
								nStrPos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case 'p':
						{
							double dVal = 0;
							if(pArgList->GetArgu(nDoublePos,dVal))
							{
								//printf(buf,(int)dVal);
								sprintf_s(tmp,32,buf,(int)dVal);
								nDoublePos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case '%':
						printf(buf);
						break;
					case 'f':
						{
							double dVal = 0;
							if(pArgList->GetArgu(nDoublePos,dVal))
							{
								//printf(buf,dVal);
								sprintf_s(tmp,32,buf,dVal);
								nDoublePos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					case 'o':
					case 'O':
					case 'x':
					case 'X':
						{
							double dVal = 0;
							if(pArgList->GetArgu(nDoublePos,dVal))
							{
								//printf(buf,(int)dVal);
								sprintf_s(tmp,32,buf,dVal);
								nDoublePos++;
								TRACE("%s\n",tmp);
								//sprintf_s(lpFmtstr,512,"%s%s",lpFmtstr,tmp);
								strcat_s(lpFmtstr,strlen(tmp)+strlen(lpFmtstr)+1,tmp);
							}
						}break;
					}
					break;
				}
			}
		}
		else
		{
			int len = strlen(lpFmtstr);
			lpFmtstr[len] = strFmt[i];
		}
	}
}

// print函数实现
int CRunLuaDlg::luaPrintf(lua_State *L)
{
	int n = lua_gettop(L);
	if(!lua_isstring(L,1))
	{// 如果第一个参数不是string类型,则报参数错误
		g_lpWnd->AddLog(_T("printf arguarement invalid!\n"));
		return 0;
	}
	const char* fmt = lua_tostring(L,1);
	CArgList argList;
	for(int i=2;i<=n;i++)
	{
		int nType = lua_type(L,i);
		switch (nType)
		{
		case LUA_TNUMBER:  // double
			{
				double x = lua_tonumber(L,i);
				argList.AddArgu(x);
			}break;
		case LUA_TSTRING:  // string
			{
				const char *str = lua_tostring(L,i);
				argList.AddArgu(str);
			}break;
		case LUA_TBOOLEAN: // boolean
			{
				BOOL bVal = lua_toboolean(L,i);
				argList.AddArgu((BOOL)bVal);
			}break;
		}
	}

	char strfmt[512] = { 0 };
	g_lpWnd->FmtDecode(fmt,&argList,strfmt);
	TRACE(strfmt);
	g_lpWnd->AddPrint(strfmt);

	char lpstrlog[530] = { 0 };
	sprintf_s(lpstrlog,530,"add print:\"%s\"\n",strfmt);
	g_lpWnd->AddLog(lpstrlog);
	return 0;
}

CArgList类实现:

#include "StdAfx.h"
#include "ArgList.h"

const char *g_cfmtstr="ducCspf%oOxX";


CArgList::CArgList(void)
{
	m_nBoolNum    = 0;
	m_nDoubleNum = 0;
	m_nStrNum    = 0;
	m_list = new LinkList;
	m_list->next = NULL;
}

CArgList::~CArgList(void)
{
	while(m_list)
	{
		LinkList *pList = m_list;
		m_list = m_list->next;
		if(pList->Elem.chType == TYPE_STRING)
		{
			if(pList->Elem.strData)
				delete[] pList->Elem.strData;
		}
		delete pList;
	}
	m_list=NULL;
	m_nStrNum = 0;
	m_nDoubleNum = 0;
	m_nBoolNum = 0;
}

// 添加结点
/*
bool CArgList::AddArgu(ElemeType item)
{
	LinkList *pList = m_list;
	while(pList->next) pList = pList->next;
	LinkList *list = new LinkList;

	if(list == NULL)
	{
		printf("new LinkList failed\n");
		return false;
	}
	list->next = NULL;
	list->Elem.chType = item.chType;
	switch (list->Elem.chType)
	{
	case TYPE_NUMBER:
		list->Elem.dData = item.dData;
		m_nDoubleNum++;
		break;
	case TYPE_BOOLEAN:
		list->Elem.bData = item.bData;
		m_nBoolNum++;
		break;
	case TYPE_STRING:
		list->Elem.strData = item.strData;
		m_nStrNum++;
		break;
	}
	pList->next = list;
	return true;
}
*/
// 添加bool结点
bool CArgList::AddArgu(BOOL bData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;
	LinkList* list = new LinkList;

	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}

	list->next = NULL;
	list->Elem.chType = TYPE_BOOLEAN;
	list->Elem.bData = bData;

	pList->next = list;
	return true;
}

// 添加double节点
bool CArgList::AddArgu(double dData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;

	LinkList *list = new LinkList;

	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}

	list->next = NULL;
	list->Elem.chType = TYPE_NUMBER;
	list->Elem.dData = dData;

	pList->next = list;
	m_nDoubleNum++;
	return true;
}

// 添加string节点
bool CArgList::AddArgu(const char* strData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;
	LinkList *list = new LinkList;
	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}
	list->next = NULL;
	list->Elem.chType = TYPE_STRING;
	int len = strlen(strData)+1;
	list->Elem.strData = new char[len];
	memset(list->Elem.strData,0,len);
	strcpy_s(list->Elem.strData,len,strData);
	pList->next = list;
	m_nStrNum++;
	return true;
}

// 获取第n个string型数据
char* CArgList::GetArgu(int nIdx)
{
	LinkList* pList = m_list;
	int nPos = 1;
	while(pList)
	{
		if(pList->Elem.chType == TYPE_STRING)
		{
			if(nPos == nIdx)
			{
				return pList->Elem.strData;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return NULL;
}

// 获取第nIdx个double型数据
bool CArgList::GetArgu(int nIdx,double &dVal)
{
	LinkList *pList = m_list;
	int nPos = 1;
	while (pList)
	{
		if(pList->Elem.chType == TYPE_NUMBER)
		{
			if(nPos == nIdx)
			{
				dVal = pList->Elem.dData;
				return true;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return false;
}

// 获取第n个bool型数据
bool CArgList::GetArgu(int nIdx,BOOL &bVal)
{
	LinkList *pList = m_list;
	int nPos = 1;
	while(pList)
	{
		if(pList->Elem.chType == TYPE_BOOLEAN)
		{
			if(nPos == nIdx)
			{
				bVal = pList->Elem.bData;
				return true;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return false;
}

// 获取链表状态
CString CArgList::GetLinkState()
{
	CString strStatus = _T("");
	LinkList* pList = m_list->next;
	int nNum = 0;
	while(pList)
	{
		CString strTmp;
		switch (pList->Elem.chType)
		{
		case TYPE_STRING:
			//printf("%s\n",pList->Elem.strData);
			strTmp.Format(_T("[%d,string,%s]"),nNum,pList->Elem.strData);
			strStatus += strTmp;
			break;
		case TYPE_NUMBER:
			//printf("%f\n",pList->Elem.dData);
			strTmp.Format(_T("[%d,num,%f]"),nNum,pList->Elem.dData);
			strStatus += strTmp;
			break;
		case TYPE_BOOLEAN:
			//printf("%d\n",pList->Elem.bData);
			strTmp.Format(_T("[%d,boolean,%d]"),nNum,pList->Elem.bData);
			strStatus += strTmp;
			break;
		}
		pList = pList->next;
		nNum++;
	}
	return strStatus;
}

// 判断是否是格式化字符
BOOL CArgList::IsFormatChar(char ch)
{
	int len = strlen(g_cfmtstr);
	for(int i=0;i<len;i++)
	{
		if(ch == g_cfmtstr[i])
			return TRUE;
	}
	return FALSE;
}

#pragma once

const int TYPE_NUMBER  = 0;    // double型数据
const int TYPE_STRING  = 1;    // string型数据
const int TYPE_BOOLEAN = 2;    // boolean型数据

typedef struct tagElemType
{
	char chType;  // 数据类型
	union
	{
		char* strData;
		double dData;
		BOOL bData;
	};
}ElemeType;

typedef struct LinkList
{
	LinkList *next;
	ElemeType Elem;
}LinkList,*PLinkList;


class CArgList
{
public:
	CArgList(void);
	~CArgList(void);
	//bool AddArgu(ElemeType item); // 添加参数
	bool AddArgu(double dData);   // 添加double型数据
	bool AddArgu(const char* strData);  // 添加string型数据
	bool AddArgu(BOOL bData);     // 添加bool型数据
	char* GetArgu(int nIdx);      // 获取第nIdx个string型数据
	bool GetArgu(int nIdx,BOOL &bVal); // 获取第nIdx个bool型数据
	bool GetArgu(int nIdx,double &dVal); // 获取第nIdx个double型数据
	CString GetLinkState();       // 获取链表状态
	static BOOL IsFormatChar(char ch);    // 是否是格式化字符
private:
	LinkList *m_list;
	int m_nBoolNum;        // bool型数据个数
	int m_nDoubleNum;      // double型数据个数
	int m_nStrNum;         // string型数据个数
};


思路:

printf('123,x=%0.3f, y=%d, z=%d,%s,%c\n',x,y,z,'Hello word','A') -- 打印函数

对于这个lua脚本函数,将它拆分成两块,一个是printf的格式化字串,二是它的可变参数。

1. 首先处理格式化字串:'123,x=%0.3f, y=%d, z=%d,%s,%c\n'

查找所有%d,%f,%X。。。之类的子串,并保存在一个buf数组中。比如经过处理后的

buf为:buf=%d, buf=%d,buf=%s,buf=%c

2. 再处理可变参数。

在MFC中。通过lua_gettop,lua_getnumber,lua_getstring()等函数获取所有的参数。

并把可变参数保存在一个链表中,链表中的数据的数据结构为:

typedef struct

{

char chType;

enum                           // 在lua中数据只要分为3中就可以了double,string,boolean型

{

char* strData;

double dData;

BOOL bData;

};

}ElemType


typedef struct

{

LinkList *next;

ElemType data;

}LinkList;

3. 把解析好的格式,和保存的可变参数

sprintf(buf, 下一个可变参数)

遇到格式化的字符串就求出值,否则就原样输出。




C++实现:

// FormatDecod.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <string.h>

#define TYPE_NUMBER 1
#define TYPE_STRING 2
#define TYPE_BOOL   3

const char* g_fmtstr = "ducCspf%oOxX";

typedef struct tagElemType
{
	char chType;  // 数据类型
	union
	{
		char* strData;
		double dData;
		bool bData;
	};
}ElemeType;

typedef struct LinkList
{
	LinkList *next;
	ElemeType Elem;
}LinkList,*PLinkList;

class CLinkList
{
public:
	CLinkList();  // 构造函数
	~CLinkList(); // 析构函数
	bool AddNode(ElemeType item);   // 添加结点
	bool AddNode(double dData);     // 添加节点
	bool AddNode(char* strData);    // 添加节点
	bool AddNode(bool bData);       // 添加节点
	void PrintNodes();              // 打印所有结点
	char* GetNode(int n);         // 获取第n个string型数据
	bool GetNode(int n,bool &bVal);            // 获取第n个bool型数据
	bool GetNode(int n,double &dVal);          // 获取第n个double型数据
private:
	LinkList *m_list;
	int m_nBoolNum;       // bool型数据个数
	int m_nDoubleNum;    // double型数据个数
	int m_nStrNum;       // string型数据个数
};

CLinkList::CLinkList()
{
	m_nBoolNum    = 0;
	m_nDoubleNum = 0;
	m_nStrNum    = 0;
	m_list = new LinkList;
	m_list->next = NULL;
}
CLinkList::~CLinkList()
{
	while(m_list)
	{
		LinkList *pList = m_list;
		m_list = m_list->next;
		if(pList->Elem.chType == TYPE_STRING)
		{
			if(pList->Elem.strData)
				delete[] pList->Elem.strData;
		}
		delete pList;
	}
	m_list=NULL;
	m_nStrNum = 0;
	m_nDoubleNum = 0;
	m_nBoolNum = 0;
}

// 添加结点
bool CLinkList::AddNode(ElemeType item)
{
	LinkList *pList = m_list;
	while(pList->next)
		pList = pList->next;
	LinkList *list = new LinkList;

	if(list == NULL)
	{
		printf("new LinkList failed\n");
		return false;
	}
	list->next = NULL;
	list->Elem.chType = item.chType;
	switch (list->Elem.chType)
	{
	case TYPE_NUMBER:
		list->Elem.dData = item.dData;
		m_nDoubleNum++;
		break;
	case TYPE_BOOL:
		list->Elem.bData = item.bData;
		m_nBoolNum++;
		break;
	case TYPE_STRING:
		list->Elem.strData = item.strData;
		m_nStrNum++;
		break;
	}
	pList->next = list;
	return true;
}

// 添加节点
bool CLinkList::AddNode(bool bData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;
	LinkList* list = new LinkList;

	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}

	list->next = NULL;
	list->Elem.chType = TYPE_BOOL;
	list->Elem.bData = bData;

	pList->next = list;
	return true;
}

// 添加double结点
bool CLinkList::AddNode(double dData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;

	LinkList *list = new LinkList;
	
	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}

	list->next = NULL;
	list->Elem.chType = TYPE_NUMBER;
	list->Elem.dData = dData;

	pList->next = list;
	m_nDoubleNum++;
	return true;
}

// 添加string节点
bool CLinkList::AddNode(char* strData)
{
	LinkList* pList = m_list;
	while(pList->next) pList = pList->next;
	LinkList *list = new LinkList;
	if(NULL == list)
	{
		printf("new LinkList failed\n");
		return false;
	}
	list->next = NULL;
	list->Elem.chType = TYPE_STRING;
	int len = strlen(strData)+1;
	list->Elem.strData = new char[len];
	memset(list->Elem.strData,0,len);
	strcpy_s(list->Elem.strData,len,strData);
	pList->next = list;
	m_nStrNum++;
	return true;
}

// 获取第n个string型数据
char* CLinkList::GetNode(int n)
{
	LinkList* pList = m_list;
	int nPos = 1;
	while(pList)
	{
		if(pList->Elem.chType == TYPE_STRING)
		{
			if(nPos == n)
			{
				return pList->Elem.strData;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return NULL;
}

// 获取第n个double型数据
bool CLinkList::GetNode(int n,double &dVal)
{
	LinkList *pList = m_list;
	int nPos = 1;
	while (pList)
	{
		if(pList->Elem.chType == TYPE_NUMBER)
		{
			if(nPos == n)
			{
				dVal = pList->Elem.dData;
				return true;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return false;
}

// 获取第n个bool型数据
bool CLinkList::GetNode(int n,bool &bVal)
{
	LinkList *pList = m_list;
	int nPos = 1;
	while(pList)
	{
		if(pList->Elem.chType == TYPE_BOOL)
		{
			if(nPos == n)
			{
				bVal = pList->Elem.bData;
				return true;
			}
			nPos++;
		}
		pList = pList->next;
	}
	return false;
}

// 打印所有结点
void CLinkList::PrintNodes()
{
	LinkList* pList = m_list->next;
	while(pList)
	{
		switch (pList->Elem.chType)
		{
		case TYPE_STRING:
			printf("%s\n",pList->Elem.strData);
			break;
		case TYPE_NUMBER:
			printf("%f\n",pList->Elem.dData);
			break;
		case TYPE_BOOL:
			printf("%d\n",pList->Elem.bData);
			break;
		}
		pList = pList->next;
	}
}

bool IsFormatStr(char ch)
{
	for(int i=0;i<strlen(g_fmtstr);i++)
	{
		if(ch == g_fmtstr[i])
			return true;
	}
	return false;
}

void FormatDecod(const char *str,CLinkList* list)
{
	int len = strlen(str);
	int nDoublePos=1;
	int nStrPos=1;
	int nBoolPos=1;
	for(int i=0;i<len;i++)
	{
		if(str[i] == '%')
		{
			for(int j=i+1;j<len && str[j];j++)
			{
				char ch = str[j];

				if(IsFormatStr(ch))
				{
					int n = j-i+1;
					char buf[32] = { 0 };
					int k = 0;
					for(k=0;k<n;k++)
					{
						buf[k] = str[i+k];
					}
					buf[k] = 0;
					//for(int i=0;i<strlen(buf);i++)
					//	printf("%c",buf[i]);
					//printf("");
					i = j;
					
					switch (ch)
					{
					case 'd':
						{
							double dVal = 0;
							if(list->GetNode(nDoublePos,dVal))
							{
								printf(buf,(int)dVal);
								nDoublePos++;
							}
						}break;
					case 'u':
						{
							double dVal = 0;
							if(list->GetNode(nDoublePos,dVal))
							{
								printf(buf,(unsigned)dVal);
								nDoublePos++;
							}
						}break;
					case 'c':
					case 'C':
						{
							char* str = list->GetNode(nStrPos);
							if(str != NULL)
							{
								printf(buf,str[0]);
								nStrPos++;
							}
						}break;
					case 's':
						{
							char* str = list->GetNode(nStrPos);
							if(str != NULL)
							{
								printf(buf,str);
								nStrPos++;
							}
						}break;
					case 'p':
						{
							double dVal = 0;
							if(list->GetNode(nDoublePos,dVal))
							{
								printf(buf,(int)dVal);
								nDoublePos++;
							}
						}break;
					case '%':
						printf(buf);
						break;
					case 'f':
						{
							double dVal = 0;
							if(list->GetNode(nDoublePos,dVal))
							{
								printf(buf,dVal);
								nDoublePos++;
							}
						}break;
					case 'o':
					case 'O':
					case 'x':
					case 'X':
						{
							double dVal = 0;
							if(list->GetNode(nDoublePos,dVal))
							{
								printf(buf,(int)dVal);
								
								nDoublePos++;
							}
						}break;
					}
					break;
				}
			}
		}
		else
		{
			printf("%c",str[i]);
		}
	}
	printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	CLinkList list;
	list.AddNode((double)10);
	list.AddNode("abcdasd");
	list.AddNode((double)1000);
	list.AddNode(123.45);
	list.AddNode((double)0x800);
	const char *strformat = "this is a test %d,%s,%-10d,%d,%%,%x";
	FormatDecod(strformat,&list);
	list.PrintNodes();
	printf("===================\n");
	printf("%s\n",list.GetNode(1));
	double dVal = 0;
	if(list.GetNode(1,dVal))
	{
		printf("%f\n",dVal);
	}
	bool bVal = 0;
	if(list.GetNode(1,bVal))
	{
		printf("%d\n",bVal);
	}
	
	return 0;
}

相关文章
相关标签/搜索
每日一句
    每一个你不满意的现在,都有一个你没有努力的曾经。
本站公众号
   欢迎关注本站公众号,获取更多程序园信息
开发小院