[SourcePawn] Урок 8 - Структуры Key Values

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
@Nekro, в уроке же всё есть
@Nekro, в уроке же всё есть
В том то и дело, что в уроке нет такого
Там есть только переходы на уже известные позиции.

C-подобный:
"GlobalKey"
{
    "key1"    //Мы не знаем его названия
    {
        "param1"    "value1"
        "param2"    "value2"
    }

    "key2"    //Мы не знаем его названия
    {
        "param1"    "value1"
        "param2"    "value2"
    }
}
А необходимо пробежать по ним не имея названий, так как в конфиге их могут сменить на любые
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
@Nekro, тебе же в коде показали ка пробежаться по блокам "key*" не зная их названий.
Внутри же обычно ключи должны быть известны (иначе применяешь тот же способ, что и для "key*").
 

Rolzzandik

Участник
Сообщения
492
Реакции
234
В том то и дело, что в уроке нет такого
Там есть только переходы на уже известные позиции.

C-подобный:
"GlobalKey"
{
    "key1"    //Мы не знаем его названия
    {
        "param1"    "value1"
        "param2"    "value2"
    }

    "key2"    //Мы не знаем его названия
    {
        "param1"    "value1"
        "param2"    "value2"
    }
}
А необходимо пробежать по ним не имея названий, так как в конфиге их могут сменить на любые
GetSectionName
so ->
снюсоеды!!!:
if(hKV.GotoFirstSubKey())
    do {
        hKV.GetSectionName(szSection, sizeof szSection);
        /*
        * Тут воркаем с ключем
        * Например, 
        *
        * hKV.JumpToKey(szSection); // Ваще проверку if(...) 
        * int ikeyname = hKV.GetNum("keyname", 0);
        * int ikeyname2 = hKV.GetNum("keyname2", 0);
        */
    } while (hKV.GotoNextKey());
Это если неизвестен сабкей(т.е его название), но известны сами ключи

Насколько я понял, вопрос заключается именно в этом.
 

Tomiks

Участник
Сообщения
419
Реакции
288
GetSectionName
so ->
снюсоеды!!!:
if(hKV.GotoFirstSubKey())
    do {
        hKV.GetSectionName(szSection, sizeof szSection);
        /*
        * Тут воркаем с ключем
        * Например,
        *
        * hKV.JumpToKey(szSection); // Ваще проверку if(...)
        * int ikeyname = hKV.GetNum("keyname", 0);
        * int ikeyname2 = hKV.GetNum("keyname2", 0);
        */
    } while (hKV.GotoNextKey());
Это если неизвестен сабкей(т.е его название), но известны сами ключи

Насколько я понял, вопрос заключается именно в этом.
@Nekro
В добавок к этому могу сказать, что, где комментарий Rolzzandik оставил, можно такой же цикл сделать и уже пройтись по ключам в этой секции(соответственно не зная названий ключей)
Значение ключей можно получить в втором цикле с помощью hHV.GetNum(NULL_STRING); допустим(если это числовое значение)
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
@Grey83, @Rolzzandik, @Tomiks,

C-подобный:
"Title"
{
    "List"
    {
        "Key1"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key2"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key3"
        {
            "min"        "0"
            "max"        "1"
        }
    }
}


C-подобный:
void List()
{
    hKeyValues.Rewind();
    hKeyValues.JumpToKey("Title", false);

    char sKey[32], sValue[16];
    char sKeyMin[32];
   
    if(hKeyValues.GotoFirstSubKey(false))        //Устанавливает текущую позицию в дереве KeyValues для первого подключа
    {
        do
        {
            if(hKeyValues.GetSectionName(sKey, sizeof(sKey)))        //Получает имя текущего раздела.
            {
                if(hKeyValues.GotoFirstSubKey(false))        //Устанавливает текущую позицию в дереве KeyValues для первого подключа
                {
                    int iCmdChat;
                    do hKeyValues.GoBack
                    {
                        if(hKeyValues.GetSectionName(sKeyMin, sizeof(sKeyMin)))        //Получает имя текущего раздела.
                        {
                            hKeyValues.GetString(NULL_STRING, sValue, sizeof(sValue));        //    Извлекает строковое значение из ключа KeyValues
                           
                            if(!iCmdChat) PrintToChatAll("Ключ: %s, значение min: %s", sKey, sValue);
                            else
                            {
                                PrintToChatAll("Ключ: %s, значение max: %s", sKey, sValue);
                                hKeyValues.GoBack();        //Прыгаем выше (это не работает)
                            }
                           
                            iCmdChat++;
                        }
                    } while( hKeyValues.GotoNextKey(false) );
                }
            }
        } while( hKeyValues.GotoNextKey(false) );
        CheckClientAll(sKey);
    }
}
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
@Nekro, не вижу никакого смыла в цикле: у тебя же в каждой секции одни и те же ключи используются.
Сообщения автоматически склеены:

@Nekro, ты это не значения кваров у игроков проверять вздумал?
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
@Nekro, не вижу никакого смыла в цикле: у тебя же в каждой секции одни и те же ключи используются.
Значения ключей будут разные, необходимо прочитать сами ключи Key1, Key2 и так далее и их min и max
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
@Nekro, тебе достаточно вот такого кода, кмк:
C-подобный:
stock void List()
{
    if(!hKeyValues) return;                    // hKeyValues не существует

    hKeyValues.Rewind();                    // переносимся в самое начало KeyValues
    if(!hKeyValues.GotoFirstSubKey(false))    // Устанавливает текущую позицию в дереве KeyValues для первого подключа
        return;

    char section[32], value[16];
    do
    {
        if(!hKeyValues.GetSectionName(section, sizeof(section)))    // Получает имя текущего раздела.
            continue;

        PrintToChatAll("Ключ: %s", section);
        hKeyValues.GetString("min", value, sizeof(value));
        if(value[0]) PrintToChatAll("значение 'min': %s", value);
        hKeyValues.GetString("max", value, sizeof(value))
        if(value[0]) PrintToChatAll("значение 'max': %s", value);

        CheckClientAll(section);
        hKeyValues.GoBack();
    } while(hKeyValues.GotoNextKey(false));
}
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
@Nekro, тебе достаточно вот такого кода, кмк:
C-подобный:
stock void List()
{
    if(!hKeyValues) return;                    // hKeyValues не существует

    hKeyValues.Rewind();                    // переносимся в самое начало KeyValues
    if(!hKeyValues.GotoFirstSubKey(false))    // Устанавливает текущую позицию в дереве KeyValues для первого подключа
        return;

    char section[32], value[16];
    do
    {
        if(!hKeyValues.GetSectionName(section, sizeof(section)))    // Получает имя текущего раздела.
            continue;

        PrintToChatAll("Ключ: %s", section);
        hKeyValues.GetString("min", value, sizeof(value));
        if(value[0]) PrintToChatAll("значение 'min': %s", value);
        hKeyValues.GetString("max", value, sizeof(value))
        if(value[0]) PrintToChatAll("значение 'max': %s", value);

        CheckClientAll(section);
        hKeyValues.GoBack();
    } while(hKeyValues.GotoNextKey(false));
}
Так он будет считывает только "List"

C-подобный:
"Title"
{
    "List"    //Читает только это
    {
        "Key1"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key2"
        {
            "min"        "0"
            "max"        "1"
        }
    }
}
Задумка, что будет не только одна секция "List", а будут ещё "List2" и "List3"

Сейчас выводит в чат Ключ: List и больше ничего
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
Дай пжлст полный пример структуры, чтобы понимать с чем по итогу будет идти работа
Вот, будет вот таких 3 блока

C-подобный:
"Title"
{
    "List"    //Читает только это
    {
        "Key1"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key2"
        {
            "min"        "0"
            "max"        "1"
        }
    }
    "List2"    //Читает только это
    {
        "Key1"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key2"
        {
            "min"        "0"
            "max"        "1"
        }
    }
    "List3"    //Читает только это
    {
        "Key1"
        {
            "min"        "0"
            "max"        "1"
        }
        "Key2"
        {
            "min"        "0"
            "max"        "1"
        }
    }
}
 

Rolzzandik

