Просмотр полной версии : [Вопрос] Почему не записывается текст в многомерный массив?
execution
06.06.2019, 12:03
Не могу понять, почему не записывает в массив.
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]
;
При входе обнуляю
gRecentPlayerAction[playerid] = NULL_gRecentPlayerAction;
Сама запись:
stock AddRecentPlayerAction(playerid, const string[])
{
if(strlen(string) > MAX_CHATBUBBLE_LENGTH)
return 0;
for(new j = sizeof(gRecentPlayerAction[]), i = 0; i < j - 1;)
{
gRecentPlayerAction[playerid][RecentPlayerAction:i] = gRecentPlayerAction[playerid][RecentPlayerAction:++i];
}
new
h_, m_, s_;
gettime(h_, m_, s_);
format(stringer, sizeof stringer, "[%2d:%2d:%2d] %s",
h_, m_, s_, string);
strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer, 0, MAX_CHATBUBBLE_LENGTH);
return 1;
}
(Проверял длину, не выходит за пределы MAX_CHATUBBLE_LENGTH)
Потому что ты не указал размер массива gRecentPlayerAction, а указал лишь размер строки.
strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer, 0, MAX_CHATBUBBLE_LENGTH, MAX_CHATBUBBLE_LENGTH);
sizeof не умеет определять размер отдельного члена перечисления в многомерном массиве, из-за чего на месте размера массива оказывается 0, в результате чего данные и не записываются. Это относится ко всем функциям, работающим со строками (всегда, когда нужно работать с многомерными массивами, размер массива указывай явно, если того требует функция).
for(new j = sizeof(gRecentPlayerAction[]), i = 0; i < j - 1;)
Крайне странный цикл. Если "j" используется только в условии, гораздо практичнее делать так:
for(new i = 0; i < sizeof(gRecentPlayerAction[]) - 1;)
Ибо в твоём текущем варианте цикл каждую итерацию будет обращаться к переменной j, отнимать от неё единицу и только потом сравнивать, а в варианте с sizeof размер массива подставится на этапе компиляции и сравнение в цикле будет происходить с обычным числом, без всяких расчётов.
new
h_, m_, s_;
gettime(h_, m_, s_);
format(stringer, sizeof stringer, "[%2d:%2d:%2d] %s",
h_, m_, s_, string);
strmid(gRecentPlayerAction[playerid][RecentPlayerAction:0], stringer, 0, MAX_CHATBUBBLE_LENGTH);
Почему вот тут сразу не записать текст в массив gRecentPlayerAction? Зачем тут stringer?
new
h_, m_, s_;
gettime(h_, m_, s_);
format(gRecentPlayerAction[playerid][RecentPlayerAction:0], MAX_CHATBUBBLE_LENGTH+1, "[%2d:%2d:%2d] %s",
h_, m_, s_, string);
Чтоб не мучиться с тегами при работе с перечислением, можно сделать так:
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]
}
Тогда не нужно будет указывать "RecentPlayerAction:" в случаях, когда обращаешься к ячейкам массива, а не членам перечисления
А что это вообще за система? Какое предназначение цикла внутри функции? Не особо похоже, что твой код будет работать так, как ты задумал, если судить по тому, как ты объявил массив и как потом с ним работаешь.
execution
06.06.2019, 15:06
Ибо в твоём текущем варианте цикл каждую итерацию будет обращаться к переменной j, отнимать от неё единицу и только потом сравнивать, а в варианте с sizeof размер массива подставится на этапе компиляции и сравнение в цикле будет происходить с обычным числом, без всяких расчётов.
Согласен, многие изменения вносились и не заметил.
А что это вообще за система? Какое предназначение цикла внутри функции? Не особо похоже, что твой код будет работать так, как ты задумал, если судить по тому, как ты объявил массив и как потом с ним работаешь.
Записывать последние действия игрока. Благодарю за помощь :thank_you:
UPD: Но почему-то всё равно не записывает :search:
Потому что ты неправильно записываешь данные? Точнее, не понимаешь как работают перечисления (enum).
В текущем виде:
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];
Твой массив будет равносилен такой записи:
new
gRecentPlayerAction[MAX_PLAYERS][1015];
А не такой:
new
gRecentPlayerAction[MAX_PLAYERS][7][MAX_CHATBUBBLE_LENGTH + 1];
И твой текущий цикл, во-первых, сам по себе работает неправильно, ибо ты значение следующей ячейки записываешь в текущую, а, во-вторых, будет смещать символы на одну ячейку вперёд, а не на "MAX_CHATBUBBLE_LENGTH + 1" ячеек, из-за чего следующая запись текста перезапишет весь прошлый текст.
В общем, тебе нужно разобраться с тем, как работают enum =)
Как-то так должно быть. Но не проверял
#define MAX_RECENT_PLAYER_ACTION 7
new gRecentPlayerAction[MAX_PLAYERS][MAX_RECENT_PLAYER_ACTION][MAX_CHATBUBBLE_LENGTH + 1];
new NULL_gRecentPlayerAction[MAX_CHATBUBBLE_LENGTH + 1];
stock ClearRecentPlayerAction(playerid)
{
for(new i; i < MAX_RECENT_PLAYER_ACTION; i++)
gRecentPlayerAction[playerid][i] = NULL_gRecentPlayerAction;
}
stock GetRecentPlayerAction(playerid, actionid)
{
return gRecentPlayerAction[playerid][actionid];
}
stock AddRecentPlayerAction(playerid, const string[])
{
for(new i = MAX_RECENT_PLAYER_ACTION-1; i != 0; i--)
{
if(isnull(gRecentPlayerAction[playerid][i-1]))
continue;
gRecentPlayerAction[playerid][i] = gRecentPlayerAction[playerid][i-1];
}
new h_, m_, s_;
gettime(h_, m_, s_);
format(gRecentPlayerAction[playerid][0], MAX_CHATBUBBLE_LENGTH, "[%2d:%2d:%2d] %s",
h_, m_, s_, string);
return 1;
}
- - - Добавлено - - -
А вот тебе функция определения последней занятой ячейки:
stock GetRecentPlayerActionLastID(playerid)
{
for(new i = MAX_RECENT_PLAYER_ACTION-1; i != 0; i--)
{
if(isnull(gRecentPlayerAction[playerid][i]))
continue;
return i;
}
return 0;
}
Использовать так:
for(new i, j = GetRecentPlayerActionLastID(playerid); i <= j; i++)
{
print(GetRecentPlayerAction(playerid, i));
}
execution
06.06.2019, 16:12
Понятно. Думал обойтись очищение массива без цикла, но увы. Спасибо ещё раз.
Там всего 7 итераций. Можешь обойтись без цикла
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 итераций и больше + очищение нужно было бы делать часто, тогда можно задуматься.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot