====================================================================

		Lu系统扩展动态库：LuSystem32.dll

====================================================================
#LuSystem使用说明{
[LuSystem32.dll] LuSystem使用说明

    LuSystem32.dll是一个Lu系统扩展动态库，包含一些增强Lu系统功能的函数、对系统内置类型的扩展以及一些新增数据类型等等。LuSystem不仅是对Lu系统的扩充，更在于演示Lu是极易扩充其功能的脚本，很少有脚本允许用户能方便地添加像字典、结构、类等高级的数据结构，但Lu允许，而且实现这些很容易，因而，LuSystem也是编程用户极佳的练手工具。

    主要的数据类型有：

    luu：系统内置类型lu表的扩展类型。

    String：系统内置类型字符串string的扩展类型。使用Unicode字符串。可以使用正则表达式。

    dict：字典。

    struct：结构。

    class：类。

    file：文件类型。

    在LuSystem中的函数是通过二级函数命名空间“sys”输出的，所有函数均具有类似“sys::lufun(...)”的格式。使用!!!using("sys");可简化LuSystem中的函数访问。

    LuSystem目前还不完善，主要用来演示Lu系统的可扩充性，但一些实用的功能或函数会不断添加进来，任何人也可以根据需要添加或改进函数的功能，欢迎大家给出各种改进的建议！

    LuSystem的源代码是开放的，源代码下载：http://www.forcal.net/xiazai/lu1/lu1code.rar
}#
--------------------------------------------------------------------
#lu表luu{
[LuSystem32.dll] lu表luu

    luu是系统内置类型lu表的扩展类型。luu表是一个可直接存取的线性表，可以存放若干任意的Lu数据。

    （1）新建luu表

!!!using("sys");
new[luu,5 : 1,1.2,"abc"].o[];    //用函数new生成luu表，长度为5，有三个初始化数据。函数o用于输出luu表。

    用函数luu生成luu表更为方便：

!!!using("sys");
luu[1+2i,1.2,"abc"].o[];         //用函数luu生成luu表，长度为3，有三个初始化数据。函数o用于输出luu表。

    （2）元素存取

!!!using("sys");
main(:a)= a=luu[1+2i,1.2,"abc"], a[1]=a[2]+"luuuu", o[a];

    （3）luu表连接：可用加号+连接两个luu表，或者将一个简单数加到luu表的前面或后面

!!!using("sys");
main(:a,b)= a=luu[1,1,1], b=luu[2,2], o[a+b, 3+a, a+3];
}#
--------------------------------------------------------------------
#sys::luu{
[LuSystem32.dll] sys::luu[...]：生成luu表对象并初始化。该对象的基本类型为lu，扩展类型为luu。

 sys::luu：整数常量，用在函数new[sys::luu,... ...]中，申请luu表对象。该对象的基本类型为lu，扩展类型为luu。
}#
--------------------------------------------------------------------
#luu new{
[LuSystem32.dll] luu new：该函数是重载函数，但直接调用了lu的new函数。用于申请luu表对象，该对象的基本类型为lu，扩展类型为luu。
}#
--------------------------------------------------------------------
#luu +{
[LuSystem32.dll] luu +：重载运算符+。连接两个luu表，或者将一个简单数加到luu表的前面或后面。
}#
--------------------------------------------------------------------
#luu len{
[LuSystem32.dll] luu len：该函数是重载函数，但直接调用了lu的len函数。返回luu表的长度。
}#
--------------------------------------------------------------------
#luu o{
[LuSystem32.dll] luu o：该函数是重载函数。输出luu表的内容。运行错误：1：不可识别对象。
}#
--------------------------------------------------------------------
#luu oset{
[LuSystem32.dll] luu oset：该函数是重载函数，但直接调用了lu的oset函数。设a是一个luu表，则执行形如a[i]=2的赋值语句时将调用该函数。
}#
--------------------------------------------------------------------
#luu oget{
[LuSystem32.dll] luu oget：该函数是重载函数，但直接调用了lu的oget函数。设a是一个luu表，则执行形如a[i]的语句时将调用该函数。
}#
--------------------------------------------------------------------
#字符串String{
[LuSystem32.dll] 字符串String

    String是系统内置类型字符串string的扩展类型。

（1）生成String

!!!using("sys");
new[String,5 : "abc"].o[];    //用函数new生成String，长度为5， 并用一个字符串进行初始化。函数o用于输出String，并返回输出的字符数目。

用函数String生成String更为方便：实际上该函数生成了原字符串的一个副本。

!!!using("sys");
String["abc"].o[];            //用函数String生成String，必须用一个字符串作为初始化数据。

注意：函数strcpy将原字符串复制到目标字符串，但不会返回一个新串。

!!!using("sys");
main(:a)= a=String[""], strcpy[a,"abc"], o[a];

（2）元素存取：可直接对字符串做更改。

!!!using("sys");
main1(:a)= a=String["abc"], a[1]=a[2]+1, o[a];  //动态字符串
main2(:a)= a="abc",         a[1]=a[2]+1, o[a];  //静态字符串

（3）String缓冲区大小和长度

!!!using("sys");
main(:a)= a=new[String,5 : "abc"], o{"字符串缓冲区=",len(a),"  字符串长度=",strlen(a),"\r\n"};

（4）String连接：用加号+连接两个字符串，返回一个新串。

!!!using("sys");
o{String["abc"]+String["def"]};
o{String["abc"]+"def"};

（5）String连接：用函数strcat连接两个字符串，不返回新串。

!!!using("sys");
main(:me)=
  me=String["abc"], printf["%s\r\n",me],  //输出me
  strcat(me,"def"), printf["%s\r\n",me];  //输出me

（6）大小写互换：用自定义函数实现

!!!using("sys");
Swapcase(str:i,k,ch,a,z,A,Z)=
  k="azAZ", a=k[0], z=k[1], A=k[2], Z=k[3],  //获得字符azAZ的ASCII值
  k=strlen[str], i=0,
  while{i<k, ch=str(i),
    which{ch>=a & ch<=z : str(i)=ch-a+A,
          ch>=A & ch<=Z : str(i)=ch-A+a,
          ch},
    i++
  },
  str;
Swapcase["abc 88 啊啊 DEF"].o[];

（7）格式化字符串，用sprintf函数实现

!!!using("sys");
main(:a,b,k,i,s)=
  a=String[""], sprintf[a,"%20s","abc"],  o[a,"\r\n"],  //固定长度，右对齐，左边不够用空格补齐
  a=String[""], sprintf[a,"%-20s","abc"], o[a,"\r\n"],  //固定长度，左对齐，右边不够用空格补齐
  a=String[""], b="abc", k=[20-strlen(b)]/2, s=new[String,k+1], i=0, while{i<k,s[i++]=32},
  sprintf[a,"%s%s%s",s,b,s], o[a,"\r\n"];  //固定长度，中间对齐，两边不够用空格补齐

（8）去字符串两边空格

!!!using("sys");
main(:a,i,j,k)=  a=["   asd  啊啊  def   "], i=strspn(a," \r\n\t"), strrev(a), j=strlen(a)-strspn(a," \r\n\t")-1, strrev(a), o{substr[a,i,j]};

（9）是否以start开头

!!!using("sys");
main(:a)=  a=["   start 啊啊  def   "], strspn(a," \r\n\t")==strstr(a,"start");

（10）是否全小写

!!!using("sys");
main(:a)=  a=["   start wsx  def   "], strspn(a,"abcdefghijklmnopqrstuvwxyz \r\n\t")<0;
}#
--------------------------------------------------------------------
#sys::String{
[LuSystem32.dll] sys::String["abc"]：生成String对象并 用一个字符串初始化。该对象的基本类型为string，扩展类型为String。运行错误：1：不可识别的初始化参数。 

 sys::String：整数常量，用在函数new[sys::String,... ...]中，申请String对象。该对象的基本类型为string，扩展类型为String。
}#
--------------------------------------------------------------------
#String new{
[LuSystem32.dll] String new：该函数是重载函数，但直接调用了string的new函数。用于申请String对象，该对象的基本类型为string，扩展类型为String。
}#
--------------------------------------------------------------------
#String +{
[LuSystem32.dll] String +：重载运算符+，但直接调用了string的+函数。连接两个String。
}#
--------------------------------------------------------------------
#String len{
[LuSystem32.dll] String len：该函数是重载函数，但直接调用了string的len函数。返回String的长度。
}#
--------------------------------------------------------------------
#String o{
[LuSystem32.dll] String o：该函数是重载函数。输出String的内容。运行错误：1：不可识别对象。
}#
--------------------------------------------------------------------
#String oset{
[LuSystem32.dll] String oset：该函数是重载函数，但直接调用了string的oset函数。设a是一个String，则执行形如a[i]=2的赋值语句时将调用该函数。
}#
--------------------------------------------------------------------
#String oget{
[LuSystem32.dll] String oget：该函数是重载函数，但直接调用了string的oget函数。设a是一个String，则执行形如a[i]的语句时将调用该函数。
}#
--------------------------------------------------------------------
#sys::astr{
[LuSystem32.dll] sys::astr
用法1：astr[k]。k为一个整数，返回一个k字节长的单字节字符串，初始化为一个空串。
用法2：astr[str]。str为一个双字节字符串，转换为单字节字符串并返回该串。
运行错误：1：参数非法；2：内存错误。 
}#
--------------------------------------------------------------------
#sys::ustr{
[LuSystem32.dll] sys::ustr
用法：astr[str]。str为一个单字节字符串，转换为双字节字符串并返回该串。
运行错误：1：参数非法；2：内存错误。
}#
--------------------------------------------------------------------
#astring o{
[LuSystem32.dll] astring o：该函数是重载函数。仅提示信息： ***ASCII字符串须先用函数ustr转换为Unicode字符串后才能显示*** 
}#
--------------------------------------------------------------------
#sys::strlen{
[LuSystem32.dll] sys::strlen[str] 返回字符串str的长度。len(str)返回字符串str的缓冲区大小。运行错误：1：不可识别对象。 
}#
--------------------------------------------------------------------
#sys::strcpy{
[LuSystem32.dll] sys::strcpy[str1,str2]
复制字符串str2到str1。当str1是动态字符串时，如果缓冲区不够用，会自动增加缓冲区。该函数不生成新的字符串 ，仍返回str1。
运行错误：1：参数非法；2：内存错误；3：静态缓冲区不够用。 
}#
--------------------------------------------------------------------
#sys::strcat{
[LuSystem32.dll] sys::strcat[str1,str2]
将字符串str2连接到str1的后面。当str1是动态字符串时，如果缓冲区不够用，会自动增加缓冲区。该函数不生成新的字符串 ，仍返回str1。
运行错误：1：参数非法；2：内存错误；3：静态缓冲区不够用。 
}#
--------------------------------------------------------------------
#sys::substr{
[LuSystem32.dll] sys::substr[str,begin,end]
返回字符串str的子字符串，begin和end指定了子字符串的位置。如果begin或end为-1，或者大于字符串长度，取字符串的最后一个字符位置；此时，若begin>end，取end和begin之间字符串的反序字符串。