Участник
Сообщения
492
Реакции
234
Вот, будет вот таких 3 блока
лютый межбулочный разрыв:
if(hKV.GotoFirstSubKey()) // переходим к первому ключу
    do {
        hKV.GetSectionName(szSection, sizeof szSection); //Получаем имя (list1, list2)
        hKV.JumpToKey(szSection); //Переходим к ключу
        if(hKV.GotoFirstSubKey()) //Переходим к первому саб-ключу
            do {
                hKV.GetSectionName(szSection, sizeof szSection); //Получаем имя (key1, key2)
                hKV.JumpToKey(szSection); //Переходим в него (Вообще это поидее не надо, туплю чет)
                int iMax = hKV.GetNum("max", 0);
                int iMax = hKV.GetNum("min", 0);
                //Далее работаем со значениями
            } while (hKV.GotoNextKey()); //Делаем цикл по всем саб-кеям (key1, key2)
    } while (hKV.GotoNextKey()); //Делаем цикл по всем ключам (list1, list2)
Поидее так, но мог где-то зашизить.
Тебе по факту надо делать два цикла, в которых ты перебираешь ключи и сабкеи в ключах
Еще возможно потребуется kv.GoBack() и для ключей, и для сабкеев
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
int iMax = hKV.GetNum("max", 0);
int iMax = hKV.GetNum("min", 0);
Дефолтные значения можно не указывать (я про нули в последнем параметре).

@Rolzzandik, и да: ты неправильно назвал вторую переменную, из-за чего код не скомпилится. =)
Сообщения автоматически склеены:

Вообще переменные следовало создавать перед циклами, а внутри только присваивать им значения.
Сообщения автоматически склеены:

@Nekro, для чего делать несколько блоков, включающих в себя ещё блоки, если всё равно внутри у них одно и то же содержимое, кроме того всё проходится циклом?
Сообщения автоматически склеены:

Задумка, что будет не только одна секция "List", а будут ещё "List2" и "List3"

Сейчас выводит в чат Ключ: List и больше ничего
Попробуй вот так:
C-подобный:
stock void List()
{
    if(!hKeyValues) return;                    // hKeyValues не существует

    hKeyValues.Rewind();                    // переносимся в самое начало KeyValues
    if(!hKeyValues.GotoFirstSubKey(false))    // Устанавливает текущую позицию в дереве KeyValues для первого подключа
        return;

    char section[32], key[32], value[16];
    do
    {
        if(hKeyValues.GetSectionName(section, sizeof(section))) do
        {
            if(!hKeyValues.GetSectionName(section, sizeof(section)))    // Получает имя текущего раздела.
                continue;

            PrintToChatAll("Ключ: %s", section);
            hKeyValues.GetString("min", value, sizeof(value));
            if(value[0]) PrintToChatAll("значение 'min': %s", value);
            hKeyValues.GetString("max", value, sizeof(value))
            if(value[0]) PrintToChatAll("значение 'max': %s", value);
    
            CheckClientAll(section);

            hKeyValues.GoBack();
        } while(hKeyValues.GotoNextKey(false));

        hKeyValues.GoBack();
    } while(hKeyValues.GotoNextKey(false));
}
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #56
Дефолтные значения можно не указывать (я про нули в последнем параметре).

@Rolzzandik, и да: ты неправильно назвал вторую переменную, из-за чего код не скомпилится. =)
Сообщения автоматически склеены:

Вообще переменные следовало создавать перед циклами, а внутри только присваивать им значения.
Сообщения автоматически склеены:

@Nekro, для чего делать несколько блоков, включающих в себя ещё блоки, если всё равно внутри у них одно и то же содержимое, кроме того всё проходится циклом?
Сообщения автоматически склеены:


Попробуй вот так:
C-подобный:
stock void List()
{
    if(!hKeyValues) return;                    // hKeyValues не существует

    hKeyValues.Rewind();                    // переносимся в самое начало KeyValues
    if(!hKeyValues.GotoFirstSubKey(false))    // Устанавливает текущую позицию в дереве KeyValues для первого подключа
        return;

    char section[32], key[32], value[16];
    do
    {
        if(hKeyValues.GetSectionName(section, sizeof(section))) do
        {
            if(!hKeyValues.GetSectionName(section, sizeof(section)))    // Получает имя текущего раздела.
                continue;

            PrintToChatAll("Ключ: %s", section);
            hKeyValues.GetString("min", value, sizeof(value));
            if(value[0]) PrintToChatAll("значение 'min': %s", value);
            hKeyValues.GetString("max", value, sizeof(value))
            if(value[0]) PrintToChatAll("значение 'max': %s", value);
  
            CheckClientAll(section);

            hKeyValues.GoBack();
        } while(hKeyValues.GotoNextKey(false));

        hKeyValues.GoBack();
    } while(hKeyValues.GotoNextKey(false));
}


