Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 6 из 6
  1. #1
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±

    Почему не записывается текст в многомерный массив?

    Не могу понять, почему не записывает в массив.

    PHP код:
    enum RecentPlayerAction
    {
        
    RPC_act_1[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_2[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_3[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_4[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_5[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_6[MAX_CHATBUBBLE_LENGTH 1],
        
    RPC_act_7[MAX_CHATBUBBLE_LENGTH 1]
    }

    new
        
    gRecentPlayerAction[MAX_PLAYERS][RecentPlayerAction],
        
    NULL_gRecentPlayerAction[RecentPlayerAction]

    При входе обнуляю

    PHP код:
    gRecentPlayerAction[playerid] = NULL_gRecentPlayerAction
    Сама запись:

    PHP код:
    stock AddRecentPlayerAction(playerid, const string[])
    {
        if(
    strlen(string) > MAX_CHATBUBBLE_LENGTH)
            return 
    0;
            
        for(new 
    sizeof(gRecentPlayerAction[]), 01;)
        {
             
    gRecentPlayerAction[playerid][RecentPlayerAction:i] = gRecentPlayerAction[playerid][RecentPlayerAction:++i];
        }
        
        new
            
    h_m_s_;
            
        
    gettime(h_m_s_);
        
        
    format(stringersizeof stringer"[%2d:%2d:%2d] %s",
            
    h_m_s_string);
            
        
    strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer0MAX_CHATBUBBLE_LENGTH);
        
        return 
    1;

    (Проверял длину, не выходит за пределы MAX_CHATUBBLE_LENGTH)

  2. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Потому что ты не указал размер массива gRecentPlayerAction, а указал лишь размер строки.
    1. strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer, 0, MAX_CHATBUBBLE_LENGTH, MAX_CHATBUBBLE_LENGTH);

    sizeof не умеет определять размер отдельного члена перечисления в многомерном массиве, из-за чего на месте размера массива оказывается 0, в результате чего данные и не записываются. Это относится ко всем функциям, работающим со строками (всегда, когда нужно работать с многомерными массивами, размер массива указывай явно, если того требует функция).

     Замечания по коду
    1. for(new j = sizeof(gRecentPlayerAction[]), i = 0; i < j - 1;)

    Крайне странный цикл. Если "j" используется только в условии, гораздо практичнее делать так:
    1. for(new i = 0; i < sizeof(gRecentPlayerAction[]) - 1;)

    Ибо в твоём текущем варианте цикл каждую итерацию будет обращаться к переменной j, отнимать от неё единицу и только потом сравнивать, а в варианте с sizeof размер массива подставится на этапе компиляции и сравнение в цикле будет происходить с обычным числом, без всяких расчётов.




    1. new
    2. h_, m_, s_;
    3.  
    4. gettime(h_, m_, s_);
    5.  
    6. format(stringer, sizeof stringer, "[%2d:%2d:%2d] %s",
    7. h_, m_, s_, string);
    8.  
    9. strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer, 0, MAX_CHATBUBBLE_LENGTH);


    Почему вот тут сразу не записать текст в массив gRecentPlayerAction? Зачем тут stringer?
    1. new
    2. h_, m_, s_;
    3.  
    4. gettime(h_, m_, s_);
    5.  
    6. format(gRecentPlayerAction[playerid][RecentPlayerAction:0], MAX_CHATBUBBLE_LENGTH+1, "[%2d:%2d:%2d] %s",
    7. h_, m_, s_, string);





    Чтоб не мучиться с тегами при работе с перечислением, можно сделать так:
    1. enum _:RecentPlayerAction
    2. {
    3. RPC_act_1[MAX_CHATBUBBLE_LENGTH + 1],
    4. RPC_act_2[MAX_CHATBUBBLE_LENGTH + 1],
    5. RPC_act_3[MAX_CHATBUBBLE_LENGTH + 1],
    6. RPC_act_4[MAX_CHATBUBBLE_LENGTH + 1],
    7. RPC_act_5[MAX_CHATBUBBLE_LENGTH + 1],
    8. RPC_act_6[MAX_CHATBUBBLE_LENGTH + 1],
    9. RPC_act_7[MAX_CHATBUBBLE_LENGTH + 1]
    10. }

    Тогда не нужно будет указывать "RecentPlayerAction:" в случаях, когда обращаешься к ячейкам массива, а не членам перечисления


    А что это вообще за система? Какое предназначение цикла внутри функции? Не особо похоже, что твой код будет работать так, как ты задумал, если судить по тому, как ты объявил массив и как потом с ним работаешь.
    Последний раз редактировалось DeimoS; 06.06.2019 в 12:59.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  3. #3
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Ибо в твоём текущем варианте цикл каждую итерацию будет обращаться к переменной j, отнимать от неё единицу и только потом сравнивать, а в варианте с sizeof размер массива подставится на этапе компиляции и сравнение в цикле будет происходить с обычным числом, без всяких расчётов.
    Согласен, многие изменения вносились и не заметил.

    Цитата Сообщение от DeimoS Посмотреть сообщение
    А что это вообще за система? Какое предназначение цикла внутри функции? Не особо похоже, что твой код будет работать так, как ты задумал, если судить по тому, как ты объявил массив и как потом с ним работаешь.
    Записывать последние действия игрока. Благодарю за помощь

    UPD: Но почему-то всё равно не записывает
    Последний раз редактировалось execution; 06.06.2019 в 15:33.

  4. #4
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Потому что ты неправильно записываешь данные? Точнее, не понимаешь как работают перечисления (enum).

    В текущем виде:
    PHP код:
    enum RecentPlayerAction 

        
    RPC_act_1[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_2[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_3[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_4[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_5[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_6[MAX_CHATBUBBLE_LENGTH 1], 
        
    RPC_act_7[MAX_CHATBUBBLE_LENGTH 1


    new 
        
    gRecentPlayerAction[MAX_PLAYERS][RecentPlayerAction]; 
    Твой массив будет равносилен такой записи:
    PHP код:
    new 
        
    gRecentPlayerAction[MAX_PLAYERS][1015]; 
    А не такой:
    PHP код:
    new 
        
    gRecentPlayerAction[MAX_PLAYERS][7][MAX_CHATBUBBLE_LENGTH 1]; 
    И твой текущий цикл, во-первых, сам по себе работает неправильно, ибо ты значение следующей ячейки записываешь в текущую, а, во-вторых, будет смещать символы на одну ячейку вперёд, а не на "MAX_CHATBUBBLE_LENGTH + 1" ячеек, из-за чего следующая запись текста перезапишет весь прошлый текст.
    В общем, тебе нужно разобраться с тем, как работают enum =)




    Как-то так должно быть. Но не проверял
    1. #define MAX_RECENT_PLAYER_ACTION 7
    2.  
    3. new gRecentPlayerAction[MAX_PLAYERS][MAX_RECENT_PLAYER_ACTION][MAX_CHATBUBBLE_LENGTH + 1];
    4. new NULL_gRecentPlayerAction[MAX_CHATBUBBLE_LENGTH + 1];
    5.  
    6. stock ClearRecentPlayerAction(playerid)
    7. {
    8. for(new i; i < MAX_RECENT_PLAYER_ACTION; i++)
    9. gRecentPlayerAction[playerid][i] = NULL_gRecentPlayerAction;
    10. }
    11.  
    12. stock GetRecentPlayerAction(playerid, actionid)
    13. {
    14. return gRecentPlayerAction[playerid][actionid];
    15. }
    16.  
    17.  
    18. stock AddRecentPlayerAction(playerid, const string[])
    19. {
    20. for(new i = MAX_RECENT_PLAYER_ACTION-1; i != 0; i--)
    21. {
    22. if(isnull(gRecentPlayerAction[playerid][i-1]))
    23. continue;
    24. gRecentPlayerAction[playerid][i] = gRecentPlayerAction[playerid][i-1];
    25. }
    26.  
    27. new h_, m_, s_;
    28. gettime(h_, m_, s_);
    29. format(gRecentPlayerAction[playerid][0], MAX_CHATBUBBLE_LENGTH, "[%2d:%2d:%2d] %s",
    30. h_, m_, s_, string);
    31. return 1;
    32. }


    - - - Добавлено - - -

    А вот тебе функция определения последней занятой ячейки:
    1. stock GetRecentPlayerActionLastID(playerid)
    2. {
    3. for(new i = MAX_RECENT_PLAYER_ACTION-1; i != 0; i--)
    4. {
    5. if(isnull(gRecentPlayerAction[playerid][i]))
    6. continue;
    7. return i;
    8. }
    9. return 0;
    10. }


    Использовать так:
    1. for(new i, j = GetRecentPlayerActionLastID(playerid); i <= j; i++)
    2. {
    3. print(GetRecentPlayerAction(playerid, i));
    4. }
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  5. #5
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±
    Понятно. Думал обойтись очищение массива без цикла, но увы. Спасибо ещё раз.

  6. #6
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Там всего 7 итераций. Можешь обойтись без цикла
    PHP код:
    new gRecentPlayerAction[MAX_PLAYERS][MAX_RECENT_PLAYER_ACTION][MAX_CHATBUBBLE_LENGTH 1];
    new 
    NULL_gRecentPlayerAction[MAX_RECENT_PLAYER_ACTION][MAX_CHATBUBBLE_LENGTH 1];

    stock ClearRecentPlayerAction(playerid)
    {
        
    gRecentPlayerAction[playerid] = NULL_gRecentPlayerAction;

    но,как видишь, приходится в 7 раз больше памяти выделять. Не думаю, что избавление от цикла на 7 итераций стоит того. Вот если бы было хотя бы 1000 итераций и больше + очищение нужно было бы делать часто, тогда можно задуматься.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •