C/C++程序使用lu对象作为配置文件

欢迎访问 Lu程序设计

C/C++程序使用lu对象作为配置文件

1 说明

    要演示本文的例子,你必须下载Lu32脚本系统。本文的例子需要lu32.dll、lu32.lib、C格式的头文件lu32.h,相信你会找到并正确使用这几个文件。

    用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。

2 使用lu对象作为配置文件的格式

    通常应用程序会有一些可调控的参数,简单的控制可以通过命令行参数来实现,然而复杂一些的则一般会使用配置文件的形式。本文讨论使用lu对象作为配置文件的格式及实现。关于lu对象,参考Lu用户指南;lu对象的数据结构参考Lu编程指南

    lu对象中的基本数据格式采取“键 : 值”的方式,键是以#开头的字符串,而值可为任意数据(本文代码支持的数据类型有lu对象、编译符#、逻辑值、nil、字符串、整数、实数)。例如:

(:static)= global(true), static=
lu{
    ... ... ,
    #name : "王刚",
    #age : 21,
    ... ...
}


    这是个无名函数,可以避免函数重名问题;函数 global(true) 使得lu对象成为全局对象,故通常要使用该函数;static是一个静态变量,将全局的lu对象保存在静态变量中可以避免被垃圾收集器回收。

    lu对象可以嵌套,故可存储类似“键1 : 键2 : 键3 : 值”的数据,第1个键在第1层lu对象中,第2个键在第2层lu对象中,依此类推。例如:

(:static)= global(true), static=
lu{
    "--- 使用字符串进行注释 ---" ,
    ... ... ,
    #生产部 : lu{
        #staff : lu{
            #王刚 : lu{
                #age : 21,
                #性别 : "男",
                #工作量 : lu{11, 15},
                #e_mail : "wanggang@sina.com"
            },
            #李军 : lu{
                #age : 25,
                #性别 : "男",
                #工作量 : lu{17, 1.2, 1.8},
                #website : "http://www.lijun.net/"
            }
        }
    },
    ... ...
}


    本例中李军的年龄可表示为“#生产部 : #staff : #李军 : #age : 25”,而李军的工作量是一个lu对象“#生产部 : #staff : #李军 : #工作量 : lu{17, 1.2, 1.8}”。

    另外,Lu核心库支持的表达式中不能有注释,不过可以使用字符串作为注释,如上例。使用字符串作为注释的好处是:当我们重建配置文件时,注释仍然存在。

    程序对配置文件的操作有三种:读配置文件,修改配置文件,写配置文件。在本文的例子中,读配置文件即编译一个返回lu对象(包含配置信息)的字符串表达式;修改配置文件即对该lu对象的成员进行存取;写配置文件即根据该lu对象生成相应的字符串表达式。

    本文的代码中提供了3个实用的函数lu2str、getlumember、setlumember以更方便地操作lu对象,包含了完整的错误检查,故代码较长。

3 代码

#include <stdio.h>
#include <string.h>
#include <locale.h>
#include "lu32.h"

#pragma comment( lib, "lu32.lib" )

