Raised This Month: $ Target: $400
 0% 

Check character then replace


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Syturi0
Veteran Member
Join Date: Aug 2014
Location: Your mom house -Portugal
Old 04-13-2016 , 14:32   Check character then replace
Reply With Quote #1

I want to only allow A-Z, 0-9, and a few special characters like [](),.-~#=+-, on nicknames.

PHP Code:
new const g_AllowNickCharacter [][] =
{
    
"a""b""c""d""e""f""g""h""i",
    
"j""k""l""m""n""o""p""q""r",
    
"s""t""u""v""x""z""<"">"",",
    
"+""*""'""?""="")""(""/""#",
    
".""-"";"":""_""ç""~""",
    
"!""|""\", "[", "]", "1", "2", "3", "4",
    "
5", "6", "7", "8", "9", "0", "@"

If the player uses a character that is not one of those mentioned above, it will get removed.
This is a test i did, its only for the first character:
PHP Code:
public client_infochanged(id)
{
    if(!
is_user_bot(id) && !is_user_hltv(id))
    {
        new const 
name[] = "name"
        
new szNewName[33]
        
get_user_info(idnameszNewNamecharsmax(szNewName))

        for(new 
0sizeof(g_AllowNickCharacter); i++)
            if(!(
equal(szNewName[0], g_AllowNickCharacter[i]) != -1))
                    
replace(szNewNamecharsmax(szNewName), szNewName[0], "")

        
set_user_info(idnameszNewName)
    }

Whats wrong?

Last edited by Syturi0; 04-13-2016 at 14:35.
Syturi0 is offline
siriusmd99
Veteran Member
Join Date: Oct 2013
Location: Republic of Moldova
Old 04-13-2016 , 17:00   Re: Check character then replace
Reply With Quote #2

It's not 2d array, because you have characters. If you had strings for example instead of "a" you had "alphabeta" then you should use double [][] but here is only [].

PHP Code:
new const g_AllowNickCharacter [] =
{
    
"a""b""c""d""e""f""g""h""i",
    
"j""k""l""m""n""o""p""q""r",
    
"s""t""u""v""x""z""<"">"",",
    
"+""*""'""?""="")""(""/""#",
    
".""-"";"":""_""ç""~""",
    
"!""|""\", "[", "]", "1", "2", "3", "4",
    "
5", "6", "7", "8", "9", "0", "@"


PHP Code:
public client_infochanged(id)
{
    if(!
is_user_bot(id) && !is_user_hltv(id))
    {
        new const 
name[] = "name"
        
new szNewName[33]
        
get_user_info(idnameszNewNamecharsmax(szNewName))

       for(new 
0charsmax(szNewName); i++)
            if(
containi(g_AllowNickCharacter,szNewName[i]) == -1)
                    
replace(szNewNamecharsmax(szNewName), szNewName[i], "")

        
set_user_info(idnameszNewName)
    }

I used containi so that case sensitive works, i mean if you have allowed "a" then "A" will be also allowed.If you do not want that then just change "containi" to "contain".

if(containi(g_AllowNickCharacter,szNewName[i]) == -1)

it means that if current symbol of player's name doesnt exists in allowed constant array then this character will removed with your method.
siriusmd99 is offline
Syturi0
Veteran Member
Join Date: Aug 2014
Location: Your mom house -Portugal
Old 04-13-2016 , 17:10   Re: Check character then replace
Reply With Quote #3

Quote:
Originally Posted by siriusmd99 View Post
It's not 2d array, because you have characters. If you had strings for example instead of "a" you had "alphabeta" then you should use double [][] but here is only [].

PHP Code:
new const g_AllowNickCharacter [] =
{
    
"a""b""c""d""e""f""g""h""i",
    
"j""k""l""m""n""o""p""q""r",
    
"s""t""u""v""x""z""<"">"",",
    
"+""*""'""?""="")""(""/""#",
    
".""-"";"":""_""ç""~""",
    
"!""|""\", "[", "]", "1", "2", "3", "4",
    "
5", "6", "7", "8", "9", "0", "@"


PHP Code:
public client_infochanged(id)
{
    if(!
is_user_bot(id) && !is_user_hltv(id))
    {
        new const 
name[] = "name"
        
new szNewName[33]
        
get_user_info(idnameszNewNamecharsmax(szNewName))

       for(new 
0charsmax(szNewName); i++)
            if(
containi(g_AllowNickCharacter,szNewName[i]) == -1)
                    
replace(szNewNamecharsmax(szNewName), szNewName[i], "")

        
set_user_info(idnameszNewName)
    }

I used containi so that case sensitive works, i mean if you have allowed "a" then "A" will be also allowed.If you do not want that then just change "containi" to "contain".

if(containi(g_AllowNickCharacter,szNewName[i]) == -1)

it means that if current symbol of player's name doesnt exists in allowed constant array then this character will removed with your method.
Still not working.
Syturi0 is offline
Syturi0
Veteran Member
Join Date: Aug 2014
Location: Your mom house -Portugal
Old 04-19-2016 , 09:35   Re: Check character then replace
Reply With Quote #4

bump
Syturi0 is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 04-19-2016 , 11:25   Re: Check character then replace
Reply With Quote #5

When using double quotes ( " ), you're basically telling the compiler that it should terminate the string after each quote So the string is actually:
a, null, b, null ...
You should use single quotes ( ' ) for characters.

Code:
    new const g_AllowNickCharacter [] = { "a", "b", "c" }     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]);
Code:
a, a, a
->
Code:
    new const g_AllowNickCharacter [] = { 'a', 'b', 'c' }     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]);
Code:
abc, abc, a


Remember though, you have to terminate the string by putting null at the end or all functions will continue reading memory until it reaches 0, which could cause memory access runtime errors.
Code:
new const g_AllowNickCharacter [] = { 'a', 'b', 'c' } public plugin_init() {     register_plugin("Test Plugin 5", "", "[ --{-@ ]");     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]); }
Code:
abcTest Plugin 5, abcTest Plugin 5, a
->
Code:
new const g_AllowNickCharacter [] = { 'a', 'b', 'c', 0 } public plugin_init() {     register_plugin("Test Plugin 5", "", "[ --{-@ ]");     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]); }
Code:
abc, abc, a
Code:
new const g_AllowNickCharacter [] = {     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',     'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',     's', 't', 'u', 'v', 'x', 'z', '<', '>', ',',     '+', '*', ''', '?', '=', ')', '(', '/', '#',     '.', '-', ';', ':', '_', /* 'ç', */ '~', /*'' ? */     '!', '|', '\', '[', ']', '1', '2', '3', '4',     '5', '6', '7', '8', '9', '0', '@', 0 // <-- Important null to end the string. }
You could just as well do
Code:
new const g_AllowNickCharacter [] = "abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@"



replace() will check for occurances, skip containi() and add upper case letters instead.



With all that said, you should check out an ASCII chart and try using direct character comparisons instead.
For example:
Code:
if ( 'a' <= string[i] <= 'z' )     // ...
And how do we do this the easy way? We sort the string real fast so we can find the combinations easily:
Code:
    new g_AllowNickCharacter [] = "abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@";     server_print("unsorted: %s", g_AllowNickCharacter);     SortIntegers(g_AllowNickCharacter, sizeof g_AllowNickCharacter - 1);     server_print("  sorted: %s", g_AllowNickCharacter);
Code:
unsorted: abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@
  sorted: !#'()*+,-./0123456789:;<=>?@[\]_abcdefghijklmnopqrstuvxz|~
And breaked down, this shows the groupings we can use:
Code:
/*
a-z
A-Z
0-9

!
#
'
()*+,-./
:;<=>?@
[\]
_
|
~
*/
That requires another way of replacing characters but a simple way is just using a buffer since the string is so small.
This way is the most efficient. There are a lot of comparisons, but replace inside a loop is loop inception. Don't get me started on replace_all. loop3
Code:
    new string1[32] = "abcåäöABC¤$123€%!";     new string2[32];     new a;     for ( new i ; i < sizeof string1 ; i++ ) {         if (             'a' <= string1[i] <= 'z' ||             'A' <= string1[i] <= 'Z' ||             '0' <= string1[i] <= '9' ||             string1[i] == '!' ||             string1[i] == '#' ||             string1[i] == '^'' || // ' <- Because the code wrapper on this page uses \ as control character while pawn uses ^             '(' <= string1[i] <= '/' ||             ':' <= string1[i] <= '@' ||             '[' <= string1[i] <= ']' ||             string1[i] == '_' ||             string1[i] == '|' ||             string1[i] == '~'             )             string2[a++] = string1[i];     }     string2[a] = 0; // Don't forget to terminate.     server_print("string1: %s", string1);     server_print("string2: %s", string2);
Code:
string1: abc+Ñ+ñ+ÂABC-ñ$123Ôé¼%!
string2: abcABC123!
Now I know you're asking... "How could I improve this further?".
Well. Comparing a variable 12 times will make it read the value of that variable from the memory 12 times. With a simple switch(), you can reduce that to 1!
Code:
    new string1[32] = "abcåäöABC¤$123€%!";     new string2[32];     new a;     for ( new i ; i < sizeof string1 ; i++ ) {         if ( IsAcceptable(string1[i]) )             string2[a++] = string1[i];     }     string2[a] = 0; // Don't forget to terminate.     server_print("string1: %s", string1);     server_print("string2: %s", string2); } IsAcceptable(c) {     switch (c) {         case 'a' .. 'z' : return 1;         case 'A' .. 'Z' : return 1;         case '0' .. '9' : return 1;         case '!' : return 1;         case '#' : return 1;         case '^'' : return 1; // ' <- Because the code wrapper on this page uses \ as control character while pawn uses ^         case '(' .. '/' : return 1;         case ':' .. '@' : return 1;         case '[' .. ']' : return 1;         case '_' : return 1;         case '|' : return 1;         case '~' : return 1;     }     return 0; }
Code:
string1: abc+Ñ+ñ+ÂABC-ñ$123Ôé¼%!
string2: abcABC123!
Readability could be improved but I guess you get the point and can take necessary parts from these examples that will fit you best.
In the end, none of these methods are slow. There's no need to worry about using one over another.
__________________

Last edited by Black Rose; 04-19-2016 at 13:03.
Black Rose is offline
Old 04-19-2016, 12:35
Black Rose
This message has been deleted by Black Rose.
Old 04-19-2016, 12:37
Black Rose
This message has been deleted by Black Rose.
Old 04-19-2016, 12:46
Black Rose
This message has been deleted by Black Rose.
Syturi0
Veteran Member
Join Date: Aug 2014
Location: Your mom house -Portugal
Old 07-28-2016 , 00:32   Re: Check character then replace
Reply With Quote #6

Quote:
Originally Posted by Black Rose View Post
When using double quotes ( " ), you're basically telling the compiler that it should terminate the string after each quote So the string is actually:
a, null, b, null ...
You should use single quotes ( ' ) for characters.

Code:
    new const g_AllowNickCharacter [] = { "a", "b", "c" }     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]);
Code:
a, a, a
->
Code:
    new const g_AllowNickCharacter [] = { 'a', 'b', 'c' }     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]);
Code:
abc, abc, a


Remember though, you have to terminate the string by putting null at the end or all functions will continue reading memory until it reaches 0, which could cause memory access runtime errors.
Code:
new const g_AllowNickCharacter [] = { 'a', 'b', 'c' } public plugin_init() {     register_plugin("Test Plugin 5", "", "[ --{-@ ]");     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]); }
Code:
abcTest Plugin 5, abcTest Plugin 5, a
->
Code:
new const g_AllowNickCharacter [] = { 'a', 'b', 'c', 0 } public plugin_init() {     register_plugin("Test Plugin 5", "", "[ --{-@ ]");     server_print("%s, %s, %c", g_AllowNickCharacter, g_AllowNickCharacter[0], g_AllowNickCharacter[0]); }
Code:
abc, abc, a
Code:
new const g_AllowNickCharacter [] = {     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',     'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',     's', 't', 'u', 'v', 'x', 'z', '<', '>', ',',     '+', '*', ''', '?', '=', ')', '(', '/', '#',     '.', '-', ';', ':', '_', /* 'ç', */ '~', /*'' ? */     '!', '|', '\', '[', ']', '1', '2', '3', '4',     '5', '6', '7', '8', '9', '0', '@', 0 // <-- Important null to end the string. }
You could just as well do
Code:
new const g_AllowNickCharacter [] = "abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@"



replace() will check for occurances, skip containi() and add upper case letters instead.



With all that said, you should check out an ASCII chart and try using direct character comparisons instead.
For example:
Code:
if ( 'a' <= string[i] <= 'z' )     // ...
And how do we do this the easy way? We sort the string real fast so we can find the combinations easily:
Code:
    new g_AllowNickCharacter [] = "abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@";     server_print("unsorted: %s", g_AllowNickCharacter);     SortIntegers(g_AllowNickCharacter, sizeof g_AllowNickCharacter - 1);     server_print("  sorted: %s", g_AllowNickCharacter);
Code:
unsorted: abcdefghijklmnopqrstuvxz<>,+*'?=)(/#.-;:_~!|\[]1234567890@
  sorted: !#'()*+,-./0123456789:;<=>?@[\]_abcdefghijklmnopqrstuvxz|~
And breaked down, this shows the groupings we can use:
Code:
/*
a-z
A-Z
0-9

!
#
'
()*+,-./
:;<=>?@
[\]
_
|
~
*/
That requires another way of replacing characters but a simple way is just using a buffer since the string is so small.
This way is the most efficient. There are a lot of comparisons, but replace inside a loop is loop inception. Don't get me started on replace_all. loop3
Code:
    new string1[32] = "abcåäöABC¤$123€%!";     new string2[32];     new a;     for ( new i ; i < sizeof string1 ; i++ ) {         if (             'a' <= string1[i] <= 'z' ||             'A' <= string1[i] <= 'Z' ||             '0' <= string1[i] <= '9' ||             string1[i] == '!' ||             string1[i] == '#' ||             string1[i] == '^'' || // ' <- Because the code wrapper on this page uses \ as control character while pawn uses ^             '(' <= string1[i] <= '/' ||             ':' <= string1[i] <= '@' ||             '[' <= string1[i] <= ']' ||             string1[i] == '_' ||             string1[i] == '|' ||             string1[i] == '~'             )             string2[a++] = string1[i];     }     string2[a] = 0; // Don't forget to terminate.     server_print("string1: %s", string1);     server_print("string2: %s", string2);
Code:
string1: abc+Ñ+ñ+ÂABC-ñ$123Ôé¼%!
string2: abcABC123!
Now I know you're asking... "How could I improve this further?".
Well. Comparing a variable 12 times will make it read the value of that variable from the memory 12 times. With a simple switch(), you can reduce that to 1!
Code:
    new string1[32] = "abcåäöABC¤$123€%!";     new string2[32];     new a;     for ( new i ; i < sizeof string1 ; i++ ) {         if ( IsAcceptable(string1[i]) )             string2[a++] = string1[i];     }     string2[a] = 0; // Don't forget to terminate.     server_print("string1: %s", string1);     server_print("string2: %s", string2); } IsAcceptable(c) {     switch (c) {         case 'a' .. 'z' : return 1;         case 'A' .. 'Z' : return 1;         case '0' .. '9' : return 1;         case '!' : return 1;         case '#' : return 1;         case '^'' : return 1; // ' <- Because the code wrapper on this page uses \ as control character while pawn uses ^         case '(' .. '/' : return 1;         case ':' .. '@' : return 1;         case '[' .. ']' : return 1;         case '_' : return 1;         case '|' : return 1;         case '~' : return 1;     }     return 0; }
Code:
string1: abc+Ñ+ñ+ÂABC-ñ$123Ôé¼%!
string2: abcABC123!
Readability could be improved but I guess you get the point and can take necessary parts from these examples that will fit you best.
In the end, none of these methods are slow. There's no need to worry about using one over another.
Hi there, sorry for the huge delay, i have been really busy lately.
Thank you for your detailed answer, it works correctly.

PS: You forgot to add
PHP Code:
case ' ' : return 
(space bar)
Syturi0 is offline
siriusmd99
Veteran Member
Join Date: Oct 2013
Location: Republic of Moldova
Old 07-28-2016 , 03:16   Re: Check character then replace
Reply With Quote #7

Why checking all allowed symbols if you can check only symbols which are not allowed?

PHP Code:

//How to use function

if( FixedName(szPlayerName) )
set_user_info(id"name"szPlayerName //If name has been changed it means that it contained restricted symbols and we set new name

FixedName str[] ) 
{
    new 
len strlen(str)
    new 
oldlen len;
    new 
ijtmp;

    while(
len)
    {
       
tmp str[i];
       if( 
tmp 31 && tmp 127)
       {
           switch(
tmp)
           {
               case 
34,36,38,94,96,123,125 : {} //If symbol is restricted then do nothing (to go to the removal part)
               
default : 
               {  
                    
i++;
                    continue; 
//If current symbol is ok then we go to the next one
               
}

           }
       }
       
       
//Code down is executed when current symbol is detected as restricted.
       //This is character's removal part

       
for(ilenj++)
       {
            
str[j] = str[j+1];   //Moving symbols with one step back.
       
}
       
       
len--; //Saving new length

    
}
    
    if(
oldlen != len)
    {
        return 
1;
    }
    
    return 
0;


Last edited by siriusmd99; 07-28-2016 at 04:03.
siriusmd99 is offline
addons_zz
Veteran Member
Join Date: Aug 2015
Location: Dreams, zz
Old 07-28-2016 , 21:32   Re: Check character then replace
Reply With Quote #8

Quote:
Originally Posted by siriusmd99 View Post
Why checking all allowed symbols if you can check only symbols which are not allowed?

PHP Code:

//How to use function

if( FixedName(szPlayerName) )
set_user_info(id"name"szPlayerName //If name has been changed it means that it contained restricted symbols and we set new name

FixedName str[] ) 
{
    new 
len strlen(str)
    new 
oldlen len;
    new 
ijtmp;

    while(
len)
    {
       
tmp str[i];
       if( 
tmp 31 && tmp 127)
       {
           switch(
tmp)
           {
               case 
34,36,38,94,96,123,125 : {} //If symbol is restricted then do nothing (to go to the removal part)
               
default : 
               {  
                    
i++;
                    continue; 
//If current symbol is ok then we go to the next one
               
}

           }
       }
       
       
//Code down is executed when current symbol is detected as restricted.
       //This is character's removal part

       
for(ilenj++)
       {
            
str[j] = str[j+1];   //Moving symbols with one step back.
       
}
       
       
len--; //Saving new length

    
}
    
    if(
oldlen != len)
    {
        return 
1;
    }
    
    return 
0;

This is a bad thing to do, an loop inside a loop always shifting everything:
Code:
       for(j = i; j < len; j++)        {             str[j] = str[j+1];   //Moving symbols with one step back.        }

Also, do not hard code chars:
Code:
               case 34,36,38,94,96,123,125 : {} //If symbol is restricted then do nothing (to go to the removal part)
-->
Code:
               case '%',"$', etc...: {} //If symbol is restricted then do nothing (to go to the removal part)
And to do a favor to other when writing code, take some time to name the variables.
Code:
    new i, j, tmp;
-->
Code:
    new latestIndex, currentIndex, currentChar;

@Black Rose solves well the problem, if you want to invert things, do it over his algorithm inverting its logic.
However, the performance on this case is kinda irrelevant whether you check the allowed symbols or the not allowed symbols.
__________________
Plugin: Sublime Text - ITE , Galileo
Multi-Mod: Manager / Plugin / Server

Support me on Patreon, Ko-fi, Liberapay or Open Collective
addons_zz is offline
Syturi0
Veteran Member
Join Date: Aug 2014
Location: Your mom house -Portugal
Old 07-28-2016 , 22:21   Re: Check character then replace
Reply With Quote #9

Quote:
Originally Posted by siriusmd99 View Post
Why checking all allowed symbols if you can check only symbols which are not allowed?
Because i dont know ALL the non-allowed symbols... Like i said, i only want to allow a-z, A-Z, 0-9, and a few normal symbols for example: #_:=-



There are way to many:





Anyways the @Black Rose method works perfectly, its exactly what i wanted.

Last edited by Syturi0; 07-28-2016 at 22:21.
Syturi0 is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:36.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode