PHP字符串函数 分类整理与简要源码分析
源码基于PHP5.5.38
addcslashes
add c (style) slashes 为字符串添加C语言风格的反斜线
string addcslashes(string $str, string $charlist)
将$str
字符串中每一个在$charlist
中的字符加上反斜线。
echo addcslashes("abcdefg", "ad");
//输出abcdefg
如果$charlist
为空字符串,返回值也是空字符串string "" (length=0)
好玩的现象:
echo addcslashes("
", "
");
//输出 \
//这里
并没有特殊的意思,就是 和 n的意思
echo addcslashes("
", "
");
//输出
不知道为什么出现这个原因,特意看了下源代码:
/**
这个函数的功能就是将$charlist中的所有字符扫描一篇,确认使用了那些字符。假设$charlist中是aaaaaabbbbbbb,如果不这么做,a,b将会重复使用多次,效率不高。
*/
static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_DC)
{
//input指的是$charlist
unsigned char *end;
unsigned char c;
int result = SUCCESS;
memset(mask, 0, 256); //初始化为0
for (end = input+len; input < end; input++)
{
c=*input;
//这个if 检查input是否是x..y形式,范围表达式
if ((input+3 < end) && input[1] == "." && input[2] == "." && input[3] >= c)
{
memset(mask+c, 1, input[3] - c + 1); //将c所代表的字符开始到最右边这段空间的所有位置设为1 mask + c 巧妙的利用指针
input+=3; //这里其实就会跳出for
}
else if ((input+1 < end) && input[0] == "." && input[1] == ".")
{
//////省略一些范围检测
} else {
mask[c]=1; //将c所代表的变量置为1
}
}
return result;
}
PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
{
/////////////////忽略一些初始化代码
php_charmask((unsigned char *)what, wlength, flags TSRMLS_CC); //在flags中记录$charlist需要用到哪些字符
for (source = (char*)str, end = source + length, target = new_str; source < end; source++)
{
c = *source; //取出$str中的某一个字符
if (flags[(unsigned char)c]) //如果当前字符不在之前记录的函数中,则跳过
{
if ((unsigned char) c < 32 || (unsigned char) c > 126) //32是空格 126是~ 反过来说32-126是ASCII可视字符
{
*target++ = "\"; //对目前字符首先新增字符 \是转义的意思 除此之外的不可见字符 显示为0开头且宽度为3的八进制数
//特殊字符 继续特殊显示不可见的
字符,被替换成可见的
字符
switch (c)
{
case "
": *target++ = "n"; break;
case " ": *target++ = "t"; break;
case "
": *target++ = "r"; break;
case "a": *target++ = "a"; break;
case "v": *target++ = "v"; break;
case "": *target++ = "b"; break;
case "f": *target++ = "f"; break;
default: target += sprintf(target, "%03o", (unsigned char) c); //sprintf首先在target指针中追加内容再返回字符串长度,来移动target指针
}
continue; //不执行下面的两句语句 避免重复添加
}
*target++ = "\"; //是记录中的字符 但是不是可视字符
}
*target++ = c; //普通字符不做任何操作,直接添加
}
}
所以addcslashes
函数使用时,会将一些转义字符可视化,其余不可视化的字符显示为八进制数。从源码可以看出,该函数一般不用于处理非ASCII编码。
//测试
echo addcslashes("
", "
");
//输出
echo addcslashes(chr(25), chr(25));
//输出 /031
addslashes
add slashes [slæʃiz]
string addslashes(string $str)
主要为了在可能需要转义的语句中的特殊字符前加入反斜线,例如SQL
语句。这些特殊字符包括"
, "
, ,
NULL
,如下文的源代码所示:
switch (*source)
{
case " ":
*target++ = "\";
*target++ = "0";
break;
case """:
case """:
case "\":
*target++ = "\"; //不放置break为的就是使用default中的语句,直接在字符串使用
default:
*target++ = *source;
break;
}
不过进行数据库操作还是建议使用框架中的ORM,框架中的查询生成器、或者PDO、最好不要自己构造完整的SQL
语句,避免SQL注入
。
bin2hex
bin to hex
string bin2hex(string $str)
ASCII转换函数,把ASCII转化为十六进制。并不是进制转换函数,例如:
echo bin2hex("ABCD");
//41424344
源码分析:
static char hexconvtab[] = "0123456789abcdef";
////
for (i = j = 0; i < oldlen; i++)
{
result[j++] = hexconvtab[old[i] >> 4];
//old[i]里面记录的是某一个ASCII码 右移4位
/*
假设old[i] = "A" => 01000001B
右移4位就只剩0100B了,也就是4,可以去查看ASCII表,你会发现某一个ASCII的前4位,和它的16进制的数值是一样的,因为ASCII是从0000 0000开始编码的。
*/
result[j++] = hexconvtab[old[i] & 15];
//这里和15 => 00001111进行与运算 可以清零old[i]的高4位
}
result[j] = " "; //加上C语言的字符串结束符
chop / rtrim
right trim
string rtrim(string $str [,string $character_mask])
函数用于删除字符串右边(末端)的空白字符(一些转义字符)或者给定的字符。空白字符包括,
,
,
,