您的位置:首页 > 编程语言 > Lua

MFC实现lua printf函数

2017-12-14 11:38 363 查看
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;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mfc lua