查询元素

简介: 查询元素

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;
}
目录
相关文章
|
程序员
check sign Fail!或sign check fail: check Sign and Data Fail!-自查方案
一、报这个错大多都是支付宝公钥配置错误,不同环境的公钥是不同的,大家先确认自己的支付宝公钥获取是否正确:  1. 沙箱公钥【查看】 密钥生成可参照【如何生成RSA,RSA2密钥】  2. 开放平台密钥【查看】,已创建应用的,直接打开对应的应用进行查看, 创建应用可参照:【如何创建应用】 打开应用查...
2140 12
|
1月前
|
JSON 自然语言处理 供应链
API接口赋能1688采购全流程:从商品获取到下单支付一键贯通
1688采购API助力企业实现全流程自动化,涵盖商品数据获取、智能比价、一键下单、支付及物流跟踪等环节,显著提升采购效率,降低成本与风险,推动B2B采购模式智能化升级。
|
7月前
|
人工智能 弹性计算 运维
操作系统控制台体验测评
操作系统管理平台是一个智能服务器管家,提供便捷易用的可视化操作界面,帮助用户高效管理操作系统。它具备运维管理、智能助手、扩展组件管理等功能,提升操作系统使用效率和体验。首次使用需开通服务并准备兼容的操作系统ECS实例(如Alibaba Cloud Linux、CentOS等),通过安装管控组件实现纳管。平台提供系统健康监测、诊断、观测及订阅服务等功能,确保集群和主机的稳定运行,并为用户提供专业指导和优化建议。智能助手功能则实现了集群多主机的自动化管理及实时技术问答支持。
318 64
|
6月前
|
存储 人工智能 安全
一文总览阿里云存储产品年度升级!
阿里云在“回顾·向新:AI浪潮下的数据存储进化”活动上,总结了过去一年在AI领域的存储研究成果,提出“AI领域”与“高可用底层架构”双轨策略。会上推出的CPFS智算版,针对模型训练场景全链路性能升级,提供20TB级吞吐和3亿IOPS性能,助力大模型高效训练。同时,OSS端到端链路升级支持构建超2万数据湖,性能显著提升。此外,阿里云强化存储安全与高可用性,推出多种灾备方案,满足企业多样化需求。通过赋能月之暗面、小鹏汽车、小红书等案例,阿里云持续领跑AI时代,助力企业智能化转型。
350 27
|
7月前
|
自然语言处理 开发者
DeepSeek全尺寸模型上线阿里云百炼!
DeepSeek全尺寸模型上线阿里云百炼!
226 4
|
网络架构
FTP的主动模式和被动模式,你应该用那种?
FTP文件传输分为两种模式,主动(PORT)模式和被动(Passive)模式,用户应该用哪种? 简单粗暴,直接上答案 1)如果不是必须需要,不要使用FTP服务,主动/被动模式,命令/数据端口,初学者很容易一下子就被搞蒙。
11638 2
|
物联网 开发者
Stm32 抢占和子优先级配置 | 学习笔记
快速学习 Stm32 抢占和子优先级配置
Stm32 抢占和子优先级配置 | 学习笔记
|
PHP
php curl指定ip,php curl请求忽略本地host文件,php curl请求跳过本地host文件
php curl指定ip,php curl请求忽略本地host文件,php curl请求跳过本地host文件
371 0
|
存储 移动开发 JavaScript
手把手教你用 Vue 搭建带预览的「上传图片」管理后台
手把手教你开发带预览的 Vue 图片上传组件,即图片上传管理后台。只要你跟本教程一步一步走,最终能很好的理解整个前后端传图的工程逻辑。前端我们使用 Vue + Axios + Multipart 来搭建前端上传图片应用,后端我们使用 Node.js + Express + Multer 来搭建后端上传图片的后端处理。
1355 0
|
网络架构
IP地址分类与CIDR
IP地址分类与CIDR
550 0