hKeyValues.GoBack();
после вложенного цикла делается, а не внутри. и ты ж нормальный человек, поставь do нормально
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
@R1KO, там GoBack() в цикле тоже нужен: там же двойное вложение
Пример конфига же кидали.
Сообщения автоматически склеены:

поставь do нормально
компилится без ошибок
 
  • Фэйспалм
Реакции: R1KO

KiKiEEKi

🏆 🥇
Сообщения
653
Реакции
513
Прочитал я тему и не чего не помогло. Подскажите что нужно сделать дабы исправить дубликаты чтения ключей.

Вот я читаю ключи и добавляю их в array:
if(hKeyValues.GotoFirstSubKey(false)) //Переходит к первому ключу внутри текущей секции
        {
            do
            {
                hKeyValues.GetString("name", sBuffer, sizeof(sBuffer));
                hArrMapName.PushString(sBuffer);
                hKeyValues.GetString("customname", sBuffer, sizeof(sBuffer));
                hArrMapCustomName.PushString(sBuffer);
            }
            while(hKeyValues.GotoNextKey(false)); //Переходит к следующему ключу в секции
        }

C-подобный:
"NewMapVoting"
{
    "0" //Уникальное индекс карты
    {
        "name"                "2000"            //Название карты
        "customname"        "Две тысячи"    //Пользовательское название карты
    }
    "1"
    {
        "name"                "de_dust2"
        "customname"        "ДАСТ 2"
    }
    "2"
    {
        "name"                "cs_assault"
        "customname"        "АСАУТ"
    }
    "3"
    {
        "name"                "cs_italy"
        "customname"        "ИТАЛИЯ"
    }
    "4"
    {
        "name"                "cs_office"
        "customname"        "ОФИС"
    }
    "5"
    {
        "name"                "de_aztec"
        "customname"        "АСТЕК"
    }
    "6"
    {
        "name"                "de_nuke"
        "customname"        "НЮК"
    }
}

C-подобный:
Size: 14 | Name: 2000 | CustomName: Две тысячи
Size: 14 | Name: de_dust2 | CustomName: ДАСТ 2
Size: 14 | Name: cs_assault | CustomName: АСАУТ
Size: 14 | Name: cs_italy | CustomName: ИТАЛИЯ
Size: 14 | Name: cs_office | CustomName: ОФИС
Size: 14 | Name: de_aztec | CustomName: АСТЕК
Size: 14 | Name: de_nuke | CustomName: НЮК
Size: 14 | Name: 2000 | CustomName: Две тысячи
Size: 14 | Name: de_dust2 | CustomName: ДАСТ 2
Size: 14 | Name: cs_assault | CustomName: АСАУТ
Size: 14 | Name: cs_italy | CustomName: ИТАЛИЯ
Size: 14 | Name: cs_office | CustomName: ОФИС
Size: 14 | Name: de_aztec | CustomName: АСТЕК
Size: 14 | Name: de_nuke | CustomName: НЮК

Код которым вывожу в консоль:
public Action Cmd_MapList(int iClient, int iArgs)
{
    char sMapName[64];
    char sMapCustomName[64];
    for(int i = 0; i < hArrMapName.Length; ++i)
    {
        hArrMapName.GetString(i, sMapName, sizeof(sMapName));
        hArrMapCustomName.GetString(i, sMapCustomName, sizeof(sMapCustomName));
        PrintToConsole(iClient, "Size: %i | Name: %s | CustomName: %s", hArrMapName.Length, sMapName, sMapCustomName);
    }

    return Plugin_Handled;
}
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,519
Реакции
4,979
@KiKiEEKi, ты вызываешь чтение конфига 2 раза, но не очищаешь перед чтением hArrMapName и hArrMapCustomName
 

Temlik

Участник
Сообщения
668
Реакции
174
Очепятка: float fVec[4] (для вектора выделяется 4 ячейки, вместо 3)
 
Сверху Снизу