主頁(yè) > 知識(shí)庫(kù) > Lua教程(五):C/C++操作Lua數(shù)組和字符串示例

Lua教程(五):C/C++操作Lua數(shù)組和字符串示例

熱門標(biāo)簽:電腦外呼系統(tǒng)輻射大嗎 開通400電話申請(qǐng)流程 揚(yáng)州電銷外呼系統(tǒng)軟件 百度地圖標(biāo)注位置網(wǎng)站 上海企業(yè)外呼系統(tǒng)排名 智能語(yǔ)音電銷的機(jī)器人 如何利用高德地圖標(biāo)注家 400手機(jī)電話免費(fèi)辦理 武漢百應(yīng)人工智能電銷機(jī)器人

本文將介紹如何在C/C++里面操作Lua的數(shù)組和字符串類型,同時(shí)還會(huì)介紹如何在C/C++函數(shù)里面存儲(chǔ)Lua狀態(tài)(registry和upvalue),而registry在使用C/C++自定義類型時(shí)非常有用,可以方便地為userdata指定metatable。

C/C++操作Lua數(shù)組

Lua數(shù)組Overview

在Lua里面,數(shù)組只不過是key為整數(shù)的table而已。比如一個(gè)table為array = {12,”Hello”, “World”},它是一個(gè)數(shù)組,可以用下面的代碼來訪問它:

復(fù)制代碼 代碼如下:

print(array[1])  --這里會(huì)輸出array的第一個(gè)元素12。
print(array[3]) --這里會(huì)輸出array的第三個(gè)元素World

需要注意的一點(diǎn)就是:Lua的數(shù)組的下標(biāo)是從1開始的。如果你使用下面的語(yǔ)句則會(huì)輸出nil值:

復(fù)制代碼 代碼如下:

print(array[0])  --輸出nil
print(array["1"])  --輸出nil(想想和array[1]的區(qū)別:一個(gè)是integer作為key,一個(gè)是字符串做為key)

通用Table操作方法

之前我們?cè)诮坛?中介紹了如何傳遞Table給Lua,以及在教程3中介紹了如何訪問Table的數(shù)據(jù)。因?yàn)閿?shù)組也是Table,所以我們可以用同樣的方式來讀取數(shù)組。

讀取數(shù)組

假設(shè)我們的Lua Table為array = {“Hello”, 1, “World”, 23.2},那么我們可以用下列函數(shù)來訪問它:

復(fù)制代碼 代碼如下:

void readLuaArray(lua_State *L)
{
    lua_settop(L,0); //這樣確保我們的array是放在當(dāng)前棧的棧頂。
    lua_getglobal(L, "array");
    //如果前面不調(diào)用lua_settop(L,0),那我們必須要使用luaL_len(L,-1)
    int n = luaL_len(L, 1);   //luaL_len可以獲得table的元素個(gè)數(shù)
    for (int i = 1; i = n; ++i) {
        lua_pushnumber(L, i);  //往棧里面壓入i
        lua_gettable(L, -2);  //讀取table[i],table位于-2的位置。
        //lua_rawget(L, -2);  //lua_gettable也可以用lua_rawget來替換
        coutlua_tostring(L, -1)endl;
        lua_pop(L, 1);
    }
}

最后輸出的結(jié)果為:

復(fù)制代碼 代碼如下:

"Hello", 1, "World", 23.2

修改數(shù)組

現(xiàn)在我們?nèi)绻胍薷倪@個(gè)數(shù)組,把每一個(gè)數(shù)組的元素都變成”hehe[i]”(i = 1-n),我們看看怎么做。

復(fù)制代碼 代碼如下:

int writeLuaArray(lua_State *L)
{
    lua_settop(L, 0);
    lua_getglobal(L, "array");
    //確保第一個(gè)函數(shù)一個(gè)要是一個(gè)table
    luaL_checktype(L, 1, LUA_TTABLE);
    int n = luaL_len(L,1);
    for (int i = 1; i = n; ++i) {
        lua_pushnumber(L, i);
        char buf[256];
        sprintf(buf, "hehe%d", i);
        lua_pushstring(L, buf);
//        lua_settable(L, -3);
        lua_rawset(L, -3);
    }
    return 0;
}
}

注意這里的lua_rawset和lua_settable是等價(jià)的,只不過lua_rawset速度更快。 最后,我們?cè)诩虞d完Lua腳本以后調(diào)用這兩個(gè)函數(shù):

復(fù)制代碼 代碼如下:

writeLuaArray(L);
readLuaArray(L);

輸出結(jié)果為:

復(fù)制代碼 代碼如下:

readLuaArray: hehe1
readLuaArray: hehe2
readLuaArray: hehe3
readLuaArray: hehe4

專門的數(shù)組操作方法

因?yàn)閿?shù)組一般在程序語(yǔ)言里面都會(huì)被特殊對(duì)待,Lua也不例外,它的C API還提供另外一種更方便高效地方法來存取數(shù)組的元素。

復(fù)制代碼 代碼如下:

 void lua_rawgeti (lua_State *L, int index, int key);
 void lua_rawseti (lua_State *L, int index, int key);

這兩個(gè)函數(shù)后面兩個(gè)參數(shù)的意思分別是:index(table在棧中的索引),key(table中數(shù)組的索引,下標(biāo)從1開始) 接下來,我會(huì)通過改造上面的示例來演示這兩個(gè)API的用法。

讀取數(shù)組

因?yàn)閘ua_rawgeti(L,t,key)等價(jià)于:

復(fù)制代碼 代碼如下:

 lua_pushnumber(L, key);
 lua_rawget(L, t);

因此,我們的讀取代碼可以改寫成下面這樣:

復(fù)制代碼 代碼如下:

void readLuaArray(lua_State *L)
{
    lua_getglobal(L, "array");
    int n = luaL_len(L, -1);
    for (int i = 1; i = n; ++i) {
        lua_rawgeti(L, 1, i);
        cout"readLuaArray: "lua_tostring(L, -1)endl;
        lua_pop(L, 1);
    }
}

修改數(shù)組

同理,lua_rawset(L,t,key)等價(jià)于

復(fù)制代碼 代碼如下:

lua_pushnumber(L,key); //此時(shí)的棧 table->value->key
lua_insert(L,-2);  //調(diào)用完后的棧: table->key->value (table[key]=value)
lua_rawset(L,t);

相應(yīng)的修改數(shù)組的代碼可以修改為:

復(fù)制代碼 代碼如下:

int writeLuaArray(lua_State *L)
{
    lua_settop(L, 0);
    lua_getglobal(L, "array");
    //確保第一個(gè)函數(shù)一個(gè)要是一個(gè)table
    luaL_checktype(L, 1, LUA_TTABLE);
    int n = luaL_len(L,1);
    for (int i = 1; i = n; ++i) {
        char buf[256];
        sprintf(buf, "hehe%d", i);
        lua_pushstring(L, buf);
        lua_rawseti(L, 1, i);
    }
    return 0;
}

C/C++操作Lua字符串

基本字符串操作

Lua C API操作字符串主要包含兩個(gè)操作:求子串(lua_pushlstring)和字符串拼接(lua_concat). 例如,我們求一個(gè)字符串s的子串[i,j],它可以表示為:

復(fù)制代碼 代碼如下:

lua_pushlstring(L, s + i, j - i + 1);

而lua_concat(L,n)則可以把當(dāng)前棧頂?shù)膎個(gè)元素轉(zhuǎn)換成字符串并拼接起來,最后把結(jié)果壓入棧頂。 比如,我們想定義一個(gè)函數(shù)mycontact(…,n)可以把n個(gè)字符串拼接起來,n表示字符串的個(gè)數(shù),那么我們的代碼可以寫成這樣:
復(fù)制代碼 代碼如下:

static int l_mycontact(lua_State* L){
    luaL_checktype(L, -1, LUA_TNUMBER);
    int n = lua_tonumber(L, -1);
    lua_pop(L, 1);
    lua_concat(L, n);
    return 1;
}

然后,我們需要注冊(cè)此函數(shù)到libs中去,最后在Lua里面調(diào)用此函數(shù):

復(fù)制代碼 代碼如下:

print(mylib.mycontact("zilong","shanren"," meng meng"," da",4))

輸出結(jié)果為:

復(fù)制代碼 代碼如下:

zilongshanren meng meng da

格式化輸出

當(dāng)我們想要往Lua里面寫入一個(gè)格式化字符串時(shí),可以使用函數(shù)

復(fù)制代碼 代碼如下:

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

另外,我們還可以使用luaL_Buffer,下面是PIL書中的示例,把Lua字符串轉(zhuǎn)換成大寫:

復(fù)制代碼 代碼如下:

 static int str_upper (lua_State *L) {
     size_t l;
     size_t i;
     luaL_Buffer b;
     const char *s = luaL_checklstring(L, 1, l);  //從Lua棧中取出字符串
     char *p = luaL_buffinitsize(L, b, l); //分配一塊與取出字符串同樣大小的緩沖區(qū)
     for (i = 0; i l; i++)
       p[i] = toupper(uchar(s[i]));
     luaL_pushresultsize(b, l);  //把緩沖區(qū)結(jié)果轉(zhuǎn)換為字符串
     return 1;
}

更多的Lua Buffer操作函數(shù)如下:

復(fù)制代碼 代碼如下:

 void luaL_buffinit   (lua_State *L, luaL_Buffer *B);
 void luaL_addvalue   (luaL_Buffer *B);
 void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
 void luaL_addstring  (luaL_Buffer *B, const char *s);
 void luaL_addchar    (luaL_Buffer *B, char c);
 void luaL_pushresult (luaL_Buffer *B);

關(guān)于每一個(gè)函數(shù)的用法和每一個(gè)參數(shù)的含義,大家可以去Lua的Reference Manual上去查看,本文就不贅述了。

存儲(chǔ)Lua狀態(tài)

在C函數(shù)里面,當(dāng)我們需要保存函數(shù)里面的一些狀態(tài)的時(shí)候,我們一般采用全局變量或者靜態(tài)變量的方式。但是,如果在與Lua交互時(shí),這兩種方法都不可取。 原因有二: 1. C變量很難存儲(chǔ)各種各樣的Lua變量。 2. 當(dāng)存在多個(gè)Lua棧的時(shí)候,就不生效了。 在Lua里面有兩種方法來存在函數(shù)內(nèi)的non-local數(shù)據(jù):registry和upvalue.

Registry方式

Register是一個(gè)Lua的全局Table,只有在Lua的C API里面可以訪問這個(gè)Table。它可以用來存儲(chǔ)多個(gè)Lua模塊之間的數(shù)據(jù)。 訪問Register的方式一般為:

復(fù)制代碼 代碼如下:

 lua_getfield(L, LUA_REGISTRYINDEX, "Key");

我們需要提供一個(gè)LUA_REGISTRYINDEX的“偽索引”來標(biāo)識(shí)它在Lua棧中的位置。我們?cè)诓僮鬟@個(gè)table的時(shí)候,最好是使用字符串做為key,而不要使用數(shù)字來做為key。關(guān)于Registry更為實(shí)際的用法,我們會(huì)在下一篇文章中討論。

Upvalue方式

Upvalue主要用來存儲(chǔ)模塊或者函數(shù)內(nèi)部的一些私有的數(shù)據(jù),它與C語(yǔ)言的靜態(tài)變量有點(diǎn)類似。具體的用法可以參考PIL

您可能感興趣的文章:
  • 淺談C/C++中指針和數(shù)組的不同
  • C++小知識(shí):C/C++中不要按值傳遞數(shù)組
  • C/C++中接收return返回來的數(shù)組元素方法示例
  • C/C++ 動(dòng)態(tài)數(shù)組的創(chuàng)建的實(shí)例詳解
  • C/C++ 數(shù)組和指針及引用的區(qū)別
  • 圖文詳解c/c++中的多級(jí)指針與多維數(shù)組
  • 淺析C/C++,Java,PHP,JavaScript,Json數(shù)組、對(duì)象賦值時(shí)最后一個(gè)元素后面是否可以帶逗號(hào)
  • C/C++中獲取數(shù)組長(zhǎng)度的方法示例
  • 淺析C語(yǔ)言編程中的數(shù)組越界問題
  • C/C++ 避免數(shù)組越界的方法

標(biāo)簽:嘉峪關(guān) 新余 黑龍江 張掖 延邊 武漢 宜賓 江西

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua教程(五):C/C++操作Lua數(shù)組和字符串示例》,本文關(guān)鍵詞  Lua,教程,五,C++,操作,數(shù)組,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Lua教程(五):C/C++操作Lua數(shù)組和字符串示例》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于Lua教程(五):C/C++操作Lua數(shù)組和字符串示例的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章