16

luaテーブルを反復処理しようとしていますが、次のエラーが発生し続けます。

invalid key to 'next'

インデックスは-8で始まり、最初の(そして唯一の)値を取得するため、そこにテーブルがあることを知っています。ただし、テーブルに文字列が1つしかないことがわかっていても、ループを再度試行します。

if (lua_istable(L, index))
{
    lua_pushnil(L);

    // This is needed for it to even get the first value
    index--;

    while (lua_next(L, index) != 0)
    {
        const char *item = luaL_checkstring(L, -1);
        lua_pop(L, 1);

        printf("%s\n", item);
    }
}
else
{
    luaL_typerror(L, index, "string table");
}

どんな助けでもいただければ幸いです。

これは、正のインデックスを使用する場合に正常に機能します(1を削除しない限り)

編集:アイテムの値をそのままにしておいても、このエラーが発生しないことに気づきました。アイテムの値を読み始めたときにのみ、このエラーが発生します。テーブルから値を取得したら、別のLua関数を呼び出します。これにより、lua_nextが中断される可能性がありますか?

4

4 に答える 4

35

あなたが見る必要がある2つのことがあります:

  • への次の呼び出しの前に、元のキーがスタックに残されていることを確認してlua_nextください。luaL_checkstring非文字列キーを文字列に変換します (結果の文字列がテーブルにないため、無効なキーになります)。これはluaL_checkstring、元のキーの代わりにキーのコピーを渡すことで最も簡単に実行できます。
  • ループを通過するたびにスタック構造を保持する (つまり、プッシュするだけの数の値をポップする) ことを確認してください。

関数は の負の値に対してのみ機能しますindex。キーを押した後も がテーブルを指しているindex--;ことを確認するのは正しいですが、負の場合 (つまり、スタックの上部に対して相対的) に限ります。が絶対インデックスまたは疑似インデックスの場合、これにより、間違った項目。最も簡単な回避策は、テーブルへの別の参照をスタックの一番上にプッシュすることです。indexindexindex

デモ用の最小限の C プログラムを次に示します。

#include <lauxlib.h>
#include <lua.h>

static void iterate_and_print(lua_State *L, int index);

int main(int ac, char **av)
{
   lua_State *L = luaL_newstate();
   luaL_openlibs(L);

   // Create a table and put it on the top of the stack
   luaL_loadstring(L, "return {one=1,[2]='two',three=3}");
   lua_call(L, 0, 1);

   iterate_and_print(L, -1);
   return 0;
}

static void iterate_and_print(lua_State *L, int index)
{
    // Push another reference to the table on top of the stack (so we know
    // where it is, and this function can work for negative, positive and
    // pseudo indices
    lua_pushvalue(L, index);
    // stack now contains: -1 => table
    lua_pushnil(L);
    // stack now contains: -1 => nil; -2 => table
    while (lua_next(L, -2))
    {
        // stack now contains: -1 => value; -2 => key; -3 => table
        // copy the key so that lua_tostring does not modify the original
        lua_pushvalue(L, -2);
        // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
        const char *key = lua_tostring(L, -1);
        const char *value = lua_tostring(L, -2);
        printf("%s => %s\n", key, value);
        // pop value + copy of key, leaving original key
        lua_pop(L, 2);
        // stack now contains: -1 => key; -2 => table
    }
    // stack now contains: -1 => table (when lua_next returns 0 it pops the key
    // but does not push anything.)
    // Pop table
    lua_pop(L, 1);
    // Stack is now the same as it was on entry to this function
}
于 2011-05-26T17:33:52.173 に答える
5

luaL_checkstring負の引数と一緒に使用しないでください。lua_tostring代わりに使用してください。

また、ループ内で関数を呼び出した後、スタックが同じままであることを確認してくださいlua_next。トラバーサルを再開できるように、スタックの一番上に前のテーブル キーが必要です。

于 2011-05-26T12:44:38.730 に答える
3

マニュアルから:

const char *lua_tolstring (lua_State *L, int index, size_t *len);

指定された受け入れ可能なインデックスの Lua 値を C 文字列に変換します。len が NULL でない場合、*len にも文字列の長さが設定されます。Lua 値は文字列または数値でなければなりません。それ以外の場合、関数は NULL を返します。値が数値の場合、 lua_tolstring はスタック内の実際の値も文字列に変更します。(この変更により、lua_tolstring がテーブル走査中にキーに適用されると lua_next が混乱します。)

luaL_checkstringを呼び出しますlua_tolstring

于 2011-05-26T12:56:04.243 に答える
2

lua_nextここに抜粋された のドキュメントの例も参照してください。

int lua_next (lua_State *L, int index);

スタックからキーをポップし、指定されたインデックス (指定されたキーの後の "次の" ペア) でテーブルからキーと値のペアをプッシュします。テーブルにそれ以上要素がない場合は、lua_next0 を返します (何もプッシュしません)。

典型的なトラバーサルは次のようになります。

/* table is in the stack at index 't' */
 lua_pushnil(L);  /* first key */
 while (lua_next(L, t) != 0) {
   /* uses 'key' (at index -2) and 'value' (at index -1) */
   printf("%s - %s\n",
          lua_typename(L, lua_type(L, -2)),
          lua_typename(L, lua_type(L, -1)));
   /* removes 'value'; keeps 'key' for next iteration */
   lua_pop(L, 1);
 }

lua_tolstringキーが実際に文字列であることがわかっている場合を除き、テーブルを走査している間はキーを直接呼び出さないでください。lua_tolstring指定されたインデックスの値を変更する可能性があることを思い出してください。これは への次の呼び出しを混乱させlua_nextます。

next走査中にテーブルを変更する場合の注意事項については、関数を参照してください。

于 2016-05-03T20:40:50.287 に答える