Lua C 字符串和数组操作

来源:互联网 发布:cf手游龙拳苍龙数据 编辑:程序博客网 时间:2024/05/16 09:26

转自lua程序设计第二版

数组操作

在Lua中,“数组”只是table的一个别名,像lua_settable和lua_gettable这种操作table的函数,也可以用于操作数组。
然而API为为数组操作提供了专门的函数。
* 出于性能考虑,通常会在算法中用循环来访问数组
* 为了方便,像字符串key,整数key是很常用的

//index表示在栈中的位置,key表示元素在 table中的位置void lua_rawgeti(Lua_State *L,int index,int key);void lua_rawseti(Lua_State *L,int index,int key);//假设t为整数,//lua_rawgeti(L,t,key)等价于lua_pushnumber(L,key);lua_rawget(L,t);//lua_rawseti(L,t,key)等价于lua_pushnumber(L,key);lua_insert(L,-2);lua_rawset(L,t);

示例

int l_map(lua_State *L){    int i,n;    //第一个参数必须是table    luaL_checktype(L,1,LUA_TABLE);    //第二个参数必须是一个函数    lua_checktype(L,2,LUA_FUNCTION);    //获取table的大小    n = lua_objlen(L,1);    for(i = 1;i<=n;i++){        //压入f        lua_pushvalue(L,2);        //压入t[i]        lua_rawgeti(L,1,i);        //调用f(t[i])        lua_call(L,1,1);        //t[i] = 结果        lua_rawseti(L,1,i);    }    return 0;}

字符串操作

当一个C函数从Lua收到一个字符串参数时,必须遵守两条规则:
* 不要再访问字符串时从栈中弹出它
* 不要修改字符串

//把一个字符串s的子串传递给Lua//区间[i,j]lua_pushlstring(L,s+i,j-i+1)

切割字符串实例

static int  l_split(lua_State *L){    const char *s = luaL_checkstring(L,1);    const char *sep = luaL_chcekcstring(L,2);    const char *e ;    int i = 1;    //结果    lua_newtable(L);    //遍历所有分隔符    while((e = strchr(s,*sep)) != NULL){        //压入字符串        lua_pushlstring(L,s,e-s);        lua_rawseti(L,-2,i++);        //跳过分隔符        s=e+1;    }    //压入最后一个字符串    lua_pushstring(L,s);    lua_rawseti(L,-2,i);    //返回table    return 1;}

字符串链接

lua_concat

//链接并弹出栈顶的n个值void lua_concat (lua_State *L, int n);

lua_pushfstring(lua_State *L,const char *fmt,…)

类似于C函数sprintf.
但与sprintf不同的是,无需提供这个新字符串的缓冲。Lua会动态的创建一个足够大的缓存来存放新字符串。
* %% 字符%
* %s 字符串
* %d 整数
* %f 表示Lua中的数字,即双精度浮点数
* %c 接受一个整数,并将其格式化为一个字符

缓存机制

这套机制包含两个层面的缓冲
1. 类似于I/O操作中的缓冲,就是在一个本地缓冲中收集较小的字符串,并在本地缓冲填满后将结果传递给Lua(通过lua_pushlstring)
2. 使用lua_concat或其他栈算法来链接多次缓冲填满后的结果

//string.upper缓冲示例static int str_upper(lua_State *L){    size_t l;    size_t i;    //声明一个luaL_Buffer变量    luaL_Buffer b;    const char* s = luaL_checklstr(L,1,&l);    //用luaL_buffinit来初始化,在初始化后,这个变量中会保留一份状态L的副本,由此再调用其他操作缓冲的函数时,就无需传递状态参数了。    luaL_buffinit(L,&b);    for(i = 0;i<l;i++){        //将一个字符放入缓冲中         luaL_addchar(&b,toupper(unsigned char)(s[i])));        //将具有显式长度的字符串 luaL_addlstring         //将对于“0结尾”的字符串 luaL_addstring    }    //更新缓冲,并将最终的字符留在栈顶    lua_pushresult(&b);    return 1;}

当向缓冲中添加东西时,缓冲会将一些中间结果放到栈中。因此,不应假设栈顶还是和使用缓冲之前一样。

0 0