Русское сообщество по скриптингу

Массивы (Array и Trie)

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Массивы (Array и Trie)

Сообщение creator_52 » 06 мар 2011, 17:16

Авторы: creator_52

Array - динамичный массив. В отличие от обычных двумерных массивов, где нужно указывать длину строки и кол-во самих строк, в динамичных нужно указать только длину строки, т.е. они имеют неограниченный размер. Это может быть полезным, к примеру, при получении информации из файла. Объявлять этот массив следует так: Array:название[]. Рассмотрим наиболее используемые функции:

Код: Выделить всё
ArrayCreate ( [ cellsize=1, reserved=32 ] )


Cоздает массив. Это может выглядеть так,

Код: Выделить всё
new Array:a_array=ArrayCreate(32)


где 32 - максимальная длина строки в массиве.

Код: Выделить всё
ArrayDestroy ( &Array:which )


Разрушает указанный динамичный массив.

Код: Выделить всё
ArrayClear ( Array:which )


Очищает указанный массив. Возвращает 1 в случае успеха, 0 - в случае неудачи.

Код: Выделить всё
ArrayPushString ( Array:which, const input[] )


Добавляет в массив новую строку. Пример занесения в массив всей информации из файла,

Код: Выделить всё
#include <amxmodx>

// Создаем переменную под массив

static Array:g_a_data

public plugin_init
()
{
    // Объявляем динамичный массив g_a_data
    
    g_a_data
=ArrayCreate(1024)
    
    
// Через 0.3 секунды начать чтение файла
    
    set_task
(0.3,"get_data",128)
}

public get_data()
{
    // Получаем индекс файла data.dat, который находится в директории cstrike
    
    new i_file
=fopen("data.dat","rt")
    
    
// Если произошла ошибка открытии файла - прекращаем выполнение кода
    
    if
(!i_file)
    {
        return PLUGIN_CONTINUE
    
}
    
    
// Создаем строку для временного хранения информации, получаемой из файла
    
    new s_buffer
[1024]
    
    
// Пока не будет достигнут конец файла, продолжать выполнять цикл
    
    while
(!feof(i_file))
    {
        //Получаем следующую строку из файла в s_buffer
        
        fgets
(i_file,s_buffer,1023)
        
        
// Очищаем строку от каретки
        
        trim
(s_buffer)
        
        
// Добавляем эту строку в массив
        
        ArrayPushString
(g_a_data,s_buffer)
    }
    
    
// Закрываем файл по индексу
    
    fclose
(i_file)
    
    return PLUGIN_CONTINUE
}


где максимальное кол-во строк не зависит от размера создаваемого массива.

Код: Выделить всё
ArrayPushCell ( Array:which, any:input )


Добавляет в массив числовую переменную или один символ.

Код: Выделить всё
ArraySize ( Array:which )


Возвращает размер массива, т.е. кол-во ячеек. Пример получения размера массива в переменную i_size,

Код: Выделить всё
new i_size=ArraySize(g_a_data)


где g_a_data - название массива.

Код: Выделить всё
ArrayDeleteItem ( Array:which, item )


Удаляет указанную ячейку в массиве.

Код: Выделить всё
ArrayGetString ( Array:which, item, output[], size )


Получает в строку информацию из ячейки, где item - номер ячейки. Пример удаления ячейки, в которой содержится строка "array":

Код: Выделить всё
public my_function()
{
    // Получаем размер массива g_a_data в переменную i_size
    
    new i_size
=ArraySize(g_a_data)
    
    
// Если размер нулевой - прекращаем работу, т.к. массив пуст
    
    if
(!i_size)
    {
        return PLUGIN_CONTINUE
    
}
    
    
// Создаем строку для временного хранения данных
    
    new s_buffer
[6]
    
    
// Создаем цикл, в котором указатель a прибавляется на одно значение, пока не достигнет конца массива
    
    for
(new a;a<i_size;a++)
    {
        // Получаем строку из ячейки a в s_buffer
        
        ArrayGetString
(g_a_data,a,s_buffer,5)
        
        
// Если строка совпадает с "array" - удаляем эту ячейку из массива
        
        if
(equal(s_buffer,"array"))
        {
            ArrayDeleteItem(g_a_data,a)
            
            return PLUGIN_CONTINUE
        
}
    }
    
    return PLUGIN_CONTINUE
}


Код: Выделить всё
ArrayGetCell ( Array:which, item )


Возвращает число из указанной ячейки. Пример получения числа из ячейки 1 в переменную i_cell из массива g_a_data,

Код: Выделить всё
new i_cell=ArrayGetCell(g_a_data,1)


где g_a_data - массив с максимальной длиной строки 1. Получается, что этот кусок кода

Код: Выделить всё
new s_buffer[128]

ArrayGetString(g_a_data,1,s_buffer,127)

new i_buffer=str_to_num(s_buffer)


выполняет ту же работу, что и этот,

Код: Выделить всё
new i_buffer=ArrayGetCell(g_a_data,1)


только второй способ оптимальнее.

Код: Выделить всё
ArraySetString ( Array:which, item, const input[] )


Заменяет информацию в указанной ячейке на Вашу строку.

Код: Выделить всё
ArraySetCell ( Array:which, item, any:input )


Заменяет информацию в указанной ячейке на Ваше число или символ.

Trie - ассоциативный массив. Ячейка в таком массиве имеет вид ключ - значение, причем ключ может быть только строкой, а вот значение - хоть строкой, хоть символом или числом. Вот некоторые функции:

Код: Выделить всё
TrieCreate()


Создает ассоциативный массив. Это может выглядеть так,

Код: Выделить всё
new Trie:g_t_data=TrieCreate()


где не надо указывать никаких размеров.

Код: Выделить всё
TrieDestroy (&Trie:handle)


Разрушает указанный массив.

Код: Выделить всё
TrieClear (Trie:handle)


Очищает указанный массив.

Код: Выделить всё
TrieSetString (Trie:handle, const key[], const value[])


Заменяет существующее значение ключа на Вашу строку, где const key[] - ключ, const value[] - значение. Если данный ключ не существует, он создается автоматически.

Код: Выделить всё
TrieSetCell (Trie:handle, const key[], any:value)


Заменяет существующее значение ключа на Ваше число или символ.

Код: Выделить всё
TrieKeyExists (Trie:handle, const key[])


Возвращает 1, если в данном массиве существует ячейка с ключом const key[], и 0, если не существует. Пример проверки на наличие ключа key в массиве g_t_data:

Код: Выделить всё
if(TrieKeyExists(g_t_data,"key"))
{
    // ...
}


или

Код: Выделить всё
if(TrieKeyExists(g_t_data,"key")==1)
{
    // ...
}


Код: Выделить всё
TrieGetString (Trie:handle, const key[], output[], outputsize)


Получает в строку данные из ячейки с ключом const key[]. Разумеется, прежде чем получать, стоит проверить наличие ячейки с данным ключом:

Код: Выделить всё
if(TrieKeyExists(g_t_data,"key"))
{
    new s_buffer[128]
    
    TrieGetString
(g_t_data,"key",s_buffer,127)
}


Код: Выделить всё
TrieGetCell (Trie:handle, const key[], &any:value)


Получает в переменную данные из ячейки с ключом const key[].

Код: Выделить всё
TrieDeleteKey (Trie:handle, const key[])


Удаляет ячейку с указанным ключом. Пример небольшого бан-плагина с блокировкой по internet protocol - у:

Код: Выделить всё
#include <amxmodx>
#include <amxmisc>

static Trie:g_t_bans

public plugin_init
()
{
    // Регистрируем плагин
    
    register_plugin
("Easy ban system","1","creator_52")
    
    
// Регистрируем консольную команду ebs_ban
    
    register_concmd
("ebs_ban","ebs_ban",ADMIN_BAN,"<playername>")
    
    
// Создаем ассоциативный массив g_t_bans
    
    g_t_bans
=TrieCreate()
    
    
// Через 0.3 секунды получить баны из файла
    
    set_task
(0.3,"read_ban_file",128)
}

public read_ban_file()
{
    // Получаем индекс файла internet_protocol.txt
    
    new i_file
=fopen("internet_protocol.txt","a+")
    
    
// Если произошла ошибка открытии файла - прекращаем выполнение кода
    
    if
(!i_file)
    {
        return PLUGIN_CONTINUE
    
}
    
    
// Создаем необходимые строки
    
    new s_buffer
[128],s_ip[64],s_name[64]
    
    
// Пока не будет достигнут конец файла, продолжать выполнять цикл
    
    while
(!feof(i_file))
    {
        //Получаем следующую строку из файла в s_buffer
        
        fgets
(i_file,s_buffer,127)
        
        
// Очищаем строку от каретки
        
        trim
(s_buffer)
        
        
// Если первый символ строки пуст - пропускаем
        
        if
(!s_buffer[0]||s_buffer[0]==';'||(s_buffer[0]=='/'&&s_buffer[1]=='/'))
        {
            continue
        
}
        
        
// Парсим строку на ip и имя
        
        parse
(s_buffer,s_ip,63,s_name,63)
        
        
// Заносим в массив ячейку с ключем ip и значением - имя
        
        TrieSetString
(g_t_bans,s_ip,s_name)
    }
    
    
// Закрываем файл по индексу
    
    fclose
(i_file)
    
    return PLUGIN_CONTINUE
}

public client_connect(i_player)
{
    // Если игрок бот или hltv - прекращаем выполнение кода
    
    if
(is_user_bot(i_player)||is_user_hltv(i_player))
    {
        return PLUGIN_CONTINUE
    
}
    
    
// Создаем переменную под ip игрока
    
    new s_ip
[64]
    
    
// Получаем ip игрока
    
    get_user_ip
(i_player,s_ip,63)
    
    
// Проверяем, есть ли такой ключ в массиве, иными словами есть ли игрок в бан-листе
    
    if
(TrieKeyExists(g_t_bans,s_ip))
    {
        // Если есть - значит, был забанен ранее
        
        
// Создаем необходимые переменные
        
        new s_dataname
[64],s_name[64]
        
        
// Получаем userid игрока
        
        new i_userid
=get_user_userid(i_player)
        
        
// Получаем имя игрока, под которым он был ранее забанен
        
        TrieGetString
(g_t_bans,s_ip,s_dataname,63)
        
        
// Получаем настоящее имя игрока
        
        get_user_info
(i_player,"name",s_name,63)
        
        
// Выводим надпись с настоящим ником игрока и тем, под каким он был забанен
        
        client_print
(0,print_chat,"Banned player %s connect with name %s",s_dataname,s_name)
        
        
// Выкидываем его с сервера
        
        server_cmd
("kick #%d You have been banned from the server!",i_userid)
    }
    
    return PLUGIN_CONTINUE
}

public ebs_ban(i_player,i_level,i_cid)
{
    // Если игрок НЕ администратор - прекращаем выполнение кода
    
    if
(!cmd_access(i_player,i_level,i_cid,2))
    {
        return PLUGIN_HANDLED
    
}
    
    
// Получаем инфо игрока для бана
    
    new s_argv
[64]
    
    read_argv
(1,s_argv,63)
    
    new i_victim
=cmd_target(i_player,s_argv,18)
    
    if
(!i_victim)
    {
        return PLUGIN_HANDLED
    
}
    
    new s_ip
[64],s_name[64],s_buffer[128]
    
    get_user_ip
(i_victim,s_ip,63,1)
    get_user_info(i_victim,"name",s_name,63)
    
    format
(s_buffer,127,"^"%s^" ^"%s^"",s_ip,s_name)
    
    
// Добавляем новый бан в массив (ip - ключ, имя - значение)
    
    TrieSetString
(g_t_bans,s_ip,s_name)
    
    
// Записываем новый бан в файл
    
    write_file
("internet_protocol.txt",s_buffer,-1)
    
    
// Выводим надпись с содержание "игрок забанен"
        
    client_print
(0,print_chat,"Player %s is banned",s_name)
    
    
// Получаем userid игрока
        
    new i_userid
=get_user_userid(i_victim)
    
    
// Выкидываем его с сервера
    
    server_cmd
("kick #%d You are banned!",i_userid)
    
    return PLUGIN_HANDLED
}
Аватара пользователя
creator_52
 
Сообщения: 513
Зарегистрирован: 02 мар 2011, 15:45
Откуда: Нижний Новгород
Благодарил (а): 116 раз.
Поблагодарили: 207 раз.
Опыт программирования: Больше трех лет

Re: Массивы (Array и Trie)

Сообщение CL0NE » 08 фев 2012, 16:56

К слову, весьма неплохо о Trie рассказано Вы должны зарегистрироваться, чтобы видеть ссылки.
OMG, что стряслось с amx-x.ru за 4 года?

[align=right]Флудер[/align]
Аватара пользователя
CL0NE
 
Сообщения: 16
Зарегистрирован: 09 июн 2010, 19:59
Откуда: UA-IX
Благодарил (а): 21 раз.
Поблагодарили: 5 раз.
Языки программирования: HTML за еду

Re: Массивы (Array и Trie)

Сообщение Mon[str] » 28 май 2012, 16:30

Возможна ли утечка памяти если не разрушить массив?
Аватара пользователя
Mon[str]
 
Сообщения: 1166
Зарегистрирован: 26 июл 2011, 12:12
Откуда: Россия -> Иркутская область
Благодарил (а): 99 раз.
Поблагодарили: 273 раз.
Опыт программирования: Около года
Языки программирования: Counter-Strike 1.6
C++

Re: Массивы (Array и Trie)

Сообщение DJ_WEST » 30 май 2012, 16:55

Они по-мойму сами закрываются, точно не скажу, надо смотреть.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Массивы (Array и Trie)

Сообщение Lt.RAT » 30 май 2012, 17:42

Mon[str] писал(а):Возможна ли утечка памяти если не разрушить массив?

После смены карты сам уничтожается.
Аватара пользователя
Lt.RAT
 
Сообщения: 301
Зарегистрирован: 30 сен 2009, 01:44
Благодарил (а): 4 раз.
Поблагодарили: 151 раз.
Языки программирования: Counter-Strike 1.6

Re: Массивы (Array и Trie)

Сообщение zippel » 22 ноя 2012, 06:25

нужна функция которая будет обрезать длинные ники у игроков, пускай макс. символов будет 13, а ник игрока например 30. Надо что бы его автоматически обрезало до 13. Знаю что это делается с помощью массивов, прощу помочь мне в этом.
Аватара пользователя
zippel
 
Сообщения: 178
Зарегистрирован: 03 апр 2011, 20:01
Благодарил (а): 33 раз.
Поблагодарили: 1 раз.
Опыт программирования: Больше трех лет
Языки программирования: Java, C++

Re: Массивы (Array и Trie)

Сообщение Asmodai » 22 ноя 2012, 09:42

zippel писал(а):нужна функция которая будет обрезать длинные ники у игроков, пускай макс. символов будет 13, а ник игрока например 30. Надо что бы его автоматически обрезало до 13. Знаю что это делается с помощью массивов, прощу помочь мне в этом.

nick[13] = '^0'
Аватара пользователя
Asmodai
Адмирал
 
Сообщения: 466
Зарегистрирован: 24 фев 2011, 20:48
Благодарил (а): 0 раз.
Поблагодарили: 393 раз.
Языки программирования: Counter-Strike 1.6

Re: Массивы (Array и Trie)

Сообщение zippel » 25 ноя 2012, 08:33

Asmodai писал(а):nick[13] = '^0'

это надо использовать с infochanged ?
Чет я не могу въехать, я понимаю что создается массив (строковый), что такой массив всегда заканчивается на символом 0. Мне кажется тут не хватает еще кода?
Аватара пользователя
zippel
 
Сообщения: 178
Зарегистрирован: 03 апр 2011, 20:01
Благодарил (а): 33 раз.
Поблагодарили: 1 раз.
Опыт программирования: Больше трех лет
Языки программирования: Java, C++

Пред.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8