PDA

Просмотр полной версии : [Function] IsRPNick - проверка на RP-ник



Daniel_Cortez
02.03.2014, 20:39
Функция была сделана давно на основе варианта от frog163, но была изменена для повышения быстродействия и, в конце концов, стала почти не похожа на оригинал.

stock bool:IsRPNick(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static i, __;
if ('A' <= name[0] <= 'Z' && 'a' <= name[1] <= 'z')
{
for (i = 1, __ = 0;;)
{
switch (name[++i])
{
case 'a'..'z':
continue;
case '_':
if (__++, 'A' <= name[++i] <= 'Z' && 'a' <= name[++i] <= 'z')
continue;
else
break;
case '\0':
return (i >= 4 && __ == 1);
default:
return false;
}
}
}
return false;
}

Также есть улучшенная реализация с использованием оператора emit (http://pro-pawn.ru/showthread.php?15830). Работает в ~1.6 (~2.1 с JIT) раза быстрее обычной реализации, но требует версию компилятора 3.10.5+.

stock bool:IsRPNick(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static num_underscores, ptr;
emit
{
load.s.pri name
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.s.pri name
add.c (cellbits / charbits)
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsgrtr ret_false
zero num_underscores
load.s.pri name
add.c (cellbits / charbits * 2)
jump loop_entry
loop:
load.pri ptr
add.c (cellbits / charbits)
loop_entry:
stor.pri ptr
load.i
const.alt 'a'
jsless is_underscore
const.alt 'z'
jsleq loop
is_underscore:
const.alt '_'
jneq is_term
inc num_underscores
load.pri ptr
add.c (cellbits / charbits)
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.pri ptr
add.c (cellbits / charbits * 2)
stor.pri ptr
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsleq loop
jump ret_false
is_term:
jnz ret_false
load.pri ptr
load.s.alt name
sub
const.alt (cellbits / charbits * 4)
jsless ret_false
load.pri num_underscores
const.alt 1
eq
retn
ret_false:
}
return false;
}


Пример использования:

public OnPlayerConnect(playerid)
{
new name[MAX_PLAYER_NAME+1];
GetPlayerName(playerid, name, sizeof(name));
if (!IsRPNick(name))
{
SendClientMessage(playerid, 0xC04000FF, "Вы были кикнуты за non-RP ник.");
return Kick(playerid);
}
return 1;
}


Автор оригинала: frog163
Доработка: Daniel_Cortez

Salvacore
02.03.2014, 21:24
Отлично,забираю.

Jeff_Monson
03.03.2014, 06:41
Тупой вопрос, а как его использовать?

Jeff_Monson
03.03.2014, 14:33
for(;;++i)
Вроде будет ругаться

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


new.pwn(7461) : error 010: invalid function or declaration

return _:((__ != 0) && (len >= 2));

Jeff_Monson
04.03.2014, 15:50
Есть кто исправит?

Daniel_Cortez
04.03.2014, 16:05
for(;;++i)
Вроде будет ругаться
Вряд ли. В цикле предусмотрен выход (используется break).



new.pwn(7461) : error 010: invalid function or declaration

return _:((__ != 0) && (len >= 2));
Уверен, что нигде в своём моде фигурную скобку не пропустил? Я вчера пробовал воспроизвести ошибку на нескольких модах - всё компилируется без проблем.

В крайнем случае можете исправить строку

return _:((__ != 0) && (len >= 2));
на такой вариант:

return (__ != 0) && (len >= 2);

Jeff_Monson
04.03.2014, 16:09
stock CheckName(playername[])
{
new firstname[10],lastname[10];
if(sscanf(playername,"p<_>s[10]s[10]",firstname,lastname)) return 0;
if(strlen(firstname) < 3) return 0;
if(strlen(lastname) < 3) return 0;
if(!('A' <= firstname[0] <= 'Z')) return 0;
if(!('A' <= lastname[0] <= 'Z')) return 0;
for(new i = 0; i < strlen(lastname); i++)
{
if(i == 0) continue;
if(i < strlen(firstname))
{
if(!('a' <= lastname[i] <= 'z')) return 0;
}
if(i < strlen(lastname))
{
if(!('a' <= lastname[i] <= 'z')) return 0;
}
}
return 1;
}

Как вы думаете код нормальный?

Gressie
15.05.2014, 18:45
Она ловит все нонрп ники?

Salvacore
15.05.2014, 20:00
Она ловит все нонрп ники?
Пробуй.
Никто не мешает :)

vovandolg
13.03.2016, 20:19
А как сделать чтобы под англ и под русские сразу шло?

DeimoS
13.03.2016, 20:37
stock IsRPNick(name[])
{
if (!('A' <= name[0] <= 'Z' || 'А' <= name[0] <= 'Я'))
return 0;
new i = 1, len = 1, __ = 0;
for (; ; ++i)
switch (name[i])
{
case '_':
{
if ((__ != 0) || (len < 2) || !('А' <= name[++i] <= 'Я') && !('A' <= name[i] <= 'Z'))
return 0;
++__, len = 1;
}
case '\0':
break;
case 'a'..'z', 'а'..'я':
++len;
default:
return 0;
}
return _:((__ != 0) && (len >= 2));
}
Попробуй

$continue$
13.03.2016, 20:40
А не легче убрать вообще проверку на символы?

DeimoS
13.03.2016, 20:59
А не легче убрать вообще проверку на символы?

Проверка на РП ник идёт. А на CRMP прикручена поддержка русских символов в нике. Вот он и просит

vovandolg
13.03.2016, 21:27
Да да на SA:MP мне нужно было, всё робит как по маслу с вариантом от DeimoS.
От души.

123
23.07.2016, 08:07
Зачем делать из мода свалку, с кучей подобных функцией? Достаточно использовать регулярные выражения, и любая подобная функция приобретет например такой вид:


#define IsValidRpName(%1) \
regex_match(%1, "([A-Z]{1,1})[a-z]{2,9}+_([A-Z]{1,1})[a-z]{2,9}")

Да и работает это очевидно быстрее, чем все представленные выше варианты.

VVWVV
23.07.2016, 11:24
Зачем делать из мода свалку, с кучей подобных функцией? Достаточно использовать регулярные выражения, и любая подобная функция приобретет например такой вид:


#define IsValidRpName(%1) \
regex_match(%1, "([A-Z]{1,1})[a-z]{2,9}+_([A-Z]{1,1})[a-z]{2,9}")

Да и работает это очевидно быстрее, чем все представленные выше варианты.

Как минимум, для данной функции требуется плагин.

ziggi
23.07.2016, 19:01
Зачем делать из мода свалку, с кучей подобных функцией? Достаточно использовать регулярные выражения, и любая подобная функция приобретет например такой вид:


#define IsValidRpName(%1) \
regex_match(%1, "([A-Z]{1,1})[a-z]{2,9}+_([A-Z]{1,1})[a-z]{2,9}")

Да и работает это очевидно быстрее, чем все представленные выше варианты.

Зачем делать из мода свалку, с кучей подобных регулярных выражений? Достаточно использовать нормальное регулярное выражение, и любое подобное регулярное выражение приобретет например такой вид:


[A-Z][a-z]{2,9}_[A-Z][a-z]{2,9}
Работает точно также, но выражение меньше и проще.

Refraktor
29.03.2017, 22:29
Не понимаю зачем делать переменную с именем __, ведь это усложняет чтение кода и понимание работы.
Также не понял что значит return _:((__ != 0) && (len >= 2));
Именно _: иногда замечаю в кодах, но что значит не гуглится. Кто объяснить может?

ziggi
29.03.2017, 22:46
Не понимаю зачем делать переменную с именем __, ведь это усложняет чтение кода и понимание работы.
Также не понял что значит return _:((__ != 0) && (len >= 2));
Именно _: иногда замечаю в кодах, но что значит не гуглится. Кто объяснить может?

Насчёт имён вида __ согласен, это тяжело читать.

_: - это "сбрасывание" тэга, в принципе, здесь можно и без этого обойтись.

Refraktor
30.03.2017, 14:37
Подробней можно о "сбрасывании" тэга?

VVWVV
30.03.2017, 14:56
Подробней можно о "сбрасывании" тэга?

Очевидно, что данная операция сбрасывает тег. Она помогает только в ситуациях, когда нужно избавиться от предупреждения и/или некоторых зависимостей (например, перегрузка операторов (http://pro-pawn.ru/showthread.php?14747) и т.п.). В компиляторе же тег выражения сбрасывается на значение "публичного" тега.

Например, можно использовать сбрасывание тега в данном участке кода:


if (!('A' <= name[0] <= 'Z'))
return 0;


Т.е. можно сделать так:


if (0 == _:('A' <= name[0] <= 'Z'))
return 0;


Из-за того, что логическое выражение возвращает значение с тегом bool, то для сравнения его с нулём нам необходимо избавиться от этого тега, иначе возникнет предупреждение.

Daniel_Cortez
15.07.2018, 14:10
Обновил реализацию функции: внесены новые оптимизации, исправлена проблема с const-корректностью (аргумент "name" был объявлен без const), добавлен тег bool для возвращаемого значения.
Также эксперимента ради набросал улучшенную версию с использованием оператора emit (http://pro-pawn.ru/showthread.php?15830), которая работает в ~1.5 раза (~2 с JIT) быстрее обычной реализации.

VVWVV
15.07.2018, 15:07
Обновил реализацию функции: внесены новые оптимизации, исправлена проблема с const-корректностью (аргумент "name" был объявлен без const), добавлен тег bool для возвращаемого значения.
Также эксперимента ради набросал улучшенную версию с использованием оператора emit (http://pro-pawn.ru/showthread.php?15830), которая работает в ~1.5 раза (~2 с JIT) быстрее обычной реализации.

Пора уже делать библиотеку с часто используемыми функциями на emit.

Daniel_Cortez
16.07.2018, 00:59
Пора уже делать библиотеку с часто используемыми функциями на emit.
Понимаю твой сарказм, но нет, я не являюсь сторонником перевода всего и вся на emit. Касаемо данной конкретной функции, как я уже сказал, это был простой эксперимент с целью определить, сколько потенциала для оптимизации упускает компилятор. А раз уж сделал что-то и оно хорошо работает, то почему бы и не поделиться?

VVWVV
16.07.2018, 01:04
Понимаю твой сарказм, но нет, я не являюсь сторонником перевода всего и вся на emit. Касаемо данной конкретной функции, как я уже сказал, это был простой эксперимент с целью определить, сколько потенциала для оптимизации упускает компилятор. А раз уж сделал что-то и оно хорошо работает, то почему бы и не поделиться?

Хех. Это был не сарказм. Как-то давно проверял, что некоторые функции на #emit работают в несколько раз быстрее, тем более в таймерах. Тыж сам говорил, что компилятор не умеет хорошо оптимизировать код, поэтому нужно делать это вручную.

:pardon:

Nexius_Tailer
16.07.2018, 02:51
Хех. Это был не сарказм. Как-то давно проверял, что некоторые функции на #emit работают в несколько раз быстрее, тем более в таймерах. Тыж сам говорил, что компилятор не умеет хорошо оптимизировать код, поэтому нужно делать это вручную.

:pardon:
Целенаправленно всё переписывать на них жизни не хватит (а если серьёзно, то просто нецелесообразно)

DeimoS
16.07.2018, 03:36
Целенаправленно всё переписывать на них жизни не хватит (а если серьёзно, то просто нецелесообразно)

Так вроде никто и не предлагает всё переписывать на emit. VVWVV предлагает собрать существующие функции, написанные на emit, в одну библиотеку, дабы можно было просто подключить эту самую библиотеку и пользоваться.

Nexius_Tailer
16.07.2018, 15:49
Так вроде никто и не предлагает всё переписывать на emit. VVWVV предлагает собрать существующие функции, написанные на emit, в одну библиотеку, дабы можно было просто подключить эту самую библиотеку и пользоваться.
А, ну мне показалось, что речь именно о намеренном переводе чего-либо, что и не имело бы никакого смысла.

Daniel_Cortez
17.07.2018, 20:01
Обновил вариант функции на emit: убрал пару лишних случаев записи в переменную и слегка улучшил код перед возвратом 1 - в итоге получилось выжать ещё примерно на 5% больше производительности (~12% с JIT).

Настройки для профайлера и результаты:


const PROFILER_ITERATIONS_MAJOR = 1_000;
const PROFILER_ITERATIONS_MINOR = 5_000;

new const code_snippets_names[][] =
{
{"IsRPNick"},
{"IsRPNickEmitOld"},
{"IsRPNickEmit"}
};

stock bool:IsRPNick(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static i, __;
if (('A' <= name[0] <= 'Z' && ('a' <= name[1] <= 'z')))
{
for (i = 1, __ = 0;;)
{
switch (name[++i])
{
case 'a'..'z':
continue;
case '_':
if (__++, 'A' <= name[++i] <= 'Z' && 'a' <= name[++i] <= 'z')
continue;
else
break;
case '\0':
return (i >= 4 && __ == 1);
default:
return false;
}
}
}
return false;
}

stock bool:IsRPNickEmitOld(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static num_underscores, ptr;
emit
{
load.s.pri name
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.s.pri name
add.c (cellbits / charbits)
stor.pri ptr
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsgrtr ret_false
zero num_underscores
loop:
load.pri ptr
add.c (cellbits / charbits)
stor.pri ptr
load.i
const.alt 'a'
jsless is_underscore
const.alt 'z'
jsleq loop
is_underscore:
const.alt '_'
jneq is_term
inc num_underscores
load.pri ptr
add.c (cellbits / charbits)
stor.pri ptr
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.pri ptr
add.c (cellbits / charbits)
stor.pri ptr
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsleq loop
jump ret_false
is_term:
jnz ret_false
load.pri ptr
load.s.alt name
sub
const.alt (cellbits / charbits * 4)
jsless ret_false
load.pri num_underscores
const.alt 1
jsless ret_false
const.pri 1
retn
ret_false:
}
return false;
}

stock bool:IsRPNickEmit(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static num_underscores, ptr;
emit
{
load.s.pri name
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.s.pri name
add.c (cellbits / charbits)
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsgrtr ret_false
zero num_underscores
load.s.pri name
add.c (cellbits / charbits * 2)
jump loop_entry
loop:
load.pri ptr
add.c (cellbits / charbits)
loop_entry:
stor.pri ptr
load.i
const.alt 'a'
jsless is_underscore
const.alt 'z'
jsleq loop
is_underscore:
const.alt '_'
jneq is_term
inc num_underscores
load.pri ptr
add.c (cellbits / charbits)
load.i
const.alt 'A'
jsless ret_false
const.alt 'Z'
jsgrtr ret_false
load.pri ptr
add.c (cellbits / charbits * 2)
stor.pri ptr
load.i
const.alt 'a'
jsless ret_false
const.alt 'z'
jsleq loop
jump ret_false
is_term:
jnz ret_false
load.pri ptr
load.s.alt name
sub
const.alt (cellbits / charbits * 4)
jsless ret_false
load.pri num_underscores
const.alt 1
eq
retn
ret_false:
}
return false;
}

static const nicks[][] =
{
/* 50 valid nicks */
"Maurice_Young",
"Leonard_Cooper",
"Norman_Allen",
"Charles_Lopez",
"Larry_Martin",
"Vince_Stewart",
"Leonard_Clark",
"Matthew_Morgan",
"Hunter_Rodriguez",
"Charles_Wright",
"Tobias_Nelson",
"Vince_Harris",
"Aaron_Wright",
"Charles_Morris",
"Alex_Young",
"Robert_Hill",
"Vince_Hernandez",
"Colin_Edwards",
"Jack_Lee",
"Leonard_Johnson",
"Justin_Taylor",
"Aaron_Allen",
"James_Jackson",
"Ronald_Howard",
"Richard_Campbell",
"Daniel_Brown",
"Zachary_Cooper",
"James_Cooper",
"Chad_Sanchez",
"Miles_Martin",
"Zachary_Anderson",
"Daniel_Cooper",
"James_Lopez",
"Samuel_Lopez",
"Brendan_Roberts",
"James_Thompson",
"Maurice_Harris",
"Brendan_Allen",
"Todd_Smith",
"John_Collins",
"Norman_Jones",
"Eric_Murphy",
"Alex_Garcia",
"Dan_Stewart",
"Mark_Bailey",
"Frank_Garcia",
"Barry_Wilson",
"Barry_Williams",
"Walter_Davis",
"Zachary_Taylor",
/* invalid nicks */
"JonhDoe",
"Johndoe",
"johnDoe",
"John__Doe",
"John_Richard_Doe",
"john_Doe",
"John_doe",
"_",
"J_D",
"_D",
"J_",
"Richard_D",
"R_Doe"
};

#define Prerequisites(); \
static i;

#define CodeSnippet0(); \
for (i = 0; i < sizeof(nicks); ++i) \
IsRPNick(nicks[i]);

#define CodeSnippet1(); \
for (i = 0; i < sizeof(nicks); ++i) \
IsRPNickEmitOld(nicks[i]);

#define CodeSnippet2(); \
for (i = 0; i < sizeof(nicks); ++i) \
IsRPNickEmit(nicks[i]);



Режим: интерпретируемый, 1000x500 итераций.
IsRPNick: 20781
IsRPNickEmitOld: 13630
IsRPNickEmit: 12930

Режим: с JIT-компиляцией, 1000x5000 итераций.
IsRPNick: 27033
IsRPNickEmitOld: 14411
IsRPNickEmit: 12811




Тыж сам говорил, что компилятор не умеет хорошо оптимизировать код, поэтому нужно делать это вручную.
Да, но целесообразно такое обычно только для функций, обрабатывающих массивы данных - например, для строковых функций, коей и является IsRPNick().
Касаемо библиотеки, если собираешься такую делать - я не против включения в неё своей функции, но только при выполнении двух простых условий:
Библиотека должна быть выпущена под лицензией, не требующей бинарной аттрибуции. Многие не задумываются при выборе лицензии, почём зря - многие популярные лицензии, такие как MIT, MPL, BSD и пр. требуют от пользователей включать копирайт и текст лицензии в скомпилированный скрипт или таскать их в отдельном текстовом файле вместе с *.amx - хотя, как правило, у самих авторов нет намерения требовать это в обязательном порядке. Одни из немногих лицензий, не требующих бинарной аттрибуции - лицензия zlib, Boost Software License.
В функции должен быть сохранён комментарий со ссылкой на данную тему, чтобы пользователи могли узнать её происхождение.



Целенаправленно всё переписывать на них жизни не хватит (а если серьёзно, то просто нецелесообразно)
Если речь про директиву #emit, то там больше проблема в ограничениях (нельзя сделать переход на метку впереди, не поддерживаются инструкции с более чем 1 аргументом) и в том, что очень просто допустить ошибку, которую потом найти затруднительно (например, вместо "load.s.pri local_var" написать "load.pri local_var" или вообще "load.s.pri" без аргумента - компилятор всё это пропустит). При этом с оператором emit эти и многие другие проблемы либо полностью решены, либо сведены к минимуму - можно куда производительнее писать код, не задумываясь об ограничениях или о том, что где-то перепутал инструкцию или тип аргумента.

VVWVV
17.07.2018, 20:09
Да, но целесообразно такое обычно только для функций, обрабатывающих массивы данных - например, для строковых функций, коей и является IsRPNick().
Касаемо библиотеки, если собираешься такую делать - я не против включения в неё своей функции, но только при выполнении двух простых условий:
Библиотека должна быть выпущена под лицензией, не требующей бинарной аттрибуции. Многие не задумываются при выборе лицензии, почём зря - многие популярные лицензии, такие как MIT, MPL, BSD и пр. требуют от пользователей включать копирайт и текст лицензии в скомпилированный скрипт или таскать их в отдельном текстовом файле вместе с *.amx - хотя, как правило, у самих авторов нет намерения требовать это в обязательном порядке. Одни из немногих лицензий, не требующих бинарной аттрибуции - лицензия zlib, Boost Software License.
В функции должен быть сохранён комментарий со ссылкой на данную тему, чтобы пользователи могли узнать её происхождение.



1. Мы в jabber уже обсуждали эту тему с лицензиями, я это прекрасно помню. Да, и в общем знал об этом, поскольку мои библиотеки использую zlib лицензию.
2. Ссылки можно разместить в шапке файла, чтобы они не бросались в глаза. Как минимум, это будет говорить, что библиотека - лишь сборник функций, не направленный на конкретную деятельность (как, например, tdw rscan).

Kovshevoy
08.11.2019, 23:57
А как сделать так, чтобы после слэша можно было юзать две заглавные? По типу, Marty_McFly

DeimoS
09.11.2019, 03:19
А как сделать так, чтобы после слэша можно было юзать две заглавные? По типу, Marty_McFly

Ну то, найден ли нижний слеш или нет, отображается в переменной "__". Соответственно, нужно добавить проверку на количество заглавных букв в "default", приписав проверку на нижний слэш, а так же в "case '_':".

Как-то так, короче:
stock bool:IsRPNick(const name[])
{ // http://pro-pawn.ru/showthread.php?7528
static i, __, bs;
if (('A' <= name[0] <= 'Z' && ('a' <= name[1] <= 'z')))
{
for (i = 1, __ = 0, bs = 0;;)
{
switch (name[++i])
{
case 'a'..'z':
continue;
case '_':
if (__++, 'A' <= name[++i] <= 'Z' && 'a' <= name[++i] <= 'z')
continue;
else if ('A' <= name[i-1] <= 'Z' && 'A' <= name[i] <= 'Z' && 'a' <= name[++i] <= 'z')
{
bs++;
continue;
}
else
break;
case '\0':
return (i >= 4 && __ == 1);
default:
{
if(__ == 1 && bs == 0 && 'A' <= name[i] <= 'Z')
{
bs++;
continue;
}
return false;
}
}
}
}
return false;
}
Это если минимально изменять алгоритм (собственно, что первое в голову пришло). И это явно не самый оптимальный вариант реализации, ибо он будет трудно масштабируемым в текущем виде.

Daniel_Cortez
10.11.2019, 12:34
Сходу получилось вспомнить следующие префиксы для фамилий:

"Mc" - ирландско-шотландский патроним; также встречается вариант "Mac" (примеры: "McSmith", "MacDonald");
"O'" - ирландский патроним (примеры: "O'Brian", "O'Connor");
"al-" - определённый артикль в арабском языке, нечто вроде "the" из английского, который в фамилиях обозначает принадлежность человека к какому-либо месту или профессии (пример: "al-Kufi" (от "Kufa" - название города в Ираке)).
"Al" - тоже из арабского языка, означает принадлежность человека к определённой семье, клану или династии (пример: "Al Saud").

Если я забыл какие-то ещё часто встречающиеся префиксы - дайте знать, добавлю в этот пост.

И вот вариант функции, который учитывает только префиксы из списка, не позволяя делать рандомные фамилии с двумя заглавными буквами:

stock bool:IsRPNick(const name[])
{ // http://pro-pawn.ru/showthread.php?7528&p=95478&viewfull=1#post95478
static i, j, __;
if ('A' <= name[0] <= 'Z' && 'a' <= name[1] <= 'z')
{
for (i = 1, __ = 0;;)
{
switch (name[++i])
{
case 'a'..'z':
continue;
case '_':
{
static const prefixes[][] = { "Mc", "Mac", "O", "von_", "van_", "al_", "Al_" };
static const prefix_lengths[] = { 2, 3, 1, 4, 4, 3, 3 };
for (++__, ++i, j = 0; j < sizeof(prefixes); ++j)
{
if (0 != strcmp(name[i], prefixes[j], false, prefix_lengths[j]))
continue;
if ('A' <= name[i + prefix_lengths[j]] <= 'Z')
i += prefix_lengths[j];
break;
}
if ('A' <= name[i] <= 'Z' && 'a' <= name[++i] <= 'z')
continue;
else
break;
}
case '\0':
return (i >= 4 && __ == 1);
default:
return false;
}
}
}
return false;
}

Примеры никнеймов с префиксами для фамилий, которые эта функция пропускает:


John_McSmith
Gerald_MacDonald
Charles_OConnor
Mohammad_al_Kufi
Mohammad_Al_Saud

Kovshevoy
11.11.2019, 03:15
https://ru.wikipedia.org/wiki/Фамильная_приставка

Daniel_Cortez
14.11.2019, 12:21
https://ru.wikipedia.org/wiki/Фамильная_приставка
На счёт многих приставок из этой статьи не уверен, что их можно часто встретить на RP-серверах. Пока что добавил только германо-австрийскую праставку "von" и голландскую "van".

DeimoS
14.11.2019, 14:28
На счёт многих приставкой из этой статьи не уверен, что их можно часто встретить на RP-серверах. Пока что добавил только германо-австрийскую праставку "von" и голландскую "van".

Добавь в основной пост ссылку на этот (http://pro-pawn.ru/showthread.php?7528-IsRPNick-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D0%BD%D0%B0-RP-%D0%BD%D0%B8%D0%BA&p=95478&viewfull=1#post95478) пост. А то затеряется среди других сообщений.

SteveStage
18.11.2019, 18:33
На счёт многих приставкой из этой статьи не уверен, что их можно часто встретить на RP-серверах.

Добавь приставку El (Эль) в начале фамилии (Испания)

DeimoS
18.11.2019, 19:10
Добавь приставку El (Эль) в начале фамилии (Испания)

Мне кажется, подразумевалось то, что любой желающий вставит в функцию свои префиксы. Не обязательно об этом просить Daniel_Cortez

SteveStage
18.11.2019, 19:10
Мне кажется, подразумевалось то, что любой желающий вставит в функцию свои префиксы. Не обязательно об этом просить Daniel_Cortez

Понятно