PDA

Просмотр полной версии : [Вопрос] Обычный подсчет или автоподсчет ячеек



DmitriyVasilev
03.03.2019, 11:33
Здравствуйте, можно узнать?
можно ли везде использовать автоподсчёт от Corteza а когда лучше будет просто использовать ручной подсчет.
И объясните каким образом тут подсчитаны ячейки, спасибо огромное!
new string[29+(-2+10)+1];
format(string, sizeof string, "С 01.01.1970 прошло %d секунд", gettime());
SendClientMessageToAll(-1, string);

DeimoS
03.03.2019, 12:51
Можно, конечно, но во многих случаях код подсчёта может занимать гораздо больше места, чем сама функция, в которой будет выводиться сообщение. То бишь, в определённых случаях гораздо практичнее подсчитать вручную, ибо код будет более компактным и опрятным. Но если тебя устраивает "раздутость" с автоподсчётом - можешь пользоваться им. Хуже в плане производительности от этого не будет.


И объясните каким образом тут подсчитаны ячейки, спасибо огромное!
new string[29+(-2+10)+1];
format(string, sizeof string, "С 01.01.1970 прошло %d секунд", gettime());
SendClientMessageToAll(-1, string);

"29" - это число символов в изначальной строке -> "С 01.01.1970 прошло %d секунд"
"-2" - это учёт заполнителя "%d" (заполнители при форматировании заменяются на данные, которые передаются в строку (в данном случае это значение gettime) => нам не нужно учитывать эти 2 символа при подсчёте)
"10" - это максимальное количество символов, которые могут быть возвращены функцией "gettime()"
Функция возвращает число. Максимально возможное число, которое можно хранить в 32-разрядной системе - "2147483647" (https://ru.wikipedia.org/wiki/%D0%A6%D0%B5%D0%BB%D0%BE%D0%B5_(%D1%82%D0%B8%D0%BF_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85)). В данном числе как раз 10 символов. Отсюда и число "10".
Если бы ты, например, выводил ник игрока в строку, то указывать следовало бы "MAX_PLAYER_NAME" иди "24" (но лучше указать именно макрос, дабы если в будущем максимальная длина ника изменится разработчиком, то не пришлось бы изменять вручную все формулы). Ну а если, например, ID игрока, то указать следует 3 символа (максимальный ID игрока - 999). То бишь, чтоб подсчитать размер входящих в строку данных, тебе нужно представить эти данные в максимально возможном их виде, а после подсчитать количество символов для хранения этого "максимального" варианта.
"+1" в конце - это учёт нуль-символа

Вообще формулу можно составлять по всякому. Я, например, предпочитаю не прописывать явно вычет заполнителя (те самые "-2"), а учитывать их сразу при подсчёте длины строки. То бишь, я бы написал сразу "27" вместо "29" и формула у меня выглядела бы так

new string[27+10+1];

Не принципиально как ты будешь составлять формулы (хотя предпочтительнее делать это по какому-то общему шаблону, чтоб в будущем, если появится нужда изменить строку и пересчитать её длину, это можно было сделать с лёгкостью, изменив лишь часть формулы, а не пересчитывая её по новой). При желании, можешь вообще не составлять формулу, а сразу писать готовое число (но тогда, в случае изменения строки, его придётся пересчитывать по новой), а-ля:

new string[38];//27+10+1 = 38

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


Можно, конечно, но во многих случаях код подсчёта может занимать гораздо больше места, чем сама функция, в которой будет выводиться сообщение.

Например, так команда выглядела с автопосчётом:
CMD:getcord(playerid, params[]) // by Daniel_Cortez
{
if(PlayerInfo[playerid][pAdmin] < 1)
return 1;
static const
fmt_str0[] = "Координаты: X = %8.2f, Y = %8.2f, Z = %8.2f",
fmt_str1[] = "Угол поворота: %8.2f°",
fmt_str2[] = "Интерьер: %d, вирт. мир: %d";
const
size0 = sizeof(fmt_str0)+(-5+11)*3,
size1 = sizeof(fmt_str1)-5+11,
size2 = sizeof(fmt_str2)+(-2+11)*2;
#if size0>size1
#define size size0
#else
#define size size1
#endif
#if size2>size
#undef size
#define size size2
#endif
new string[size];
#undef size
{
new Float:x, Float:y, Float:z;
GetPlayerPos(playerid, x, y, z);
format(string, sizeof(string), fmt_str0, x, y, z);
}
SendClientMessage(playerid, -1, string);
{
new Float:f;
GetPlayerFacingAngle(playerid, f);
format(string, sizeof(string), fmt_str1, f);
}
SendClientMessage(playerid, -1, string);
new
i = GetPlayerInterior(playerid),
w = GetPlayerVirtualWorld(playerid);
format(string, sizeof(string), fmt_str2, i, w);
return SendClientMessage(playerid, -1, string);
}

А так она выглядит сейчас (http://pro-pawn.ru/showthread.php?5738-getpos-setpos-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BA%D0%BE%D0%BE%D1%80%D0%B4%D0%B8%D0%BD%D0%B0%D1%82%D0%B0%D0%BC%D0%B8):
CMD:getpos(playerid, params[]) // by Daniel_Cortez \ pro-pawn.ru
{
// Проверка на админа (если нужно, замените на свою).
if (PlayerInfo[playerid][pAdmin] < 1)
return 1;

new string[62];
static Float:x, Float:y, Float:z, Float:f, i, w;
GetPlayerPos(playerid, x, y, z);
format(string, sizeof(string), "Координаты: X = %8.2f, Y = %8.2f, Z = %8.2f", x, y, z);
SendClientMessage(playerid, -1, string);

GetPlayerFacingAngle(playerid, f);
format(string, sizeof(string), "Угол поворота: %8.2f°", f);
SendClientMessage(playerid, -1, string);

i = GetPlayerInterior(playerid);
w = GetPlayerVirtualWorld(playerid);
format(string, sizeof(string), "Интерьер: %d, вирт. мир: %d", i, w);
return SendClientMessage(playerid, -1, string);
}

Там, конечно, помимо отказа от автоподсчёта, есть ещё некоторые изменения, но, в целом, видно, что в данном случае автоподсчёт только "раздувал" код команды. В итоге, если такой автоподсчёт использовать повсеместно, что приличный процент кода будет занимать только этот самый автоподсчёт. А чем больше кода, тем труднее его поддерживать, ибо, как минимум, приходится дольше искать тот или иной участок кода. Вот тут (http://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8&p=84685&viewfull=1#post84685) я ещё несколько "проблемных мест", по моему мнению, описывал касаемо автоподсчёта.

В целом, лично я так и не нашёл применение для автоподсчёта. Для меня гораздо практичнее и быстрее использовать функционал редактора кода, который подсчитывает выделенный текст
https://i.imgur.com/Enx7np6.png (https://i.imgur.com/Enx7np6.png)
дабы получившееся значение в дальнейшем использовать при составлении формулы (как показал в предыдущем сообщении). Но это ни в коем случае не призыв к отказу от автоподсчёта. Используй то, что тебе удобнее. Главное научись правильно составлять формулу, ибо иначе от этого может быть больше проблем, чем пользы.

DmitriyVasilev
03.03.2019, 13:51
а куда ответ ваш делся

DeimoS
03.03.2019, 14:04
Эмм, он на месте. Вот:

Можно, конечно, но во многих случаях код подсчёта может занимать гораздо больше места, чем сама функция, в которой будет выводиться сообщение. То бишь, в определённых случаях гораздо практичнее подсчитать вручную, ибо код будет более компактным и опрятным. Но если тебя устраивает "раздутость" с автоподсчётом - можешь пользоваться им. Хуже в плане производительности от этого не будет.


И объясните каким образом тут подсчитаны ячейки, спасибо огромное!
new string[29+(-2+10)+1];
format(string, sizeof string, "С 01.01.1970 прошло %d секунд", gettime());
SendClientMessageToAll(-1, string);

"29" - это число символов в изначальной строке -> "С 01.01.1970 прошло %d секунд"
"-2" - это учёт заполнителя "%d" (заполнители при форматировании заменяются на данные, которые передаются в строку (в данном случае это значение gettime) => нам не нужно учитывать эти 2 символа при подсчёте)
"10" - это максимальное количество символов, которые могут быть возвращены функцией "gettime()"
Функция возвращает число. Максимально возможное число, которое можно хранить в 32-разрядной системе - "2147483647" (https://ru.wikipedia.org/wiki/%D0%A6%D0%B5%D0%BB%D0%BE%D0%B5_(%D1%82%D0%B8%D0%BF_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85)). В данном числе как раз 10 символов. Отсюда и число "10".
Если бы ты, например, выводил ник игрока в строку, то указывать следовало бы "MAX_PLAYER_NAME" иди "24" (но лучше указать именно макрос, дабы если в будущем максимальная длина ника изменится разработчиком, то не пришлось бы изменять вручную все формулы). Ну а если, например, ID игрока, то указать следует 3 символа (максимальный ID игрока - 999). То бишь, чтоб подсчитать размер входящих в строку данных, тебе нужно представить эти данные в максимально возможном их виде, а после подсчитать количество символов для хранения этого "максимального" варианта.
"+1" в конце - это учёт нуль-символа

Вообще формулу можно составлять по всякому. Я, например, предпочитаю не прописывать явно вычет заполнителя (те самые "-2"), а учитывать их сразу при подсчёте длины строки. То бишь, я бы написал сразу "27" вместо "29" и формула у меня выглядела бы так

new string[27+10+1];

Не принципиально как ты будешь составлять формулы (хотя предпочтительнее делать это по какому-то общему шаблону, чтоб в будущем, если появится нужда изменить строку и пересчитать её длину, это можно было сделать с лёгкостью, изменив лишь часть формулы, а не пересчитывая её по новой). При желании, можешь вообще не составлять формулу, а сразу писать готовое число (но тогда, в случае изменения строки, его придётся пересчитывать по новой), а-ля:

new string[38];//27+10+1 = 38

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


Можно, конечно, но во многих случаях код подсчёта может занимать гораздо больше места, чем сама функция, в которой будет выводиться сообщение.

Например, так команда выглядела с автопосчётом:
CMD:getcord(playerid, params[]) // by Daniel_Cortez
{
if(PlayerInfo[playerid][pAdmin] < 1)
return 1;
static const
fmt_str0[] = "Координаты: X = %8.2f, Y = %8.2f, Z = %8.2f",
fmt_str1[] = "Угол поворота: %8.2f°",
fmt_str2[] = "Интерьер: %d, вирт. мир: %d";
const
size0 = sizeof(fmt_str0)+(-5+11)*3,
size1 = sizeof(fmt_str1)-5+11,
size2 = sizeof(fmt_str2)+(-2+11)*2;
#if size0>size1
#define size size0
#else
#define size size1
#endif
#if size2>size
#undef size
#define size size2
#endif
new string[size];
#undef size
{
new Float:x, Float:y, Float:z;
GetPlayerPos(playerid, x, y, z);
format(string, sizeof(string), fmt_str0, x, y, z);
}
SendClientMessage(playerid, -1, string);
{
new Float:f;
GetPlayerFacingAngle(playerid, f);
format(string, sizeof(string), fmt_str1, f);
}
SendClientMessage(playerid, -1, string);
new
i = GetPlayerInterior(playerid),
w = GetPlayerVirtualWorld(playerid);
format(string, sizeof(string), fmt_str2, i, w);
return SendClientMessage(playerid, -1, string);
}

А так она выглядит сейчас (http://pro-pawn.ru/showthread.php?5738-getpos-setpos-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BA%D0%BE%D0%BE%D1%80%D0%B4%D0%B8%D0%BD%D0%B0%D1%82%D0%B0%D0%BC%D0%B8):
CMD:getpos(playerid, params[]) // by Daniel_Cortez \ pro-pawn.ru
{
// Проверка на админа (если нужно, замените на свою).
if (PlayerInfo[playerid][pAdmin] < 1)
return 1;

new string[62];
static Float:x, Float:y, Float:z, Float:f, i, w;
GetPlayerPos(playerid, x, y, z);
format(string, sizeof(string), "Координаты: X = %8.2f, Y = %8.2f, Z = %8.2f", x, y, z);
SendClientMessage(playerid, -1, string);

GetPlayerFacingAngle(playerid, f);
format(string, sizeof(string), "Угол поворота: %8.2f°", f);
SendClientMessage(playerid, -1, string);

i = GetPlayerInterior(playerid);
w = GetPlayerVirtualWorld(playerid);
format(string, sizeof(string), "Интерьер: %d, вирт. мир: %d", i, w);
return SendClientMessage(playerid, -1, string);
}

Там, конечно, помимо отказа от автоподсчёта, есть ещё некоторые изменения, но, в целом, видно, что в данном случае автоподсчёт только "раздувал" код команды. В итоге, если такой автоподсчёт использовать повсеместно, что приличный процент кода будет занимать только этот самый автоподсчёт. А чем больше кода, тем труднее его поддерживать, ибо, как минимум, приходится дольше искать тот или иной участок кода. Вот тут (http://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8&p=84685&viewfull=1#post84685) я ещё несколько "проблемных мест", по моему мнению, описывал касаемо автоподсчёта.

В целом, лично я так и не нашёл применение для автоподсчёта. Для меня гораздо практичнее и быстрее использовать функционал редактора кода, который подсчитывает выделенный текст
https://i.imgur.com/Enx7np6.png (https://i.imgur.com/Enx7np6.png)
дабы получившееся значение в дальнейшем использовать при составлении формулы (как показал в предыдущем сообщении). Но это ни в коем случае не призыв к отказу от автоподсчёта. Используй то, что тебе удобнее. Главное научись правильно составлять формулу, ибо иначе от этого может быть больше проблем, чем пользы.

DmitriyVasilev
03.03.2019, 14:19
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 128974801 bytes) in /var/www/u0253307/data/www/pro-pawn.ru/includes/functions_threadedmode.php on line 23
мне пишет когда нажимаю на ваш ответ из раздела форум, а здесь только мои сообщения

DmitriyVasilev
03.03.2019, 16:36
я правильно сосчитал?
new bandprotect[24], bandattack[24];
switch(GZInfo[i][gFrakVlad])
{
case 12: bandprotect="Ballas";
case 13: bandprotect="Vagos";
case 15: bandprotect="Grove";
case 17: bandprotect="Aztecas";
case 18: bandprotect="Rifa";
}
switch(User[playerid][pMember])
{
case 12: bandattack="Ballas";
case 13: bandattack="Vagos";
case 15: bandattack="Grove";
case 17: bandattack="Aztecas";
case 18: bandattack="Rifa";
}
new fmt_str[(27 - 4) + ( 48 + 1)];
format(fmt_str,sizeof(fmt_str),"Банда %s напала на банду %s", bandattack, bandprotect);
и
if(IsAGunsCar(newcar))
{
new fmt_str[16 + ( -2 + 11 ) + 1];
format(fmt_str, sizeof(fmt_str), "Оружия: %i/10000", MatHaul[newcar-gunscar[0]][mLoad],MatHaul[newcar-gunscar[0]][mCapasity]);
SCM(playerid, TEAM_GROVE_COLOR, fmt_str);
SCM(playerid, -1, !"(( Для загрузки/разгрузки Оружия Введите: /carm ))");
}

DeimoS
03.03.2019, 16:56
Скобки расставлены довольно странно, но в остальном - да, правильно.
Обычно скобками отделяют вычисление для разных данных. В твоём случае было бы как-то так:

new fmt_str[27+(-2+sizeof(bandprotect))+(-2+sizeof(bandattack))+1];
То бишь, отдельно размер строки без учёта входящих данных и отдельно вычисление для каждого заполнителя. В таком случае, если ты, например, решишь убрать отображение "bandattack", то тебе достаточно просто удалить первую скобку и не нужно будет ничего пересчитывать. В этом весь смысл такого составления формул :)
Ну и стоит нормально подсчитать размер для bandprotect/bandattack.


Хотя вообще в твоём случае лучше сделать так:
static const band_list[][] =// Зарезервируем переменную сразу в сегменте данных, дабы при каждом вызове кода не заниматься извлечением данных в стэк
{
"Ballas", // 12 ID | 0 ячейка
"Vagos", // 13 ID | 1 ячейка
"Grove", // 15 ID | 2 ячейка
"Aztecas", // 17 ID | 3 ячейка
"Rifa" // 18 ID | 4 ячейка
};

//Далее сопоставим ID фракций номеру ячеек в массиве.
new protect_idx;
switch(GZInfo[i][gFrakVlad])
{
case 12: protect_idx = 0;
case 13: protect_idx = 1;
case 15: protect_idx = 2;
case 17: protect_idx = 3;
case 18: protect_idx = 4;
}

new attack_idx;
switch(User[playerid][pMember])
{
case 12: attack_idx = 0;
case 13: attack_idx = 1;
case 15: attack_idx = 2;
case 17: attack_idx = 3;
case 18: attack_idx = 4;
}

new fmt_str[27+ (-2+sizeof(band_list[])) + (-2+sizeof(band_list[])) +1];
format(fmt_str,sizeof(fmt_str),"Банда %s напала на банду %s", band_list[attack_idx], band_list[protect_idx]);// Получим нназвание банд из массива согласно полученному номеру ячейки

DmitriyVasilev
03.03.2019, 20:29
warning 224: indeterminate array size in "sizeof" expression (symbol "")
это в new fmt_str[27+ (-2+sizeof(band_list[])) + (-2+sizeof(band_list[])) +1];

DeimoS
04.03.2019, 03:21
Ах да, вот тут тоже размер нужно подсчитать, так как массив многомерный и компилятор в данном случае не сможет точный размер второй меры определить для sizeof самостоятельно

static const band_list[5][8] =// Зарезервируем переменную сразу в сегменте данных, дабы при каждом вызове кода не заниматься извлечением данных в стэк
{
"Ballas", // 12 ID | 0 ячейка
"Vagos", // 13 ID | 1 ячейка
"Grove", // 15 ID | 2 ячейка
"Aztecas", // 17 ID | 3 ячейка
"Rifa" // 18 ID | 4 ячейка
};