运行错误：1：参数非法；2：内存错误。

例子1：substr["abcdefg",-1,3]，结果：gfed
例子2：substr["abcdefg",3,-1]，结果：defg
}#
--------------------------------------------------------------------
#sys::strchr{
[LuSystem32.dll] sys::strchr[str,c]：在字符串str中定位首次出现的字符c（整数），返回c在str中的下标（相对偏移量），失败时返回-1。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strrchr{
[LuSystem32.dll] sys::strrchr[str,c]：在字符串str中定位最后出现的字符c（整数），返回c在str中的下标（相对偏移量），失败时返回-1。运行错误：1：参数非法。  
}#
--------------------------------------------------------------------
#sys::strcmp{
[LuSystem32.dll] sys::strcmp[str1,str2]：按字母顺序，对字符串进行比较。若str1<str2，返回值<0；若str1=str2，返回值=0；若str1>str2，返回值>0。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strpbrk{
[LuSystem32.dll] sys::strpbrk[str1,str2]：在字符串str1中定位字符集str2中首次出现的某个字符，返回这个字符在str1中的下标（相对偏移量），失败时返回-1。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strspn{
[LuSystem32.dll] sys::strspn[str1,str2]：在字符串str1中定位首次出现的不包含在字符集str2中的某个字符，返回这个字符在str1中的下标（相对偏移量），失败时返回-1。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strstr{
[LuSystem32.dll] sys::strstr[str1,str2,begin,end]：在字符串str1中查找子串str2，返回子串在str1中的位置（相对偏移量），失败时返回-1。begin和end指定了查找位置；若缺省end，则从begin位置开始查找；若begin和end都缺省，则查找整个字符串。运行错误：1： 参数个数非法；2：参数非法。 
}#
--------------------------------------------------------------------
#sys::strtok{
[LuSystem32.dll] sys::strtok[str1,str2]
在字符串str1（包含分隔符和记号）中提取记号，str2是包含分隔符的字符串，返回一个luu对象，luu对象包含了所有提取的记号，失败时返回nil。
运行错误：1：参数非法。
例子：sys::strtok["one,two three , four*five", ", *"].o[]; 
}#
--------------------------------------------------------------------
#sys::strlwr{
[LuSystem32.dll] sys::strlwr[str]：将字符串str转换为小写，仍返回该字符串。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strupr{
[LuSystem32.dll] sys::strupr[str]：将字符串str转换为大写，仍返回该字符串。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strset{
[LuSystem32.dll] sys::strset[str,ch,begin,end]：将字符串str中从begin～end的内容设置为字符ch。若缺省begin和end，则设置整个内容；若仅缺省end，则设置从begin开始的内容。仍返回该字符串。运行错误：1：参数个数非法；2：参数非法。 
}#
--------------------------------------------------------------------
#sys::strrev{
[LuSystem32.dll] sys::strrev[str]：反转字符串str中的字符顺序，仍返回该字符串。运行错误：1：参数非法。 
}#
--------------------------------------------------------------------
#sys::strrep{
[LuSystem32.dll] sys::strrep[str,oldstr,newsyt,start,ntimes]
将字符串str中的子串oldstr替换为newstr，返回替换后的字符串。start为查找替换的开始位置，缺省为从头开始替换。ntimes指定进行替换的次数，缺省表示替换所有匹配。
运行错误：1：参数个数非法；2：参数非法 ；3：内存错误。  
}#
--------------------------------------------------------------------
#sys::strdate{
[LuSystem32.dll] sys::strdate[]：把日期拷贝到一个字符串中并返回该字符串，失败时返回nil。 
}#
--------------------------------------------------------------------
#sys::strtime{
[LuSystem32.dll] sys::strtime[]：把时间拷贝到一个字符串中并返回该字符串，失败时返回nil。 
}#
--------------------------------------------------------------------
#sys::ComRegex{
[LuSystem32.dll] sys::ComRegex(pattern,flags)：编译正则表达式文本

    pattern：字符串，正则表达式。
    flags：表达式匹配模式。支持的匹配模式有：sys::reIgnoreCase, sys::reSingleline, sys::reMultiline, sys::reGlobal, sys::reRightToLeft, sys::reExtended 这 6 种模式以及它们的组合，或者使用缺省的sys::reNoFlag模式。可以缺省该参数，缺省值为sys::reNoFlag。详细说明如下：

    sys::reIgnoreCase ：匹配时忽略大小写。默认情况下，正则表达式是要区分大小写的。不管是否指定忽略大小写模式，字符类，比如 [A-Z] 是要区分大小写的。

    sys::reSingleline ：使小数点 "." 可以匹配包含换行符（\n）在内的任意字符。默认情况下，小数点只匹配换行符以外的任意字符，不匹配换行符。

    sys::reMultiline ：使 ^ 符号除了能够匹配字符串开始位置外，还能匹配换行符（\n）之后的位置；使 $ 符号除了能够匹配字符串结束位置外，还能匹配换行符之前的位置。默认情况下， ^ 符号只能匹配字符串开始位置， $ 符号只能匹配字符串结束位置。sys::reSingleline 和 sys::reMultiline 虽然听起来相互矛盾，但却是作用在不同的地方。因此它们是可以组合使用的。在指定了 sys::reMultiline 之后，如果需要仅匹配字符串开始和结束位置，可以使用 \A 和 \Z。

    sys::reGlobal ：使 \G 可以用来匹配本次查找匹配的开始位置，对于连续的匹配来说，也就是上次匹配的结束位置。默认情况下， \G 没有作用。在进行替换操作（Replace）时，不管是否指定 sys::reGlobal 模式，都可以进行所有的替换。是否指定 sys::reGlobal 模式只是对 \G 起作用。如果希望进行有限次数的替换，可在替换操作时指定替换次数。

    sys::reRightToLeft ：从右向左的进行匹配。从被匹配字符串的结束位置向前进行查找匹配，同时，在表达式中也是右侧的表达式先进行匹配。表达式的写法仍然按原来的习惯：匹配次数修饰符（*, +, {n}, ……）仍然位于被修饰部分的右侧而不是左侧；^ 仍然匹配文本开始而不是文本结束；(?=xxx) 仍然是正向与搜索（向右预搜索），而不是向左；分组（group）编号仍然是从左向右进行编号；等等。不管整个表达式是否指定了 sys::reRightToLeft 模式，"反向预搜索（反向零宽度断言）" 内的表达式始终采用 sys::reRightToLeft 模式。

    sys::reExtended ：使 DEELX 忽略表达式中的空白字符，并且把从 # 开始到该行行末的内容视为注释。默认情况下，正则表达式中的空格，换行等字符将可以匹配相应的字符。指定了 sys::reExtended 模式后，如果要在正则表达式中表示空白字符比如空格符号（space）时，应该用 \x20 表示，如果要在表达式中表示 # 符号，应该用 \# 表示。不管是否指定了 sys::reExtended 模式，括号内以 ?# 号开始时，比如(?# xxx )，那么这一对括号以及包含的内容都始终作为注释而被忽略。

    返回值：pattern。出错时返回nil。

    说明：任何一个正则表达式对象，都需要先用该函数编译正则表达式文本后才能使用。

    运行错误：1：参数个数非法；2：参数非法。

    例子：判断一个字符串是否全由数字组成

!!!using["sys"];                              //使用命名空间sys
main()=
{
    ComRegex(@"\d+"),                         //编译正则表达式文本
    MatchExact("12345"),                      //验证是否刚好匹配
    which{
        IsMatched() : printf{"\r\nyes!\r\n"}, //匹配成功输出yes
        printf{"\r\nno!\r\n"}                 //匹配失败输出no
    }
};
}#
--------------------------------------------------------------------
#sys::MatchExact{
[LuSystem32.dll] sys::MatchExact(str)：验证传入的文本是否刚好匹配正则表达式

    str：进行匹配的字符串。

    返回值：str。

    说明：所谓刚好匹配，就是要求正则表达式从文本开始位置刚好匹配到文本结束位置。匹配结果可通过函数sys::IsMatched获取。

    运行错误：1：非法的字符串。
}#
--------------------------------------------------------------------
#sys::Match{
[LuSystem32.dll] sys::Match(... ...)：从文本中查找匹配符合表达式的子字符串

    格式1：sys::Match()：使用上下文对象，从上次匹配结束位置或者初始化位置开始查找匹配。上下文对象需要先使用函数sys::PrepareMatch进行初始化。
    格式2：sys::Match(str)：Match 方法未指定开始位置，则根据当前匹配模式是否是 sys::reRightToLeft 模式决定开始位置：如果是普通模式，则从 0 开始，向右查找；如果是 sys::reRightToLeft 模式，则从字符串结束位置开始，向左查找。
    格式3：sys::Match(str,start)：Match 方法指定了开始位置，则从指定位置开始查找。

    str：进行匹配的字符串。
    start：开始查找匹配的位置。

    返回值：str。

    说明：匹配结果可通过函数sys::IsMatched等函数获取。

    运行错误：1：参数个数非法；2：参数非法。

    例子1：Match格式1：在一段 C++ 源代码文本中，查找注释

!!!using["sys"];
main(:str)=
{
    str=new(string,"int a; /* a */"),          //申请字符串，存放源代码
    ComRegex(@"/\*((?!\*/).)*(\*/)?|//([^\x0A-\x0D\\]|\\.)*"),  //编译正则表达式文本
    PrepareMatch(str),                         //匹配准备
    Match(),                                   //匹配子字符串
    which{
        IsMatched() : printf{"\r\nfound:%s\r\n",substr[str,GetStart(),GetEnd()-1]},   //匹配成功输出匹配结果
        printf{"\r\nnot found!\r\n"}           //匹配失败输出 not found!
    }
};

    例子2：Match格式2：在一段 C++ 源代码文本中，查找注释

!!!using["sys"];
main(:str)=
{
    str=new(string,"int a; /* a */"),          //申请字符串，存放源代码
    ComRegex(@"/\*((?!\*/).)*(\*/)?|//([^\x0A-\x0D\\]|\\.)*"),  //编译正则表达式文本
    Match(str),                                //匹配子字符串
    which{
        IsMatched() : printf{"\r\nfound:%s\r\n",substr[str,GetStart(),GetEnd()-1]},   //匹配成功输出匹配结果
        printf{"\r\nnot found!\r\n"}           //匹配失败输出 not found!
    }
};

    例子3：列举一段文本中所有的带小数的数字

!!!using["sys"];
main(:str,result)=
{
    str=new(string,"12.5, a1.1, 0.123, 178"),  //申请字符串，存放文本
    ComRegex(@"\b\d+\.\d+"),                   //编译正则表达式文本
    PrepareMatch(str),                         //匹配准备
    Match(),                                   //匹配子字符串
    while{IsMatched(),                         //匹配成功输出匹配结果
        printf{"%s\r\n",substr[str,GetStart(),GetEnd()-1]},
        Match()                                //匹配子字符串
    }
};
}#
--------------------------------------------------------------------
#sys::GetNamedGroupNumber{
[LuSystem32.dll] sys::GetNamedGroupNumber(GroupName)：通过命名分组名，返回命名分组编号

    GroupName：字符串，命名分组名。

    返回值：命名分组编号。

    运行错误：1：非法的字符串。
}#
--------------------------------------------------------------------
#sys::PrepareMatch{
[LuSystem32.dll] sys::PrepareMatch(tstring,start)：初始化上下文对象，准备从文本中查找匹配符合表达式的子字符串

    tstring：进行匹配的字符串。
    start：开始查找的起始位置。可以缺省该参数，此时根据当前匹配模式是否是 sys::reRightToLeft 模式决定开始位置：如果是普通模式，则从 0 开始，向右查找；如果是 sys::reRightToLeft 模式，则从结束位置开始，向左查找。

    返回值：tstring。

    运行错误：1：参数个数非法；2：参数非法。
}#
--------------------------------------------------------------------
#sys::Replace{
[LuSystem32.dll] sys::Replace(str,rplto,start,ntimes)：文本替换操作

    str：字符串。被进行替换的初始文本。
    rplto：“替换为”字符串，将匹配到的子字符串替换成 rplto 字符串。
    start：进行查找替换的开始位置。可以缺省该参数（默认-1），此时根据是否是 sys::reRightToLeft 自动决定开始位置。
    ntimes：指定进行替换的次数。可以缺省该参数（默认-1），此时表示替换所有匹配。

    返回值：替换后得到的新字符串。

    运行错误：1：参数个数非法；2：参数非法；3：内存错误。
}#
--------------------------------------------------------------------
#sys::IsMatched{
[LuSystem32.dll] sys::IsMatched()：获取是否匹配成功

    返回值：返回 true 表示匹配成功，返回 false 表示匹配失败。
}#
--------------------------------------------------------------------
#sys::GetStart{
[LuSystem32.dll] sys::GetStart()：获取匹配到的子字符串开始位置

    返回值：匹配成功后，获取所匹配到的子字符串的开始位置。如果匹配失败，则返回负值。
}#
--------------------------------------------------------------------
#sys::GetEnd{
[LuSystem32.dll] sys::GetEnd()：获取匹配到的子字符串结束位置

    返回值：匹配成功后，获取所匹配到的子字符串的结束位置。如果匹配失败，则返回负值。
}#
--------------------------------------------------------------------
#sys::GetGroupStart{
[LuSystem32.dll] sys::GetGroupStart(nGroupNumber)：获取分组开始位置

    nGroupNumber：整数，分组编号。

    返回值：获取指定分组捕获的字符串的开始位置。如果指定分组未捕获，或者整个表达式未匹配成功，则返回负值。

    运行错误：1：非法的参数。
}#
--------------------------------------------------------------------
#sys::GetGroupEnd{
[LuSystem32.dll] sys::GetGroupEnd(nGroupNumber)：获取分组结束位置

    nGroupNumber：整数，分组编号。

    返回值：获取指定分组捕获的字符串的结束位置。如果指定分组未捕获，或者整个表达式未匹配成功，则返回负值。

    运行错误：1：非法的参数。
}#
--------------------------------------------------------------------
#sys::MaxGroupNumber{
[LuSystem32.dll] sys::MaxGroupNumber()：获取正则表达式最大捕获组编号

    返回值：返回最大分组编号。
}#
--------------------------------------------------------------------
#sys::fopen{
[LuSystem32.dll] sys::fopen("filename","mode")：打开文件

    "filename"：文件名，可以包含路径和文件名两部分。
    "mode"：打开文件的类型。关于文件类型的规定参见下面说明。
    返回值：操作成功，返回有效的文件句柄hFile。否则返回nil。无需检查文件句柄是否有效，相应的文件操作函数会自动进行检查。

    运行错误：1：需要字符串参数指出文件名和文件访问模式；2：文件访问模式错误。

    说明：

文件名格式：
	"B:TEST.DAT"
	"C:\\TC\\TEST.DAT"
注意：如果将路径写成"C:\TC\TEST.DAT"是不正确的, 这一点要特别注意。
fopen函数用来打开一个文件，其调用的一般形式为：fopen(文件名,使用文件方式)
 其中，“文件名”是被打开文件的文件名。“使用文件方式”是指文件的类型和操作要求。“文件名”是一个字符串。例如： 
	fopen("file a","r");
其意义是在当前目录下打开文件file a，只允许进行“读”操作。
又如：
	fopen("c:\\hzk16","rb")
其意义是打开C驱动器磁盘的根目录下的文件hzk16， 这是一个二进制文件，只允许按二进制方式进行读操作。
两个反斜线“\\ ”中的第一个表示转义字符，第二个表示根目录。使用文件的方式共有12种，下面给出了它们的符号和意义。
                   表 文件操作类型
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      字符                 含义
────────────────────────────
       "r"            打开文字文件只读
       "w"            创建文字文件只写
       "a"            增补, 如果文件不存在则创建一个
       "r+"           打开一个文字文件读/写
       "w+"           创建一个文字文件读/写
       "a+"           打开或创建一个文件增补
       "b"            二进制文件(可以和上面每一项合用)
       "t"            文这文件(默认项)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

文件使用方式 　　　　　　　意 义

"rt"　　　　　　只读打开一个文本文件，只允许读数据 
"wt"　　　　　　只写打开或建立一个文本文件，只允许写数据
"at"　　　　　　追加打开一个文本文件，并在文件末尾写数据
"rb"　　　　　　只读打开一个二进制文件，只允许读数据
"wb"　　　　 　 只写打开或建立一个二进制文件，只允许写数据
"ab" 　　　　 　追加打开一个二进制文件，并在文件末尾写数据
"rt+"　　　　　 读写打开一个文本文件，允许读和写
"wt+"　　　　　 读写打开或建立一个文本文件，允许读写
"at+"　　　　　 读写打开一个文本文件，允许读，或在文件末追加数据
"rb+"　　　　　 读写打开一个二进制文件，允许读和写 
"wb+"　　　　　 读写打开或建立一个二进制文件，允许读和写
"ab+" 　　　　　读写打开一个二进制文件，允许读，或在文件末追加数据

对于文件使用方式有以下几点说明：

1. 文件使用方式由r,w,a,t,b，+六个字符拼成，各字符的含义是：

	r(read): 读
	w(write): 写
	a(append): 追加
	t(text): 文本文件，可省略不写
	b(banary): 二进制文件
	+: 读和写

2. 凡用"r"打开一个文件时，该文件必须已经存在，且只能从该文件读出。

3. 用"w"打开的文件只能向该文件写入。若打开的文件不存在，则以指定的文件名建立该文件，若打开的文件已经存在，则将该文件删去，重建一个新文件。

4. 若要向一个已存在的文件追加新的信息，只能用"a "方式打开文件。但此时该文件必须是存在的，否则将会出错。

5. 在打开一个文件时，如果出错，fopen将返回一个空指针值NULL给文件句柄hFile，后续文件操作将不能正常进行。

6. 把一个文本文件读入内存时，要将ASCII码转换成二进制码，而把文件以文本方式写入磁盘时，也要把二进制码转换成ASCII码，因此文本文件的读写要花费较多的转换时间。

7. 对二进制文件的读写不存在转换。

8. Unicode文本文件的标志是：文件长度是偶数，首字符为sys::UTEXT（该字符仅是一个标志，不包括在有效的Unicode文本文件内容中）。


如果要打开一个CCDOS子目录中, 文件名为CLIB的二进制文件, 可写成:
	fopen("c:\\ccdos\\clib", "rb");
    [例子1] 读Unicode文本文件（以起始字符UTEXT为标志）并显示其内容，表达式之间用模块变量传递参数

!!!using["sys"];            //使用命名空间“sys”
main(:f,len,s,x)=
  f=fopen["aa.txt","rb"],   //打开文件，"aa.txt"必须是已经存在的Unicode文本文件
  fseek(f,0,SEEK_END),      //把文件指针移动到文件末尾，记得显示文件内容时要把指针移动回到文件头部
  len=ftell[f],             //获取文件指针的位置，相当于得到文件的长度了
  s=new[string,len+1],      //根据文件长度申请内存空间，使读取文件长度获得一定的灵活性，注意后面加一的意义
  rewind[f],                //把文件指针移动到文件开头，当然也可以用fseek()完成这个动作
  x=0, fread[f,&x,2],       //读取第一个字符到x，若为Unicode文本文件，该字符应为UTEXT，可以进行判断，这里省略了
  fread[f,s],               //读取文件
  fclose[f],                //关闭文件
  printf["%s\r\n",s];       //输出文件内容

    [例子2] 二进制文件读写

!!!using["sys"];
main(:f,d,e)=
  d=new[ints,5,data:1,2,3,4,5], e=new[ints,5,data:0,0,0,0,0],
  f=fopen["bb.txt","wb+"],
  fwrite[f,d], rewind[f], fread[f,e],
  fclose[f],
  printf{"%i %i %i %i %i\r\n",e[0],e[1],e[2],e[3],e[4]};

    [例子3] Unicode文本文件读写，用二进制文件实现

!!!using["sys"];
main(:f,d,e,x)=
  d=new[string,"hello!\r\nLu!"],e=new[string,80],
  f=fopen["cc.txt","wb+"],
  fwrite[f,UTEXT,2], fwrite[f,d],
  rewind[f], x=0, fread[f,x,2], fread[f,e],
  fclose[f],
  printf["%s\r\n",e];
}#
--------------------------------------------------------------------
#sys::fclose{
[LuSystem32.dll] sys::fclose(hFile)：关闭文件

    hFile：文件句柄。
    返回值：操作成功，返回0。否则返回sys::EOF。
    说明：也可以用delete(hFile)关闭文件。如果使用del(hFile)，将不能立即关闭文件。
}#
--------------------------------------------------------------------
#sys::fwrite{
[LuSystem32.dll] sys::fwrite(hFile,value,size)或sys::fwrite(hFile,buffer,count)：写文件

    hFile：文件句柄。
    value：简单数据（支持整数、实数、复数和向量）。
    size：简单数据的字节数。size=1～24。size=1表示8位数（如一个ASCII字符）；size=2表示16位数（如一个Unicode字符）；size=4表示32位数；size=8表示64位数（Lu默认整数或实数）。可以缺省该参数，此时，若value是一个整数、实数、指针，size=8；若value是一个复数，size=16；若value是一个向量，size=24。
    buffer：数组数据（支持ASCII字符串、Unicode字符串、整数数组、实数数组）。将写数组的全部数据，或者count指定的数据数目。
    count：写入数据的最大数目。如果该值大于数组长度，该值被忽略，将写全部数据。该参数可以缺省，表示写全部数据。
    返回值：返回写入的数据对象的数目。

    运行错误：1：只能有2个或3个参数；2：不可识别参数，例如非法的文件句柄等；3：数据的字节数或数据数目非法；4：不可识别的字符串；5：不可识别的ASCII字符串；6：不可识别的数组；7：简单数据的字节数太多。
}#
--------------------------------------------------------------------
#sys::fread{
[LuSystem32.dll] sys::fread(hFile,value,size)或sys::fread(hFile,buffer,count)：读文件

    hFile：文件句柄。
    value：简单数据（支持整数、实数、复数和向量）。
    size：简单数据的字节数。size=1～24。size=1表示8位数（如一个ASCII字符）；size=2表示16位数（如一个Unicode字符）；size=4表示32位数；size=8表示64位数（Lu默认整数或实数）。可以缺省该参数，此时，若value是一个整数、实数、指针，size=8；若value是一个复数，size=16；若value是一个向量，size=24。
    buffer：数组数据（支持ASCII字符串、Unicode字符串、整数数组、实数数组）。将读满数组的全部数据，或者count指定的数据数目。
    count：读入数据的最大数目。如果该值大于数组长度，该值被忽略，仅读满全部数据。该参数可以缺省，表示读全部数据。
    返回值：返回读取的数据对象的数目。

    运行错误：1：只能有2个或3个参数；2：不可识别参数，例如非法的文件句柄等；3：数据的字节数或数据数目非法；4：不可识别的字符串；5：不可识别的ASCII字符串；6：不可识别的数组；7：简单数据的字节数太多。
}#
--------------------------------------------------------------------
#sys::fseek{
[LuSystem32.dll] sys::fseek(hFile,offset,origin)：设置文件指针的位置

    hFile：文件句柄。
    offset：文件指针从origin开始的偏移字节数。
    origin：起始位置，函数从该位置开始增加偏移量。只能取sys::SEEK_CUR（当前位置），sys::SEEK_END（文件尾）和sys::SEEK_SET（文件头）。
    返回值：成功时返回0，否则返回非0值。

    运行错误：1：不可识别参数；2：非法的起始位置；3：非法的文件句柄。
}#
--------------------------------------------------------------------
#sys::feof{
[LuSystem32.dll] sys::feof(hFile)：判断是否到文件尾

    hFile：文件句柄。
    返回值：没有到达文件尾时返回0，否则返回非0值。

    运行错误：1：非法的文件句柄。
}#
--------------------------------------------------------------------
#sys::fflush{
[LuSystem32.dll] sys::fflush(hFile)：刷新一个打开的流，将缓冲区中的内容写入文件

    hFile：文件句柄。
    返回值：操作成功，返回0。否则返回sys::EOF。

    运行错误：1：非法的文件句柄。
}#
--------------------------------------------------------------------
#sys::ftell{
[LuSystem32.dll] sys::ftell(hFile)：获取文件指针位置

    hFile：文件句柄。
    返回值：操作失败返回-1。

    运行错误：1：非法的文件句柄。
}#
--------------------------------------------------------------------
#sys::rewind{
[LuSystem32.dll] sys::rewind(hFile)：把文件指针设置回文件的起始位置

    hFile：文件句柄。
    返回值：hFile。

    运行错误：1：非法的文件句柄。
}#
--------------------------------------------------------------------
#sys::printf{
[LuSystem32.dll] sys::printf(FormatStr,x1,x2,... ...)：格式化输出到标准设备

    FormatStr：格式串（字符串），可包括文本和下表中的控制码。格式化字符串包括两部分内容：一部分是正常字符，这些字符将按原样输出；另一部分是格式化规定字符，以“%”开始, 后跟一个或几个规定字符用来确定输出内容格式。
    x1,x2,... ...：与格式串中的控制代码相匹配的数据项列表。数据项的个数与格式说明的个数一致，格式说明和数据项在顺序上相互对应。
    返回值：输出字符数（出错时返回-1）。

    运行错误：1：不能将字符串发送到自己的地址；2：字符串太多，无法申请缓冲区；3：内存错误；4：缺少格式字符串；5：缺少数据项；6：非法的字符串指针；7：无法识别格式串；8：数据项多于格式符；9：格式化输出错误。

函数printf()的格式说明符

说明符 描述 
%% 说明一个宽字符“%”。 
%C 说明一个宽字符。 
%d 说明一个带符号的10进制整数。 
%e 说明一个带符号的双精度浮点值，该值是用带小写字母“e”的科学计数法表示的。 
%E 说明一个带符号的双精度浮点值，该值是用带大写字母“E”的科学计数法表示的。 
%f 说明一个带符号的双精度浮点值。 
%g 说明一个带符号的双精度浮点值，该值是用正常方法表示的，或者是用带小写字母“e”的科学计数法表示的。 
%G 说明一个带符号的双精度浮点值，该值是用正常方法表示的，或者是用带大写字母“E”的科学计数法表示的。 
%i 说明一个带符号的10进制整数。 
%n 说明一个数，该数用于接收已写字符的个数。 
%o 说明一个无符号的8进制整数（此格式符工作不正常） 。 
%p 说明一个指针，在32位平台上，指针为一个数的前4个字节。 
%s 说明一个字符串，如果指定域宽，域宽最大为99。 
%u 说明一个无符号的10进制整数。 
%x 说明一个无符号的16进制整数，整数中的字母是用小写字母表示的。 
%X 说明一个无符号的16进制整数，整数中的字母是用大写字母表示的。 

    printf格式控制符的完整格式：

    printf的格式控制的完整格式：
    %  -  0  m.n  l、h或I64  格式字符
    下面对组成格式说明的各项加以说明：
    ①%：表示格式说明的起始符号，不可缺少。
    ②-：有-表示左对齐输出，如省略表示右对齐输出。
    ③0：有0表示指定空位填0,如省略表示指定空位不填。
    ④m.n：m指域宽，即对应的输出项在输出设备上所占的字符数。n指精度。用于说明输出的实型数的小数位数。为指定n时，隐含的精度为n=6位。
    ⑤l、h或I64：l对整型指long型，对实型指double型。h用于将整型的格式字符修正为short型。I64用于说明一个64位整数。

    －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－
    格式字符
    格式字符用以指定输出项的数据类型和输出格式。
     ①d格式：用来输出十进制整数。有以下几种用法：
    %d：按整型数据的实际长度输出。
    %md：m为指定的输出字段的宽度。如果数据的位数小于m，则左端补以空格，若大于m，则按实际位数输出。
    %ld：输出长整型数据。
    ②o格式：以无符号八进制形式输出整数。对长整型可以用"%lo"格式输出。同样也可以指定字段宽度用“%mo”格式输出。
    例：
     printf("%d, %o", -1, -1);
     运行结果：-1,177777
     程序解析：-1在内存单元中（以补码形式存放）为(1111111111111111)2，转换为八进制数为(177777)8。
    ③x格式：以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出。同样也可以指定字段宽度用"%mx"格式输出。
    ④u格式：以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。同样也可以指定字段宽度用“%mu”格式输出。
    ⑤c格式：输出一个字符。
    ⑥s格式：用来输出一个串。有几中用法
    %s：例如:printf("%s", "CHINA")输出"CHINA"字符串（不包括双引号）。
    %ms：输出的字符串占m列，如字符串本身长度大于m，则突破获m的限制,将字符串全部输出。若串长小于m，则左补空格。
    %-ms：如果串长小于m，则在m列范围内，字符串向左靠，右补空格。
    %m.ns：输出占m列，但只取字符串中左端n个字符。这n个字符输出在m列的右侧，左补空格。
    %-m.ns：其中m、n含义同上，n个字符输出在m列范围的左侧，右补空格。如果n>m，则自动取n值，即保证n个字符正常输出。
    ⑦f格式：用来输出实数（包括单、双精度），以小数形式输出。有以下几种用法：
    %f：不指定宽度，整数部分全部输出并输出6位小数。
    %m.nf：输出共占m列，其中有n位小数，如数值宽度小于m左端补空格。 
    %-m.nf：输出共占n列，其中有n位小数，如数值宽度小于m右端补空格。
    ⑧e格式：以指数形式输出实数。可用以下形式：
    %e：数字部分（又称尾数）输出6位小数，指数部分占5位或4位。
    %m.ne和%-m.ne：m、n和”-”字符含义与前相同。此处n指数据的数字部分的小数位数，m表示整个输出数据所占的宽度。
    ⑨g格式：自动选f格式或e格式中较短的一种输出，且不输出无意义的零。

    －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－
    对于单精度数，使用%f格式符输出时，仅前7位是有效数字，小数6位。
    对于双精度数，使用%lf格式符输出时，前16位是有效数字，小数6位。

    例子：

sys::printf("a=%d\r\n", 123);                     //输出十进制整数a=123
sys::printf("a=%6d\r\n", 123);                    //输出6位十进制数a= 123
sys::printf("a=%06d\r\n", 123);                   //输出6位十进制数a=000123
sys::printf("a=%2d\r\n", 123);                    //超过2位,按实际值输出a=123
sys::printf("i=%-6d\r\n", 123);                   //输出左对齐6位十进制整数i=123 
sys::printf("i=%p\r\n", 1111111111111);           //输出地址类似于i=211C7000
sys::printf("f=%f\r\n", 3.141593);                //输出浮点数f=3.141593
sys::printf("f=%6.4f\r\n", 3.141593);             //输出6位其中小数点后4位的浮点数f=3.1416 
sys::printf("x=%lf\r\n", 0.123457);               //输出长浮点数x=0.123457
sys::printf("x=%18.16lf\r\n", 0.1234567898765432);//输出18位其中小数点后16位的长浮点x=0.1234567898765432
sys::printf("c=%C\r\n", 66);                      //输出字符c=B
sys::printf("s=%s\r\n", "hello！您好！");          //输出数组字符串s=hello！您好！
sys::printf("X=%X\r\n", 1234567890123456789);     //输出16进制整数X=7DE98115
sys::printf("X=%I64X\r\n", 1234567890123456789);  //输出16进制整数X=112210F47DE98115
}#
--------------------------------------------------------------------
#sys::sprintf{
[LuSystem32.dll] sys::sprintf(str,FormatStr,x1,x2,... ...)：格式化输出到字符串

    str：动态字符串。所有输出将保存到该字符串。如果该字符串不够用，该函数会自动增加字符串的大小。
    FormatStr：格式字符串，可包括文本和控制码。格式化字符串包括两部分内容：一部分是正常字符，这些字符将按原样输出；另一部分是格式化规定字符，以“%”开始, 后跟一个或几个规定字符用来确定输出内容格式。
    x1,x2,... ...：与格式串中的控制代码相匹配的数据项列表。数据项的个数与格式说明的个数一致，格式说明和数据项在顺序上相互对应。
    返回值：输出字符数（出错时返回-1）。

    运行错误：1：非法的动态字符串指针str；2：不能将字符串发送到自己的地址；3：字符串太多，无法申请缓冲区；4：内存错误；5：缺少格式字符串；6：缺少数据项；7：非法的字符串指针；8：无法识别格式串；9：数据项多于格式符；10：格式化输出错误。

    说明：该函数功能与printf类似，仅将输出定向到字符串，请参考printf的说明。

    例子：

(:s)= s=new[string,100,""],sys::sprintf(s,"a=%06d\r\n", 123),sys::printf["%s",s]; //输出6位十进制数a=000123
}#
--------------------------------------------------------------------
#sys::fprintf{
[LuSystem32.dll] sys::fprintf(pfile,FormatStr,x1,x2,... ...)：格式化输出到文件

    pfile：文件句柄。所有输出将保存到该文件。
    FormatStr：格式字符串，可包括文本和控制码。格式化字符串包括两部分内容：一部分是正常字符，这些字符将按原样输出；另一部分是格式化规定字符，以“%”开始, 后跟一个或几个规定字符用来确定输出内容格式。
    x1,x2,... ...：与格式串中的控制代码相匹配的数据项列表。数据项的个数与格式说明的个数一致，格式说明和数据项在顺序上相互对应。
    返回值：输出字符数（出错时返回-1）。

    运行错误：1：非法的文件句柄；2：缺少格式字符串；3：缺少数据项；4：非法的字符串指针；5：无法识别格式串；6：数据项多于格式符；7：格式化输出错误。

    说明：该函数功能与printf类似，仅将输出定向到文件，请参考printf的说明。

    例子：

!!!using["sys"];
main(:f,d,e,x)=
  d=new[string,"您好！\r\nhello!\r\n"],
  f=fopen["dd.txt","wb+"],
  fwrite[f,UTEXT,2], fprintf(f,"a=%06d\r\n%s", 123,d),
  e=new[string,(ftell(f)-1)/2],
  rewind[f], x=0, fread[f,x,2], fread[f,e],
  fclose[f],
  printf["\r\n%s\r\n",e];
}#
--------------------------------------------------------------------
#sys::sscanf{
[LuSystem32.dll] sys::sscanf(str,FormatStr,&x1,&x2,... ...)：从字符串格式化输入

    str：字符串指针。所有数据将从该字符串读取。
    FormatStr：格式串（字符串），可包括文本和控制码。格式化字符串包括两部分内容：一部分是正常字符，另一部分是格式化规定字符，以“%”开始, 后跟一个或几个规定字符用来确定输出内容格式。
    &x1,&x2,... ...：与格式串中的控制代码相匹配的数据项列表。数据项的个数与格式说明的个数一致，格式说明和数据项在顺序上相互对应。
    返回值：返回成功地处理的数据项的个数（出错时返回-1）。在此例中，若仅读取了x1，返回3；若处理到x2，返回4；以此类推。

    运行错误：1：源字符串不存在；2：缺少格式串；3：源字符串的偏移量非法；4：内存错误；5：缺少数据项；6：非法的字符串指针；7：源字符串与目的字符串相同，无法操作；8：静态字符串缓冲区太小，无法接收字符；9：无法识别格式串；10：数据项多于格式符。

函数sscanf()的格式说明符

说明符 描述 
%& 说明一个相对于源字符串的偏移量，将从该位置从字符串中读取数据。该说明符仅用于格式串的开头。该说明符仅用于sscanf()函数。 
%% 说明一个宽字符“%”。 
%C 说明一个宽字符。 
%d 说明一个带符号的10进制整数。 
%e 说明一个带符号的双精度浮点值，该值是用带小写字母“e”的科学计数法表示的。 
%E 说明一个带符号的双精度浮点值，该值是用带大写字母“E”的科学计数法表示的。 
%f 说明一个带符号的双精度浮点值。 
%g 说明一个带符号的双精度浮点值，该值是用正常方法表示的，或者是用带小写字母“e”的科学计数法表示的。 
%G 说明一个带符号的双精度浮点值，该值是用正常方法表示的，或者是用带大写字母“E”的科学计数法表示的。 
%i 说明一个带符号的10进制整数。 
%n 说明一个数，该数用于接收已读字符的个数。在函数fscanf()中，该数用于接收当前的文件指针位置。 
%o 说明一个无符号的8进制整数（此格式符工作不正常） 。 
%p 说明一个指针，在32位平台上，指针为一个数的前4个字节。 
%s 说明一个字符串。 
%u 说明一个无符号的10进制整数。 
%x 说明一个无符号的16进制整数，整数中的字母是用小写字母表示的。 
%X 说明一个无符号的16进制整数，整数中的字母是用大写字母表示的。 

    sscanf格式控制符的完整格式：{%[*] [width] [{h | l | I64 | L}]type | 非%符号}

    说明：

    1、* 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入(也就是不把此数据读入参数中) 。
    2、{a|b|c}表示a,b,c中选一，[d],表示可以有d也可以没有d。 
    3、width表示读取宽度。
    4、{h | l | I64 | L}:参数的size,通常h表示单字节size，I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
    5、type :这就很多了，就是%s,%d之类。 
    6、特别地：%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉，不会向目标参数中写入值
    支持集合操作：

    %[a-z] 表示匹配a到z中任意字符，贪婪性(尽可能多的匹配)
    %[aB'] 匹配a、B、'中一员，贪婪性
    %[^a]  匹配非a的任意字符，贪婪性

    %<a-z> 表示匹配a到z中任意字符，贪婪性(尽可能多的匹配)
    %<aB'> 匹配a、B、'中一员，贪婪性
    %<^a>  匹配非a的任意字符，贪婪性

    例子1：读一个字符串

!!!using["sys"];
main(:s,buf)=
  s=new[string,"您好！\r\nhello!\r\n"], buf=new[string,80],
  sscanf(s, "%s", buf),            //读第1个字符串
  printf["\r\n%s\r\n\r\n",buf],
  sscanf(s, "%*s%s",buf),          //读第2个字符串
  printf["\r\n%s\r\n\r\n",buf],
  sscanf(s, "%&%s",1,buf),         //从第2个字符开始读
  printf["\r\n%s\r\n\r\n",buf];
}#
--------------------------------------------------------------------
#sys::fscanf{
[LuSystem32.dll] sys::fscanf(pfile,FormatStr,&x1,&x2,... ...)：从文件格式化输入

    pfile：文件句柄。将从该文件中读取格式化数据。
    FormatStr：格式串字符串，可包括文本和控制码。格式化字符串包括两部分内容：一部分是正常字符，另一部分是格式化规定字符，以“%”开始, 后跟一个或几个规定字符用来确定输出内容格式。
    &x1,&x2,... ...：与格式串中的控制代码相匹配的数据项列表。数据项的个数与格式说明的个数一致，格式说明和数据项在顺序上相互对应。
    返回值：返回成功地处理的数据项的个数（出错时返回-1）。在此例中，若仅读取了x1，返回3；若处理到x2，返回4；以此类推。

    运行错误：1：非法的文件句柄；2：缺少格式串；3：缺少数据项；4：非法的字符串指针；5：内存错误；6：静态字符串缓冲区太小，无法接收字符；7：无法识别格式串；8：数据项多于格式符。

    说明：该函数功能与sscanf类似，但从文件中读取数据，请参考sscanf的说明。

    例子1：读一个字符串

!!!using["sys"];
main(:f,s,buf)=
  buf=new[string,80], f=fopen["aa.txt","rb"],            //Unicode文件“aa.txt”要预先存在
  fread[f,0,2], fscanf(f, "%s", buf),                    //读第1个字符串
  printf["\r\n%s\r\n\r\n",buf],
  rewind[f], fread[f,0,2],    fscanf(f, "%*s%s",buf),    //读第2个字符串
  printf["\r\n%s\r\n\r\n",buf],
  fseek[f,6,SEEK_SET], fscanf(f, "%s",buf),              //从第3个字符开始读
  printf["\r\n%s\r\n\r\n",buf];
}#
--------------------------------------------------------------------
#sys::setlocale{
[LuSystem32.dll] sys::setlocale(category,locale,str)：设置当前地域的各种要素

    category：要被修改的地域要素。只能取LC_ALL（设置所有类别）、LC_COLLATE（设置与函数strcoll()等相关联的地域类别）、LC_CTYPE（设置与宽字符关联的地域类别）、LC_MONETARY（设置影响内存格式的地域类别）、LC_NUMERIC（设置影响小数点的地域类别）和LC_TIME（设置影响时间函数的地域类别）。
    locale：地域名字符串。
    str：字符串地址，用于接收原先的地域字符串。
    返回值：返回str。如果字符串缓冲区太小，仅接收部分地域字符串，且返回-1。

    运行错误：1：参数非法。
}#
--------------------------------------------------------------------
#sys::readtxt{
[LuSystem32.dll] sys::readtxt["aa.txt"]
该函数以文本方式打开文件，并将内容读到一个字符串，该函数返回这个字符串，出错时返回nil。

运行错误：1：参数不可识别。 
}#
--------------------------------------------------------------------
#sys::writetxt{
[LuSystem32.dll] sys::writetxt["aa.txt",str]
该函数以文本方式创建或打开文件（如果打开一个文件，则原文件将被覆盖），并将字符串str的内容写入文件，该函数返回写入字符的个数，出错时返回nil。

运行错误：1：参数不可识别。 
}#
--------------------------------------------------------------------
#字典dict{
[LuSystem32.dll] 字典dict

    字典（dict）是一个可直接存取的双向链表，可以存放若干任意的Lu数据。字典元素由“键－值”对组成，键只能是字符串，但值可以是任何Lu数据类型。

    （1）新建字典

!!!using("sys");
new[dict, "aa":1.2, "abc":"luuu"].o[];    //用函数new生成字典，有2组初始化数据。函数o用于输出字典。

    用函数dict生成字典更为方便：

!!!using("sys");
dict["aa":1.2, "abc":"luuu"].o[];         //用函数dict生成字典，有2组初始化数据。函数o用于输出字典。

    （2）得到字典元素

!!!using("sys");
main(:a)= a=dict["aa":1.2, "abc":"luu"], o[a."aa", a."abc"];

    （3）增加字典元素

!!!using("sys");
main(:a)= a=dict["aa":1.2, "abc":"luu"], a."cc"=a."abc"+"88", o[a];

    说明：当往字典中增加元素时，若已存在该键，则进行更新。

    （4）删除字典

    删除指定键－值对：a.dict_del["aa","abc"];

    清空字典：a.dict_clear();

    删除字典对象，但暂存在缓冲区：del[a];

    立即彻底删除字典对象：delete[a];

    （5）字典反序

!!!using("sys");
main(:a)= a=dict["aa":1.2, "abc":"luu"], o[a], o[a.dict_reverse()];

    结果：

dict{aa : 1.2 , abc : luu}dict{abc : luu , aa : 1.2}

    （6）字典存取效率测试：在字典a中添加若干元素，元素的键通过变换字符串str的值得到，sum用于求所有元素的值的和。

!!!using("sys");
main(:a,i,j,str,t0,sum)= t0=clock(), a=dict[], str="aaaa", sum=0,
  i=0, while{++i<=100, str[1]=i,
    j=1000, while{j<2000, str[2]=j, sum=sum+i+j, a.str=i+j, j++}
  },
  o{"\r\n创建字典耗时", [clock()-t0]/1000., "秒。共", len(a), "个元素。sum=", sum},
  t0=clock(), sum=0,
  i=0, while{++i<=100, str[1]=i,
    j=1000, while{j<2000, str[2]=j, sum=sum+a.str, j++}
  },
  o{"\r\n查询字典耗时", [clock()-t0]/1000., "秒。共", len(a), "个元素。sum=", sum, "\r\n"};

    结果：

创建字典耗时0.89000000000000001秒。共100000个元素。sum=155000000
查询字典耗时9.4e-002秒。共100000个元素。sum=155000000
}#
--------------------------------------------------------------------
#sys::dict{
[LuSystem32.dll] sys::dict["a":2, "b":8, ...]：生成字典对象并初始化。运行错误：1：字典元素不匹配；2：字典元素的键应为字符串；3：内存错误。 

 sys::dict：整数常量，用在函数new[sys::dict,... ...]中，申请字典对象。 
}#
--------------------------------------------------------------------
#dict new{
[LuSystem32.dll] dict new：该函数是重载函数，用于申请字典对象。一般用法：new[sys::dict, "a":2, "b":8, ... ...]
}#
--------------------------------------------------------------------
#dict o{
[LuSystem32.dll] dict o：该函数是重载函数。输出字典的内容。运行错误：1：不可识别对象。
}#
--------------------------------------------------------------------
#dict oset{
[LuSystem32.dll] dict oset：该函数是重载函数。设a是一个字典，则执行形如a."b"=2的赋值语句时将调用该函数。运行错误：1：参数太多或者太少；2：不可识别对象；3：非法的字符串；4：内存错误。
}#
--------------------------------------------------------------------
#dict oget{
[LuSystem32.dll] dict oget：该函数是重载函数。设a是一个字典，则执行形如a."b"的语句时将调用该函数，获得字典元素的值。运行错误：1：参数太多或者太少；2：不可识别对象；3：非法的字符串。
}#
--------------------------------------------------------------------
#dict len{
[LuSystem32.dll] dict len：该函数是重载函数。设a是一个字典，len(a)求a的所有元素数目。
}#
--------------------------------------------------------------------
#sys::dict_oset{
[LuSystem32.dll] sys::dict_oset[p:"a",2]：设置字典p的元素"a"的值为2。运行错误：1：参数太多或者太少；2：不可识别对象；3：非法的字符串；4：内存错误。 
}#
--------------------------------------------------------------------
#sys::dict_oget{
[LuSystem32.dll] sys::dict_oget[p:"a"]：获得字典p的元素"a"的值。运行错误：1：参数太多或者太少；2：不可识别对象；3：非法的字符串。 
}#
--------------------------------------------------------------------
#sys::dict_del{
[LuSystem32.dll] sys::dict_del[p:"a","bc",...]：删除字典p的元素"a","bc",...。运行错误：1：参数太少；2：不可识别对象；3：非法的字符串。  
}#
--------------------------------------------------------------------
#sys::dict_clear{
[LuSystem32.dll] sys::dict_clear[p]：清空字典p的所有元素。运行错误：1：不可识别对象。 
}#
--------------------------------------------------------------------
#sys::dict_reverse{
[LuSystem32.dll] sys::dict_reverse[p] 字典反序。 
}#
--------------------------------------------------------------------
#结构struct{
[LuSystem32.dll] 结构struct

    结构（struct）是一个线性表，可以存放若干任意的Lu数据。结构成员必须以#开头。结构成员的存储顺序与其定义顺序不一定相同。

    （1）新建结构：相当于结构定义

!!!using("sys");
new[struct, #num, #姓名 : "luuu", #年龄].o[];    //用函数new生成结构，有3个成员，其中“姓名”成员进行了初始化。函数o用于输出结构。

    用函数struct生成结构更为方便：

!!!using("sys");
struct[#num, #姓名 : "luuu", #年龄].o[];        //用函数new生成结构，有3个成员，其中“姓名”成员进行了初始化。函数o用于输出结构。

    （2）复制结构：相当于生成结构对象

!!!using("sys");
main(:a)= a=struct[#num, #姓名 : "luuu", #年龄], o[a,"\r\n",copy(a),"\r\n",copy(a, #num:22, #年龄:33),"\r\n"];

    结果：

struct{#num : nil , #姓名 : luuu , #年龄 : nil}
struct{#num : nil , #姓名 : luuu , #年龄 : nil}
struct{#num : 22 , #姓名 : luuu , #年龄 : 33}

    （3）复制结构：要求有相同的结构成员，依次复制结构成员的值

!!!using("sys");
main(:a,b)= a=struct[#num : 55, #姓名 : "luuu", #年龄 : 33], b=struct[#num, #姓名, #年龄], b.=a, o[a,"\r\n",b,"\r\n"];

    结果：

struct{#num : 55 , #姓名 : luuu , #年龄 : 33}
struct{#num : 55 , #姓名 : luuu , #年龄 : 33}

    （4）设置结构：批量对结构成员赋值，注意次序是任意的，并且可设置部分成员或全部成员

!!!using("sys");
main(:a)= a=struct[#num, #姓名, #年龄], o[a,"\r\n"], a.set(#年龄:33, #num:22).o["\r\n"];

    结果：

struct{#num : nil , #姓名 : nil , #年龄 : nil}
struct{#num : 22 , #姓名 : nil , #年龄 : 33}

    （5）结构成员单独赋值，获取结构成员的值

!!!using("sys");
main(:a)= a=struct[#num, #姓名, #年龄], a.#姓名="王强", a.#年龄=33, a.#num=22, o[a,"\r\n",a.#姓名,"\r\n",a.#年龄,"\r\n"];

    结果：

struct{#num : 22 , #姓名 : 王强 , #年龄 : 33}
王强
33

    （6）结构嵌套

!!!using("sys");
main(:a)= a=struct[#num, #班级], a.#num=22, a.#班级=struct[#num, #姓名, #年龄],
  a.#班级.#num=88,
  a.#班级.#姓名="王强",
  a.#班级.#年龄=33,
  o[a,"\r\n",a.#num,"\r\n",a.#班级,"\r\n",a.#班级.#num,"\r\n",a.#班级.#姓名,"\r\n",a.#班级.#年龄,"\r\n"];

    结果：

struct{#num : 22 , #班级 : struct[...]}
22
struct{#num : 88 , #姓名 : 王强 , #年龄 : 33}
88
王强
33

    （7）效率测试

!!!using("sys");
main(:a,i,t0,sum)=
  a=struct{
    #January,
    #February,
    #March,
    #April,
    #May,
    #June,
    #July,
    #August,
    #September,
    #October,
    #November,
    #December
  },
  t0=clock(), sum=0,
  i=0, while{++i<=100000,
    a.#January=1,
    a.#February=2,
    a.#March=3,
    a.#April=4,
    a.#May=5,
    a.#June=6,
    a.#July=7,
    a.#August=8,
    a.#September=9,
    a.#October=10,
    a.#November=11,
    a.#December=12,
    sum=sum+a.#January+a.#February+a.#March+a.#April+a.#May+a.#June+a.#July+a.#August+a.#September+a.#October+a.#November+a.#December
  },
  o{"\r\n耗时", [clock()-t0]/1000., "秒。sum=", sum, "\r\n"};

    结果：

耗时0.75秒。sum=7800000

    使用函数struct_oset和struct_oget存取结构成员会提供运行效率，如下例：

!!!using("sys");
main(:a,i,t0,sum)=
  a=struct{
    #January,
    #February,
    #March,
    #April,
    #May,
    #June,
    #July,
    #August,
    #September,
    #October,
    #November,
    #December
  },
  t0=clock(), sum=0,
  i=0, while{++i<=100000,
    a.struct_oset[#January : 1],
    a.struct_oset[#February : 2],
    a.struct_oset[#March : 3],
    a.struct_oset[#April : 4],
    a.struct_oset[#May : 5],
    a.struct_oset[#June : 6],
    a.struct_oset[#July : 7],
    a.struct_oset[#August : 8],
    a.struct_oset[#September : 9],
    a.struct_oset[#October : 10],
    a.struct_oset[#November : 11],
    a.struct_oset[#December : 12],
    sum=sum+a.struct_oget[#January]+a.struct_oget[#February]+a.struct_oget[#March]+a.struct_oget[#April]+a.struct_oget[#May]+a.struct_oget[#June]+a.struct_oget[#July]+a.struct_oget[#August]+a.struct_oget[#September]+a.struct_oget[#October]+a.struct_oget[#November]+a.struct_oget[#December]
  },
  o{"\r\n耗时", [clock()-t0]/1000., "秒。sum=", sum, "\r\n"};

    结果：

耗时0.56200000000000006秒。sum=7800000

    Matlab2009a代码：

a=struct('January',1,'Febrary',2,'March',3,'April',4,'May',5,'June',6,'July',7,'August',8,'September',9,'October',10,'November',11,'December',12);
tic; 
sum=0;
for i=1:100000
    a.January=1;
    a.February=2;
    a.March=3;
    a.April=4;
    a.May=5;
    a.June=6;
    a.July=7;
    a.August=8;
    a.September=9;
    a.October=10;
    a.November=11;
    a.December=12;
    sum=sum+a.January+a.February+a.March+a.April+a.May+a.June+a.July+a.August+a.September+a.October+a.November+a.December;
end
toc,
sum

    结果：

Elapsed time is 3.275743 seconds.

sum =

7800000 
}#
--------------------------------------------------------------------
#sys::struct{
[LuSystem32.dll] sys::struct[#a, #b:8, ...]：生成结构对象并初始化 ，结构成员必须以#开头。运行错误：1：非法的结构成员；2：结构成员重名。 

 sys::struct：整数常量，用在函数new[sys::struct,... ...]中，申请结构对象。 
}#
--------------------------------------------------------------------
#struct new{
[LuSystem32.dll] struct new：该函数是重载函数，用于申请结构对象。一般用法：new[sys::struct, #a, #b:8, ...]
}#
--------------------------------------------------------------------
#struct o{
[LuSystem32.dll] struct o：该函数是重载函数。输出结构的内容。运行错误：1：不可识别对象。
}#
--------------------------------------------------------------------
#struct oset{
[LuSystem32.dll] struct oset：该函数是重载函数。设a是一个结构，则执行形如a.#b=2的赋值语句时将调用该函数。运行错误：1：参数太少；2：不可识别对象或成员；3：没有找到成员。
}#
--------------------------------------------------------------------
#struct oget{
[LuSystem32.dll] struct oget：该函数是重载函数。设a是一个结构，则执行形如a.#b的语句时将调用该函数，获得结构成员的值。运行错误：1：参数太少；2：不可识别对象或成员；3：没有找到成员。
}#
--------------------------------------------------------------------
#struct len{
[LuSystem32.dll] struct len：该函数是重载函数。设a是一个结构，len(a)求a的所有成员数目。
}#
--------------------------------------------------------------------
#struct copy{
[LuSystem32.dll] struct copy：该函数是重载函数。设a和b是结构，copy(a)求a的副本，copy(a,b)复制b的内容到a（执行a.=b时将自动调用该函数），copy(a: #ab,2, #b:8, ...)求a的副本并进行初始化，初始化参数要成对。运行错误：1：不可识别对象 ；2：对象结构不相同；3：非法的成员标识；4：没有找到成员；5：参数不匹配。
}#
--------------------------------------------------------------------
#struct set{
[LuSystem32.dll] struct set：该函数是重载函数，设置结构的成员。设a是一个结构，a.set(#ab,2, #b:8, ...)设置a的成员，注意参数要成对。运行错误：1：参数太少；2：不可识别对象 ；3：非法的成员标识；4：没有找到成员；5：参数不匹配。
}#
--------------------------------------------------------------------
#sys::struct_oset{
[LuSystem32.dll] sys::struct_oset[p,#b : 2]：设置结构p的成员#b的值为2。运行错误：1：参数太少；2：不可识别对象或成员；3：没有找到成员。 
}#
--------------------------------------------------------------------
#sys::struct_oget{
[LuSystem32.dll] sys::struct_oget[p,#b] 获得结构p的成员#b的值。运行错误：1：参数太少；2：不可识别对象或成员；3：没有找到成员。 
}#
--------------------------------------------------------------------
#类class{
[LuSystem32.dll] 类class

    类（class）是一个具有数据成员和方法成员的自定义数据结构。类可以继承和派生，类的层次结构是一棵树。

    类对象（obj）是类的实例。

    （1）类定义

!!!using("sys");
new[class, #人, public : #姓名, private : #性别, #年龄].o[];    //用函数new定义类，有1个公有成员，2个私有成员。函数o用于输出类定义。

    结果：

class{#人 : 
private:
  #性别, #年龄, 
public:
  #姓名, 
method:
  #__init__ : 0, #__del__ : 0
}

    用函数class定义类更为方便：

!!!using("sys");
class[#人, public : #姓名, private : #性别, #年龄].o[];    //用函数new定义类，有1个公有成员，2个私有成员。函数o用于输出类定义。

    输出结果与上面相同。

    （2）单一继承

!!!using("sys");
class[#人, public : #姓名, private : #性别, #年龄],
class[#学生, #人, public : #学校, #班级].o[];

    结果：

class{#学生 : #人,
private:

public:
  #学校, #班级, 
method:
  #__init__ : 0, #__del__ : 0
}

    （3）类对象

!!!using("sys");
main(:a,b)=
  class[#人, public : #姓名, #性别, #年龄],
  a=class[#学生, #人, public : #学校, #班级],
  b=obj[a],
  b.#学校="实验中学", b.#班级="二年级", b.#姓名="王强", b.#性别="男", b.#年龄=12,
  o[b, b.#学校,"  ", b.#班级,"  ", b.#姓名,"  ", b.#性别, "  ", b.#年龄, "\r\n"];

    结果：

class obj{#学生 : #人,
private:
public:
  #学校 : 实验中学,
  #班级 : 二年级
}
实验中学 二年级 王强 男 12

    说明：如果基类“#人”中#性别和#年龄被定义为私有成员，将无法直接进行存取。

    （4）多重继承及构造函数和析构函数

    例子1：

!!!using("sys");
initA(p)= o["\r\nA的构造函数!"];
initB(p)= o["\r\nB的构造函数!"];
initC(p)= o["\r\nC的构造函数!"];
initD(p)= o["\r\nD的构造函数!"];
delA(p) = o["\r\nA的析构函数!"];
delB(p) = o["\r\nB的析构函数!"];
delC(p) = o["\r\nC的析构函数!"];
delD(p) = o["\r\nD的析构函数!"];
main()=
  class[#A,         method : #__init__ : @initA, #__del__ : @delA],
  class[#B, #A,     method : #__init__ : @initB, #__del__ : @delB],
  class[#C, #A,     method : #__init__ : @initC, #__del__ : @delC],
  class[#D, #B, #C, method : #__init__ : @initD, #__del__ : @delD].obj[].delete[];

    结果：

A的构造函数!
B的构造函数!
A的构造函数!
C的构造函数!
D的构造函数!
D的析构函数!
B的析构函数!
A的析构函数!
C的析构函数!
A的析构函数!

    例子2：

!!!using("sys");
initA(p)= p.#a=0;
initB(p)= p.#a=1;
initC(p)= p.#a=2;
initD(p)= p.#a=3;
main(:c)=
  class[#A,           public: #a, method : #__init__ : @initA],
  class[#B, #A,       public: #a, method : #__init__ : @initB],
  class[#C, #A,       public: #a, method : #__init__ : @initC],
  c=class[#D, #B, #C, public: #a, method : #__init__ : @initD].obj[],
  o[c.#a,"  ",c.#B.#a,"  ",c.#C.#a,"  ",c.#B.#A.#a,"  ",c.#C.#A.#a,"\r\n"],
  c.#B.#A.#a=5, c.#C.#A.#a=6, o[c.#B.#A.#a,"  ",c.#C.#A.#a,"\r\n"];

    结果：

3 1 2 0 0
5 6

    例子3：

!!!using("sys");
initA(p)= p.#a=0;
initB(p)= p.#b=1;
initC(p)= p.#c=2;
initD(p)= p.#d=3;
main(:c)=
  class[#A,           public: #a, method : #__init__ : @initA],
  class[#B, #A,       public: #b, method : #__init__ : @initB],
  class[#C, #A,       public: #c, method : #__init__ : @initC],
  c=class[#D, #B, #C, public: #d, method : #__init__ : @initD].obj[],
  o[c.#a,"  ",c.#b,"  ",c.#c,"  ",c.#d,"\r\n"],
  c.#a=5, c.#b=6, c.#c=7, c.#d=8,
  o[c.#a,"  ",c.#b,"  ",c.#c,"  ",c.#d,"\r\n"],
  c.#B.#A.#a=11, c.#C.#A.#a=12, o[c.#a," ",c.#B.#A.#a,"  ",c.#C.#A.#a,"\r\n"];

    结果：

0 1 2 3
5 6 7 8
11 11 12

    （5）成员函数：第一个参数为对象指针

    例子1：

!!!using("sys");
setA(p,x)= p.#a=x;
setB(p,x)= p.#a=x;
setC(p,x)= p.#a=x;
getA(p)= p.#a;
getB(p)= p.#a;
getC(p)= p.#a;
main(:c)=
  class[#A,           private: #a, method : #mGetA : @getA, #mSetA : @setA],
  class[#B,           private: #a, method : #mGetB : @getB, #mSetB : @setB],
  c=class[#C, #A, #B, private: #a, method : #mGetC : @getC, #mSetC : @setC].obj[],
  c.#mSetA=5, c.#mSetB=6, c.#mSetC=7,
  o[c.#mGetA,"  ",c.#mGetB,"  ",c.#mGetC,"\r\n"];

    结果：

5 6 7

    说明：类的方法成员和数据成员用法几乎相同，但方法可以接受多个参数，如下例。

    例子2：

!!!using("sys");
out(p,x,y,z)= o[x,y,z,"\r\n"];
main(:c)=
  c=class[#A, method : #mOut : @out].obj[],
  c.#mOut := [5,6,7],
  c.#mOut."***".(888)."***";

    结果：

567
***888***

    （6）类对象复制

!!!using("sys");
setA(p,x,y)= p.#a=x, p.#b=y;
sumA(p)= p.#a+p.#b;
copyAB(s,t)= s.#a=t.#a, s.#b=t.#b;
class[#A,     private : #a, public : #b, method : #__copy__ : @copyAB, #setA : @setA, #sumA : @sumA],
class[#B, #A, private : #a, public : #b, method : #__copy__ : @copyAB];
main(:a,b)=
  a=obj[class_handle(#B)], b=obj[class_handle(#B)],
  a.#a=1, a.#b=2, a.#setA:=[8,9],
  b.=a,
  b.#a+b.#b+b.#sumA;

    结果：

20

    （7）多态性

!!!using("sys");
getA()= 1;
getB()= 2;
getC()= 3;
class[#A,     method : #mGet : @getA],
class[#B, #A, method : #mGet : @getB],
class[#C, #B, method : #mGet : @getC];
main(:a,b,c)=
  c=obj[class_handle(#C)],
  o[c.#mGet,"  ",c.#B.#mGet,"  ",c.#B.#A.#mGet,"\r\n"],
  b=c.#B, a=b.#A,  //获得基类对象
  o[c.#mGet,"  ",b.#mGet,"  ",a.#mGet,"\r\n"];

    结果：

3 2 1
3 2 1

    （8）效率测试

!!!using("sys");
main(:a,i,t0,sum)=
  a=class{#A,
    public:
    #January,
    #February,
    #March,
    #April,
    #May,
    #June,
    #July,
    #August,
    #September,
    #October,
    #November,
    #December
  }.obj[],
  t0=clock(), sum=0,
  i=0, while{++i<=100000,
    a.#January=1,
    a.#February=2,
    a.#March=3,
    a.#April=4,
    a.#May=5,
    a.#June=6,
    a.#July=7,
    a.#August=8,
    a.#September=9,
    a.#October=10,
    a.#November=11,
    a.#December=12,
    sum=sum+a.#January+a.#February+a.#March+a.#April+a.#May+a.#June+a.#July+a.#August+a.#September+a.#October+a.#November+a.#December
  },
  o{"\r\n耗时", [clock()-t0]/1000., "秒。sum=", sum, "\r\n"};

    结果：

耗时0.85999999999999999秒。sum=7800000

    比较：前面使用struct的耗时0.75秒，故class比struct稍慢。

    使用函数obj_oset和obj_oget存取类成员会提供运行效率，如下例：

!!!using("sys");
main(:a,i,t0,sum)=
  a=class{#A,
    public:
    #January,
    #February,
    #March,
    #April,
    #May,
    #June,
    #July,
    #August,
    #September,
    #October,
    #November,
    #December
  }.obj[],
  t0=clock(), sum=0,
  i=0, while{++i<=100000,
    a.obj_oset[#January : 1],
    a.obj_oset[#February : 2],
    a.obj_oset[#March : 3],
    a.obj_oset[#April : 4],
    a.obj_oset[#May : 5],
    a.obj_oset[#June : 6],
    a.obj_oset[#July : 7],
    a.obj_oset[#August : 8],
    a.obj_oset[#September : 9],
    a.obj_oset[#October : 10],
    a.obj_oset[#November : 11],
    a.obj_oset[#December : 12],
    sum=sum+a.obj_oget[#January]+a.obj_oget[#February]+a.obj_oget[#March]+a.obj_oget[#April]+a.obj_oget[#May]+a.obj_oget[#June]+a.obj_oget[#July]+a.obj_oget[#August]+a.obj_oget[#September]+a.obj_oget[#October]+a.obj_oget[#November]+a.obj_oget[#December]
  },
  o{"\r\n耗时", [clock()-t0]/1000., "秒。sum=", sum, "\r\n"};

    结果：

耗时0.625秒。sum=7800000 
}#
--------------------------------------------------------------------
#sys::class{
[LuSystem32.dll] sys::class{... ...}：创建类定义

 sys::class：整数常量，用在函数new[sys::class,... ...]中，申请类定义。 

    类定义格式如下：

class{#cMyClass: #cBase1, #cBase2, ...  //定义类cMyClass，继承自cBase1和cBase2, ...
private:                  //私有数据成员
  #pvMem1, #pvMem2, ...
public:                   //公有数据成员
  #plMem1, #plMem2, ...
method:                   //方法（函数成员）
  #__init__ : @init, #__del__ : @delme, #mFun1 ：@Fun1, #mFun2 ：@Fun2, ...
};

    类定义中，类名称、基类名称、成员及方法都是以#开头的标识符，不可重复。类名称在最前面，其次是基类名称；private、public及method的次序是任意的，且可多次定义；方法标识符后必须提供函数句柄。类成员的存储顺序与其定义顺序不一定相同。

    #__init__和#__del__只可被定义为方法，其中#__init__用于定义构造函数，#__del__用于定义析构函数。若这两个方法被缺省，其函数句柄被自动指定为0。构造函数和析构函数只有一个参数，即对象本身。

    若方法有不止一个参数，则方法被调用时，第一个参数总是传入对象本身，相当于C++的this指针。

    运行错误：1：非法的类名；2：__init__和__del__只能是方法成员；3：类名或基类名有重名；4：不可识别关键字；5：缺少函数句柄；6：不可识别关键字或成员；7：基类没有定义或循环定义。

    约定：类名称以字母c开头；私有数据成员以pv开头；公有数据成员以pl开头；方法成员以m开头。
}#
--------------------------------------------------------------------
#sys::obj{
[LuSystem32.dll] sys::obj(pClass)：创建类对象

 sys::obj：整数常量，用在函数new[sys::obj,pclass,... ...]中，申请类对象，其中pclass是类定义。 

    pClass是类定义的句柄。

    创建类对象时，将自动调用每一个基类的构造函数#__init__初始化基类对象。对象被销毁时，将自动调用每一个基类的析构函数#__del__销毁基类对象。

    语句 a.=b 将对象b的内容复制到对象a，要求a和b具有相同的类定义，若类定义中定义了方法#__copy__（有且只有2个参数），将自动调用该方法进行对象复制，否则仅依次复制类成员的值。

    运行错误：1：不可识别类定义。 
}#
--------------------------------------------------------------------
#sys::obj_method{
[LuSystem32.dll] sys::obj_method(#FunName : pObj,... ...)：调用类对象的方法。

    #FunName：以#开头的标识符指出函数名。
    pObj：类对象。

    运行错误：1：参数太少；2：不可识别的函数标识或对象；3：不可识别类对象；4：参数不匹配；5：找不到指定的方法。 
}#
--------------------------------------------------------------------
#sys::class_handle{
[LuSystem32.dll] sys::class_handle(#AA)：根据类名称得到类句柄，该句柄可用在函数obj中创建类对象。 
}#
--------------------------------------------------------------------
#sys::obj_oset{
[LuSystem32.dll] sys::obj_oset[p,#b : 2]：设置对象p的成员#b的值为2。运行错误：1：参数太少；2：不可识别成员标识；3：不可识别对象标识；4：没有找到类成员；5：不可识别的结构对象；6：没有找到结构成员；7：不可识别数据类型；8：成员函数参数不匹配；9：不可更改基类对象。  
}#
--------------------------------------------------------------------
#sys::obj_oget{
[LuSystem32.dll] sys::obj_oget[p,#b]：获得对象p的成员#b的值。运行错误：1：参数太少；2：不可识别成员标识；3： 不可识别对象标识；4：没有找到类成员；5：不可识别的结构对象；6：没有找到结构成员；7：不可识别数据类型；8：成员函数参数不匹配。 
}#
--------------------------------------------------------------------
#class new{
[LuSystem32.dll] class new：该函数是重载函数，用于申请类定义。
}#
--------------------------------------------------------------------
#obj new{
[LuSystem32.dll] obj new：该函数是重载函数，用于申请类对象。
}#
--------------------------------------------------------------------
#class o{
[LuSystem32.dll] class o：该函数是重载函数。输出类定义的内容。运行错误：1：不可识别对象；2：找不到类定义。
}#
--------------------------------------------------------------------
#obj o{
[LuSystem32.dll] obj o：该函数是重载函数。输出类对象的内容。运行错误：1：不可识别对象；2：找不到类定义。
}#
--------------------------------------------------------------------
#obj oset{
[LuSystem32.dll] obj oset：该函数是重载函数。设a是一个类对象，则执行形如a.#b=2的赋值语句时将调用该函数。运行错误：1：参数太少；2：不可识别成员标识；3：不可识别对象标识；4：没有找到类成员；5：不可识别的结构对象；6：没有找到结构成员；7：不可识别数据类型；8：成员函数参数不匹配；9：不可更改基类对象。
}#
--------------------------------------------------------------------
#obj oget{
[LuSystem32.dll] obj oget：该函数是重载函数。设a是一个类对象，则执行形如a.#b的语句时将调用该函数，获得类成员的值。运行错误：1：参数太少；2：不可识别成员标识；3： 不可识别对象标识；4：没有找到类成员；5：不可识别的结构对象；6：没有找到结构成员；7：不可识别数据类型；8：成员函数参数不匹配。
}#
--------------------------------------------------------------------
#obj copy{
[LuSystem32.dll] obj copy：该函数是重载函数。设a和b是对象，copy(a,b)复制b的内容到a，执行a.=b时将自动调用该函数。运行错误：1： 参数太多或者太少；2：不可识别对象；3：对象结构不相同；4：对象的成员函数#__copy__参数不是2个；5：没有找到成员函数#__copy__的句柄。
}#
--------------------------------------------------------------------
#sys::null{
[LuSystem32.dll] sys::null：空指针常量。 
}#
--------------------------------------------------------------------
#sys::isnil{
[LuSystem32.dll] sys::isnil(a)：判断一个数据是否是nil，若是返回true，否则返回false。 
}#
--------------------------------------------------------------------
#sys::rearray{
[LuSystem32.dll] sys::rearray(a)：数组维数反序，该函数用于在Lu数组（C数组格式）和Fortran数组之间进行转换。a是一个实数或整数数组。例如三维数组a[2,3,5]，调用该函数后，将成为a[5,3,2]。运行错误：1：非法的数组指针。  
}#
--------------------------------------------------------------------
#sys::SetCurrentDirectory{
[LuSystem32.dll] sys::SetCurrentDirectory(a)：设置当前目录，a是一个字符串。设置成功仍返回a，否则返回nil。   
}#
--------------------------------------------------------------------
#sys::GetCurrentDirectory{
[LuSystem32.dll] sys::GetCurrentDirectory(a)：获得当前目录，a是一个字符串，用于存放当前目录。获取成功仍返回a，否则返回nil。 
}#
--------------------------------------------------------------------
#sys::lufun{
[LuSystem32.dll] sys::lufun(hFor:x1,x2,...,xn : xx)：以Lu表的元素为自变量进行函数调用。

    hFor为函数句柄；x1,x2,...,xn : xx为等长的Lu表；xx用于存放结果，可缺省。若缺省xx，返回一个Lu表存放结果，否则该函数返回xx。该函数以x1,x2,...,xn的第i个元素为自变量，用函数hFor进行计算，结果存入xx的第i个单元。

    运行错误：1：至少需要2个参数；2：指定的表达式不存在；3：Lu表个数与自变量个数不相等；4：不是Lu表；5：Lu表长度不匹配；6：内存错误。

    例子：

!!!using("sys");
f(x,y)=x+y;
lufun[@f,luu(1.,"aa",5),luu(2.,"bb",5)].o[];
}#
--------------------------------------------------------------------
#sys::ShellExecute{
[LuSystem32.dll] sys::ShellExecute(hwnd,"lpOperation","lpFile","lpParameters","lpDirectory",nShowCmd)：执行外部程序

    hwnd：窗口句柄（该句柄是一个指针或者nil，一般为nil）；
    lpOperation：指定本命令所要执行的动作；
    lpFile：指定本命令所要操作的文件；
    lpParameters：指定操作文件时所使用的参数；
    lpDirectory：指定本命令所使用的缺省路径；
    nShowCmd：显示方式。

    运行成功返回一个整数标识的代码，否则返回nil。

    例子：

    打开一个应用程序：    sys::ShellExecute(nil,"open","calc.exe","","",0);
    打开一个网页：       sys::ShellExecute(nil,"open","http://www.forcal.net","","",0);
    用系统打印机打印文档：sys::ShellExecute(nil,"print","openlu.ini","","",0);
    查找文件：           sys::ShellExecute(nil,"find","","","",0);
}#
--------------------------------------------------------------------