//输出lu对象到一个字符串,支持lu对象、编译符#、逻辑值、nil、字符串、整数、实数
int lu2str(LuData *pVal,wchar_t *luStr,int luStrMax,int *luStrNow)
{
	luLu *plu;	//lu对象指针
	static luLu *pmainlu=NULL;	//记住最初的lu对象,避免该函数无穷递归调用
	static int kkk;
	int j;
	luVOID i,StrMax;
	luINT k;
	wchar_t *pStr;
	char str32[32];
	int bBlank = 1, bKeyLu = 0;

	if(pVal->BType!=luDynData_lu) return 1;	//无效的lu对象
	//验证lu对象是否有效
	plu=(luLu *)SearchKey((char *)&(pVal->x), sizeof(luVOID), luDynData_lu);
	if(NULL==plu) return 1;	//无效的lu对象指针
	if(plu==pmainlu) return 2;	//递归嵌套的lu对象
	if(pmainlu==NULL)
	{
		pmainlu=plu;  	//记住最初的lu对象
		if(luStrMax<40) return 3;	//缓冲区太小
		wcscpy_s(luStr,luStrMax,L"(:static)= global(true), static=\r\nlu{\r\n");
		*luStrNow=39;
	}

	kkk++;

	for(i=0;i<plu->Len;i++)
	{
		if(plu->Lu[i].BType==luStaData_struniint || plu->Lu[i].BType==luDynData_lu) bKeyLu=1;
	}
	if(bKeyLu==0)
	{
		if(luStr[*luStrNow-1]=='\n') (*luStrNow)--;
		if(luStr[*luStrNow-1]=='\r') (*luStrNow)--;
		if(luStr[*luStrNow]) luStr[*luStrNow]='\0';
	}
	for(i=0;i<plu->Len;i++)
	{
		if(bKeyLu==0)
		{
			bBlank = 0;
			if(luStr[*luStrNow-1]=='\n') (*luStrNow)--;
			if(luStr[*luStrNow-1]=='\r') (*luStrNow)--;
			if(luStr[*luStrNow]) luStr[*luStrNow]='\0';
		}
		if(bBlank)
		{
			if(luStrMax-(*luStrNow)<kkk*4)
			{
				kkk--; return 3;	//缓冲区太小
			}
			for(j=0;j<kkk*4;j++) luStr[(*luStrNow)++]=' ';
			luStr[*luStrNow]='\0';
		}
		else
		{
			bBlank = 1;
		}

		switch(plu->Lu[i].BType)
		{
		case luStaData_nil :	//nil
			if(luStrMax-(*luStrNow)<5)
			{
				kkk--; return 3;	//缓冲区太小
			}
			wcscat_s(luStr,luStrMax,L"nil");
			*luStrNow=*luStrNow+3;
			break;
		case luStaData_int64 :	//整数
			j=sprintf_s(str32,32,"%I64d",plu->Lu[i].x);
			if(j<0)
			{
				kkk--; return 4;	//数据转换错误
			}
			if(luStrMax-(*luStrNow)<j)
			{
				kkk--; return 3;	//缓冲区太小
			}
			for(j=0;str32[j];j++) luStr[(*luStrNow)++]=str32[j];
			luStr[*luStrNow]='\0';
			break;
		case luStaData_double :	//实数
			j=sprintf_s(str32,32,"%f",*(double *)&(plu->Lu[i].x));
			if(j<0)
			{
				kkk--; return 4;	//数据转换错误
			}
			if(luStrMax-(*luStrNow)<j)
			{
				kkk--; return 3;	//缓冲区太小
			}
			for(j=0;str32[j];j++) luStr[(*luStrNow)++]=str32[j];
			luStr[*luStrNow]='\0';
			break;
		case luStaData_logical :	//逻辑值
			if(luStrMax-(*luStrNow)<8)
			{
				kkk--; return 3;	//缓冲区太小
			}
			if(plu->Lu[i].x)
			{
				wcscat_s(luStr,luStrMax,L"true");
				*luStrNow=*luStrNow+4;
			}
			else
			{
				wcscat_s(luStr,luStrMax,L"false");
				*luStrNow=*luStrNow+5;
			}
			break;
		case luStaData_struniint :	//由字符串决定的唯一整数
			pStr=(wchar_t *)UniIntToStr((luVOID)plu->Lu[i].x,&k);
			if(!pStr)
			{
				kkk--; return 4;	//数据转换错误
			}
			k=k/2;
			if(luStrMax-(*luStrNow)<=k)
			{
				kkk--; return 3;	//缓冲区太小
			}
			luStr[(*luStrNow)++]='#';
			for(j=0;j<(int)k;j++) luStr[(*luStrNow)++]=pStr[j];
			luStr[*luStrNow]='\0';
			break;
		case luStaData_string :		//静态字符串
		case luDynData_string :		//动态字符串
			pStr=GetStr(plu->Lu+i,NULL,&StrMax);
			if(!pStr)
			{
				kkk--; return 4;	//数据转换错误
			}
			if(luStrMax-(*luStrNow)<2)
			{
				kkk--; return 3;	//缓冲区太小
			}
			luStr[(*luStrNow)++]='\"';
			for(j=0;j<pStr[j];j++)
			{
				if(luStrMax-(*luStrNow)<=3)
				{
					kkk--; return 3;	//缓冲区太小
				}
				switch(pStr[j])
				{
					case '\\' :
					case '\"' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]=pStr[j];
						break;
					case '\a' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='a';
						break;
					case '\b' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='b';
						break;
					case '\f' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='f';
						break;
					case '\n' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='n';
						break;
					case '\r' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='r';
						break;
					case '\t' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='t';
						break;
					case '\v' :
						luStr[(*luStrNow)++]='\\'; luStr[(*luStrNow)++]='v';
						break;
					default:
						luStr[(*luStrNow)++]=pStr[j];
				}
			}
			luStr[(*luStrNow)++]='\"'; luStr[*luStrNow]='\0';
			break;
		case luDynData_lu :		//lu对象
			if(luStrMax-(*luStrNow)<5)
			{
				kkk--; return 3;	//缓冲区太小
			}
			wcscat_s(luStr,luStrMax,L"lu{\r\n");
			*luStrNow=*luStrNow+5;
			j=lu2str(plu->Lu+i,luStr,luStrMax,luStrNow);  //递归调用
			if(j)
			{
				kkk--; return j;	//错误
			}
			if(luStr[*luStrNow-1]=='\n')
			{
				if(luStrMax-(*luStrNow)<kkk*4+3)
				{
					kkk--; return 3;	//缓冲区太小
				}
				for(j=0;j<kkk*4;j++) luStr[(*luStrNow)++]=' ';
			}
			luStr[(*luStrNow)++]='}'; luStr[*luStrNow]='\0';
			break;
		default :
			j=sprintf_s(str32,32,"%I64d",plu->Lu[i].x);
			if(j<0)
			{
				kkk--; return 4;	//数据转换错误
			}
			if(luStrMax-(*luStrNow)<j+20)
			{
				kkk--; return 3;	//缓冲区太小
			}
			wcscat_s(luStr,luStrMax,L"\"不可识别对象 ");
			*luStrNow=*luStrNow+8;
			for(j=0;str32[j];j++) luStr[(*luStrNow)++]=str32[j];
			luStr[(*luStrNow)++]='\"'; luStr[*luStrNow]='\0';
		}
		if(luStrMax-(*luStrNow)<10)
		{
			kkk--; return 3;	//缓冲区太小
		}
		if(i+1!=plu->Len)
		{
			if(plu->Lu[i].BType==luStaData_struniint) bBlank = 0;
			if(i)
			{
				if(plu->Lu[i-1].BType==luStaData_struniint) bBlank = 1;
			}
			if(bBlank)
			{
				wcscat_s(luStr,luStrMax,L", \r\n");
				*luStrNow=*luStrNow+4;
			}
			else
			{
				wcscat_s(luStr,luStrMax,L" : ");
				*luStrNow=*luStrNow+3;
			}
		}
		else
		{
			if(bKeyLu==1)
			{
				wcscat_s(luStr,luStrMax,L"\r\n");
				*luStrNow=*luStrNow+2;
			}
		}
	}

	kkk--;
	if(kkk==0)
	{
		pmainlu=NULL;
		wcscat_s(luStr,luStrMax,L"}\r\n");
		*luStrNow=*luStrNow+3;
	}
	return 0;
}
//获得lu对象成员的值,通过pme返回
//luMember存放以#开头的成员列表,0表示结束
int getlumember(LuData *pVal,luVOID *luMember,LuData **pme)
{
	luLu *plu;	//lu对象指针
	luVOID i,j,k;

	for(i=0;luMember[i];i++)
	{
		if(pVal->BType!=luDynData_lu) return 1;	//无效的lu对象
		//验证lu对象是否有效
		plu=(luLu *)SearchKey((char *)&(pVal->x), sizeof(luVOID), luDynData_lu);
		if(NULL==plu) return 1;	//无效的lu对象指针
		for(j=0;j<plu->Len;j++)
		{
			if(plu->Lu[j].BType==luStaData_struniint)
			{
				if((luVOID)plu->Lu[j].x==luMember[i])
				{
					k=j+1;
					if(k<plu->Len)
					{
						pVal=plu->Lu+k;
						break;
					}
				}
			}
		}
		if(j==plu->Len) return 2;	//没有找到对象成员
	}
	*pme=pVal;
	return 0;
}
//设置lu对象成员的值
//luMember存放以#开头的成员列表,0表示结束;如果从luMember找到的成员是一个lu对象,一般index表示该lu对象成员的序号;index的意义取决于mode。
//mode表示工作模式。
//mode=0表示删除对象成员(键 : 值)。index、key_me和me被忽略。
//mode=1时,index=0表示用新的键值(键key_me : 值me)更新对象成员键值;index<0表示在对象成员前插入键值;index>0表示在对象成员后插入键值。
//mode=2表示直接用me更新对象成员的值。index和key_me被忽略。
//mode=3,从luMember找到的成员应是一个lu对象,更新该lu对象第index个成员。key_me被忽略。
//mode=4,从luMember找到的成员应是一个lu对象,从该lu对象第index个成员前插入me,若index<0或者大于原lu对象长度,从末尾插入me。key_me被忽略。
int setlumember(LuData *pVal,luVOID *luMember,int index,luVOID key_me,LuData *me,int mode)
{
	luLu *plu,*plup;	//lu对象指针
	LuData *old;
	int kk;
	luVOID i,j,k;

	if(mode==0 || mode==1)	//删除、更新、插入键值(键 : 值)
	{
		old=NULL;
		for(i=0;luMember[i];i++)
		{
			if(pVal->BType!=luDynData_lu) return 1;	//无效的lu对象
			//验证lu对象是否有效
			plu=(luLu *)SearchKey((char *)&(pVal->x), sizeof(luVOID), luDynData_lu);
			if(NULL==plu) return 1;	//无效的lu对象指针
			for(j=0;j<plu->Len;j++)
			{
				if(plu->Lu[j].BType==luStaData_struniint)
				{
					if((luVOID)plu->Lu[j].x==luMember[i])
					{
						k=j+1;
						if(k<plu->Len)
						{
							old=pVal; pVal=plu->Lu+k;
							break;
						}
					}
				}
			}
			if(j==plu->Len) return 2;	//没有找到对象成员
		}
		if(!old) return 2;	//没有找到对象成员
		if(mode==0)
		{
			plup=(luLu *)NewSysObj(luDynData_lu,plu->Len-2,0);
			if(!plup) return 3;	//内存错误
			for(i=0;i<j;i++) plup->Lu[i]=plu->Lu[i];
			for(j=i+2;i<plup->Len;i++,j++) plup->Lu[i]=plu->Lu[j];
			*(luVOID *)&(old->x)=(luVOID)plup;	//更新lu对象
			DeleteKey((char *)&plu,sizeof(luVOID),luDynData_lu,NULL,1);	//销毁以前的lu对象
			return 0;
		}
		if(index==0)
		{
			plu->Lu[j].x=key_me; *pVal=*me; return 0;
		}
		plup=(luLu *)NewSysObj(luDynData_lu,plu->Len+2,0);
		if(!plup) return 3;	//内存错误
		index = (index<0) ? j : k+1;
		for(i=0;i<index;i++) plup->Lu[i]=plu->Lu[i];
		j=i; plup->Lu[i].BType=luStaData_struniint; plup->Lu[i].VType=luStaData_struniint; plup->Lu[i++].x=key_me; plup->Lu[i++]=*me;
		for(;i<plup->Len;i++,j++) plup->Lu[i]=plu->Lu[j];
		*(luVOID *)&(old->x)=(luVOID)plup;	//更新lu对象
		DeleteKey((char *)&plu,sizeof(luVOID),luDynData_lu,NULL,1);	//销毁以前的lu对象
		return 0;
	}
	kk=getlumember(pVal,luMember,&old);
	if(kk) return kk;
	if(mode==2)			//直接更新键值
	{
		*old=*me; return 0;
	}
	if(old->BType!=luDynData_lu) return 1;	//无效的lu对象
	//验证lu对象是否有效
	plu=(luLu *)SearchKey((char *)&(old->x), sizeof(luVOID), luDynData_lu);
	if(NULL==plu) return 1;	//无效的lu对象指针
	if(mode==3)		//更新键值的成员
	{
		if(index<0 || index>=plu->Len) return 2;	//没有找到对象成员
		plu->Lu[index]=*me; return 0;
	}
	else if(mode==4)	//插入键值的成员
	{
		plup=(luLu *)NewSysObj(luDynData_lu,plu->Len+1,0);
		if(!plup) return 3;	//内存错误
		if(index<0 || index>plu->Len) index=plu->Len;
		for(i=0;i<index;i++) plup->Lu[i]=plu->Lu[i];
		j=i; plup->Lu[i++]=*me;
		for(;i<plup->Len;i++,j++) plup->Lu[i]=plu->Lu[j];
		*(luVOID *)&(old->x)=(luVOID)plup;	//更新lu对象
		DeleteKey((char *)&plu,sizeof(luVOID),luDynData_lu,NULL,1);	//销毁以前的lu对象
		return 0;
	}
	else
	{
		return 4;	//不正确的工作模式
	}
}

