查询元素

简介: 查询元素

C API 使用索引index )来引用栈中的元素。第一个被压入栈的元素索引为 1 ,第二个被压入的元素索引为 2 ,以此类推,我们还可以以栈顶为参照,使用负数索引来访问栈中的元素。此时, -1 表示栈顶元素(即最后被压入栈的元素), -2 表示在它之前被压入栈的元素,以此类推。例如,调用 lua_tostring(L, -1) 会将栈顶的值作为字符串返回。有些情况下从栈底对栈进行索引更加自然(即使用正数索引),而有些情况下则使用负数索引更好。


要检查栈中的一个元素是否为特定的类型, C API 提供了一系列名为 lua_is* 的函数,其中 * 可以是任意一种 Lua 数据类型。这些函数包括 lua_isnillua_isnumberlua_isstringlua_istable 等。所有这些函数都有相同的原型:

int lua_is* (lua_State *L, int index);


实际上,函数 lua_isnumber 不会检查某个值是否为特定类型,而是检查该值是否能被转换为此特定类型。函数 lua_istring 与之类似,特别之处在于,它接受数字。


还有一个函数 lua_type ,用于返回栈中元素的类型,每一种类型都由一个对应的常量表示,包括 LUA_TNILLUA_TBOOLEANLUA_TNUMBERLUA_tSTRING 等。该函数一般与 switch 语句连用。当需要检查字符串和数值是否存在潜在的强制类型转换时,该函数也同样有用。


函数 lua_to* 用于从栈中获取一个值:

int lua_toboolean (lua_State *L, int index);
const char * lua_tostring (lua_State *L, int index, size_t *len);
lua_State *lua_tothread (lua_State *L, int index);
lua_Number lua_tonumber (lua_State *L, int index);
lua_Integer lua_tointeger (lua_State *L, int index);


即使指定的元素的类型不正确,调用这些函数也不会有问题。函数 lua_toboolean 适用于所有类型,它可以按照如下的规则将任意 Lua 值转换为 C 的布尔值: nilfalse 转换为 0 ,所有其他的 Lua 值转换为 1 。对于类型不正确的值,函数 lua_tolstringlua_tothread 返回 NULL 。不过,数值相关的函数都无法提示数值的类型错误,因此只能简单地返回 0 。以前我们需要调用函数 lua_isnumber 来检查类型,但 Lua5.2 引入了如下的新函数:

lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum);
lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);


出口参数 isnum 返回了一个布尔值,来表示 Lua 值是否被强制转换为期望的类型。

函数 lua_tolstring 返回一个指向该字符串内部副本指针,并将字符串的长度存入到参数 len 指定的位置。我们无法修改这个内部副本( const 表明了这一点)。

Lua 语言保证,只要对应的字符串还在栈中,那么这个指针就是有效的。当 Lua 调用的一个 C 函数返回时, Lua 就会清空栈。因此,作为规则,永远不要把指向 Lua 字符串的指针存放到获取该指针的函数之外。


函数 lua_tostring 返回的所有字符串在其末尾都会有一个额外的 \0 ,不过这些字符串中也可能会有 \0 ,因此可以通过第三个参数 len 获取字符串的真实长度。特别的,假设栈顶的值是一个字符串,那么如下推断永远成立:

size_t len;
const char *s = lua_tolstring(L, -1, &len); /* 任意lua字符串 */
assert(s[len] == '\0');
assert(strlen(s) <= len);点击复制复制失败已复制


如果不需要长度信息,可以在调用函数 lua_tolstring 时将第三个参数设置为 NULL 。不过,使用宏 lua_tostring 会更好,因为这个宏就是用 NULL 作为第三个参数来调用函数 lua_tolstring 的。


为了演示这些函数的用法,如下示例提供了一个有用的辅助函数,它输出整个栈的内容:

static void stackDump(lua_State *L) {
  int i;
  int top = lua_gettop(L);  // 栈的深度
  for (i = 1; i <= top; i++) {  // 循环
    int t = lua_type(L, i);
    switch (t) {
      case LUA_TSTRING: { // 字符串类型
        printf("'%s'", lua_tostring(L, i));
        break;
      }
      case LUA_TBOOLEAN: {  // 布尔类型
        printf(lua_toboolean(L, i) ? "true" : "false");
        break;
      }
      case LUA_TNUMBER: {   // 数值类型
        printf("%g", lua_tonumber(L, i));
        break;
      }
      default: {  // 其他类型
        printf("%s", lua_typename(L, t));
        break;
      }
    }
    printf("  ");   // 输出分隔符
  }
  printf("\n");   // 换行符
}点击复制复制失败已复制


这个函数从栈底向栈顶遍历,并根据每个元素的类型打印其值。它打印字符串时会用单引号将其括起来,对数值类型的值则使用格式 "%g" 输出,对于其他 C 语言中不存在等价类型的值(表、函数等)则值打印出他们的类型(函数 lua_typename )可以将类型编码转换为类型名称。


Lua5.3 中,由于整型总是可以被强制转换为浮点型,因此仍然可以用函数 lua_tonumber"%g" 的格式打印所有的数值。但是,我们倾向于将整数打印为整型,以避免损失精度。此时,我们可以用新函数 lua_isinteger 来区分整型和浮点型:

case LUA_TNUMBER: {   // 数值
  if lua_isinteger(L, i)  // 整型
    printf("%lld", lua_tointeger(L, i));
  else  // 浮点型
    printf("%g", lua_tonumber(L, i));
  break;
}
目录
相关文章
|
6月前
|
JavaScript 前端开发
页面插入元素
页面插入元素
54 8
|
6月前
|
移动开发 HTML5
分组元素
分组元素。
39 3
|
6月前
|
算法 前端开发 索引
过滤数组中的元素
过滤数组中的元素
49 0
|
2月前
不排序列表
不排序列表。
30 5
|
3月前
列表元素
【8月更文挑战第4天】列表元素。
39 8
|
4月前
|
存储 语音技术 索引
语音识别,列表的定义语法,列表[],列表的下标索引,从列表中取出来特定的数据,name[0]就是索引,反向索引,头部是-1,my[1][1],嵌套列表使用, 列表常用操作, 函数一样,需引入
语音识别,列表的定义语法,列表[],列表的下标索引,从列表中取出来特定的数据,name[0]就是索引,反向索引,头部是-1,my[1][1],嵌套列表使用, 列表常用操作, 函数一样,需引入
|
5月前
|
SQL 关系型数据库 MySQL
数据的插入和查询
数据的插入和查询
|
6月前
判断两个不重复的list集合是否相等 只比较元素值 不比较顺序
判断两个不重复的list集合是否相等 只比较元素值 不比较顺序
62 0
es6查询数组某元素出现次数
es6查询数组某元素出现次数
118 1
|
索引
查找某个元素在数组中对应的索引
查找某个元素在数组中对应的索引
86 0
查找某个元素在数组中对应的索引