void main(void)
{
	void *hFor;		//表达式句柄
	luINT nPara;		//存放表达式的自变量个数
	LuData *pPara;		//存放输入自变量的数组指针
	luINT ErrBegin,ErrEnd;	//表达式编译出错的初始位置和结束位置
	int ErrCode;		//错误代码
	LuData Val;		//Lu基本数据类型
	wchar_t luStr[1000];	//保存由lu对象转换来的字符串表达式
	int luStrNow;		//接收luStr中的字符个数
	luString *pString;		//Lu动态字符串指针
	wchar_t ForStr[]=L"(:static)= global(true), static=lu{\"--- 使用字符串进行注释 ---\" , #生产部 : lu{ #staff : lu{ #王刚 : lu{ #age : 21, #性别 : \"男\", #工作量 : lu{ 11, 15}, #e_mail : \"wanggang@sina.com\"}, #李军 : lu{ #age : 25, #性别 : \"男\", #工作量 : lu{ 17,1.2,1.8}, #website : \"http://www.lijun.net/\"}}}}";

	//由字符串获得一个唯一的整数
	luVOID ui_PD;		//#生产部
	luVOID ui_staff;		//#staff
	luVOID ui_wanggang;	//#王刚
	luVOID ui_lijun;		//#李军
	luVOID ui_age;		//#age
	luVOID ui_gender;		//#性别
	luVOID ui_workload;	//#工作量
	luVOID ui_e_mail;		//#e_mail
	luVOID ui_website;		//#website
	luVOID ui_addr;		//#家庭地址
	luVOID luMember[10];	//用以查找替换lu对象成员
	LuData *pme;		//Lu基本数据类型指针,用来返回lu对象
	LuData me;		//Lu基本数据类型,用来更新lu对象键值

	setlocale(LC_ALL, "chs");	//设置可以输出中文

	if(!InitLu()) return;	//初始化Lu

	ui_PD		=	StrToUniInt((char *)L"生产部",6);	//由字符串获得一个唯一的整数,下同
	ui_staff		=	StrToUniInt((char *)L"staff",10);
	ui_wanggang	=	StrToUniInt((char *)L"王刚",4);
	ui_lijun		=	StrToUniInt((char *)L"李军",4);
	ui_age		=	StrToUniInt((char *)L"age",6);
	ui_gender		=	StrToUniInt((char *)L"性别",4);
	ui_workload	=	StrToUniInt((char *)L"工作量",6);
	ui_e_mail		=	StrToUniInt((char *)L"e_mail",12);
	ui_website	=	StrToUniInt((char *)L"website",14);
	ui_addr		=	StrToUniInt((char *)L"家庭地址",8);

	ErrCode=LuCom(ForStr,0,0,0,&hFor,&nPara,&pPara,&ErrBegin,&ErrEnd);  //编译表达式
	if(ErrCode)
	{
		printf("表达式有错误!错误代码: %d \n",ErrCode);
	}
	else
	{
		Val=LuCal(hFor,pPara);	//计算表达式的值
		if(Val.BType==luDynData_lu)
		{
			if(0==lu2str(&Val,luStr,1000,&luStrNow))	//输出lu对象的值
			{
				wprintf(L"%s",luStr);
			}

			//luMember中存放键的位置“#生产部 : #staff : #王刚 : #age”
			luMember[0]=ui_PD; luMember[1]=ui_staff; luMember[2]=ui_wanggang; luMember[3]=ui_age;  luMember[4]=0;
			if(0==getlumember(&Val,luMember,&pme))
			{
				wprintf(L"\r\n查找到 #生产部 : #staff : #王刚 : #age : %I64d\r\n\r\n",pme->x);
			}

			//luMember中存放键的位置“#生产部 : #staff : #李军 : #工作量”
			luMember[0]=ui_PD; luMember[1]=ui_staff; luMember[2]=ui_lijun; luMember[3]=ui_workload;  luMember[4]=0;
			pString=(luString *)NewSysObj(luDynData_string,80,0);
			if(pString) wcscpy_s(pString->Str,80,L"XX省XX市XX区XX路100号大院60#7楼 邮政编码:123456");
			me.BType=luDynData_string; me.VType=luDynData_string; me.x=0; *(luVOID *)&(me.x)=(luVOID)pString;
			setlumember(&Val,luMember,-1,ui_addr,&me,1);	//在李军工作量前面增加家庭地址

			//luMember中存放键的位置“#生产部 : #staff : #李军 : #工作量”
			luMember[0]=ui_PD; luMember[1]=ui_staff; luMember[2]=ui_lijun; luMember[3]=ui_workload;  luMember[4]=0;
			me.BType=luStaData_double; me.VType=luStaData_double; *(double *)&(me.x)=12.3;
			setlumember(&Val,luMember,-1,0,&me,4);	//李军的工作量增加12.3,添加到末尾

			if(0==lu2str(&Val,luStr,1000,&luStrNow))	//输出lu对象的值
			{
				wprintf(L"%s",luStr);
			}
		}
	}
	FreeLu();		//释放Lu
}


运行结果:

(:static)= global(true), static=
lu{
    "--- 使用字符串进行注释 ---",
    #生产部 : lu{
        #staff : lu{
            #王刚 : lu{
                #age : 21,
                #性别 : "男",
                #工作量 : lu{11, 15},
                #e_mail : "wanggang@sina.com"
            },
            #李军 : lu{
                #age : 25,
                #性别 : "男",
                #工作量 : lu{17, 1.200000, 1.800000},
                #website : "http://www.lijun.net/"
            }
        }
    }
}

查找到 #生产部 : #staff : #王刚 : #age : 21

(:static)= global(true), static=
lu{
    "--- 使用字符串进行注释 ---",
    #生产部 : lu{
        #staff : lu{
            #王刚 : lu{
                #age : 21,
                #性别 : "男",
                #工作量 : lu{11, 15},
                #e_mail : "wanggang@sina.com"
            },
            #李军 : lu{
                #age : 25,
                #性别 : "男",
                #家庭地址 : "XX省XX市XX区XX路100号大院60#7楼 邮政编码:123456",
                #工作量 : lu{17, 1.200000, 1.800000, 12.300000},
                #website : "http://www.lijun.net/"
            }
        }
    }
}


4 函数说明

    本例用到了Lu的10个输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,编译表达式的函数LuCom、计算表达式的函数LuCal、申请系统内置动态对象函数NewSysObj、查找键值函数SearchKey、 删除键值函数DeleteKey、由字符串获得一个唯一的整数StrToUniInt、由一个唯一的整数获得字符串UniIntToStr、获得字符串函数GetStr、。从这里查看这些函数的说明:Lu编程指南

5 难点分析

    代码中提供了3个实用的函数lu2str、getlumember、setlumember以更方便地操作lu对象。

lu2str:输出lu对象到一个字符串,该字符串用LuCom编译后运行,可重新得到该lu对象。

getlumember:获得lu对象成员的值。输入参数是类似“键1 : 键2 : 键3 : 0”的整数数组,每一个键是由字符串(Lu脚本中,键以#开头)获得的一个唯一的整数(用StrToUniInt转换)。

setlumember: 设置lu对象成员的值。可对lu对象的键值进行重置、插入、删除等操作。

    程序主要操作步骤如下:

    (1)对返回lu对象(包含了配置信息)的字符串表达式ForStr进行编译运行;

    (2)用函数lu2str将lu对象转换为字符串表达式并输出;

    (3)从lu对象中查询键“#生产部 : #staff : #王刚 : #age”并输出结果;

    (4)在lu对象中“#生产部 : #staff : #李军 : #工作量”位置前插入键(#家庭地址 : "XX省XX市XX区XX路100号大院60#7楼 邮政编码:123456");

    (5)在lu对象中“#生产部 : #staff : #李军 : #工作量”位置添加键成员(即将lu{17, 1.2, 1.8}修改为lu{17, 1.2, 1.8, 12.3});

    (6)用函数lu2str将lu对象转换为字符串表达式并输出。

6 其他

    你可能注意到了,我的联系方式就在下面,如有不明之处或有什么建议,可随时与我进行联系。


版权所有© Lu程序设计 2002-2013,保留所有权利
E-mail: forcal@sina.com
  QQ:630715621
最近更新: 2014年01月12日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值