PHP字符串函数 分类整理与简要源码分析

PHP字符串函数 分类整理与简要源码分析

源码基于PHP5.5.38

addcslashes

add c (style) slashes 为字符串添加C语言风格的反斜线

string addcslashes(string $str, string $charlist)

$str字符串中每一个在$charlist中的字符加上反斜线。

echo addcslashes('abcdefg', 'ad');
//输出\abc\defg

如果$charlist为空字符串,返回值也是空字符串string '' (length=0)
好玩的现象:

echo addcslashes('\n', '\n');
//输出 \\\n 
//这里\n并没有特殊的意思,就是\ 和 n的意思

echo addcslashes("\n", "\n");
//输出 \n

不知道为什么出现这个原因,特意看了下源代码:


/**
这个函数的功能就是将$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的八进制数
                //特殊字符 继续特殊显示不可见的\n字符,被替换成可见的\n字符
                switch (c) 
                {
                    case '\n': *target++ = 'n'; break;
                    case '\t': *target++ = 't'; break;
                    case '\r': *target++ = 'r'; break;
                    case '\a': *target++ = 'a'; break;
                    case '\v': *target++ = 'v'; break;
                    case '\b': *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("


", "\n");
//输出\n\n\n\n\n

echo addcslashes(chr(25), chr(25));
//输出 /031

addslashes

add slashes [slæʃiz]

string addslashes(string $str)

主要为了在可能需要转义的语句中的特殊字符前加入反斜线,例如SQL语句。这些特殊字符包括', ", \, NULL ,如下文的源代码所示:

switch (*source) 
{
    case '\0':
        *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] = '\0'; //加上C语言的字符串结束符

chop / rtrim

right trim

string rtrim(string $str [,string $character_mask])

函数用于删除字符串右边(末端)的空白字符(一些转义字符)或者给定的字符。空白字符包括, \t, \n, \r, \0,\x0B。如果不给$character_mask就默认删除空白符。
示例:

var_dump(rtrim('user    '));
//string 'user' (length = 4)
var_dump(rtrim('user11111', '1'));
//string 'user' (length = 4)
var_dump(rtrim('user1111 111  ', ' 1'));
//删除多个字符 string 'user' (length = 4)

源码分析之前, 我觉得$character_mask应该用了之前处理addcslashes函数中的$charlist参数的函数php_charmask

PHPAPI char *php_trim(char *c, int len, char *what, int what_len, zval *return_value, int mode TSRMLS_DC)
{
    register int i;
    int trimmed = 0;
    char mask[256];

    //这里what指针就是$character_mask 我们可以看见 当不传参数时,what为空指针执行第二句php_charmask 把\n等作为字符串参数主动传入,在mask数组中设置好相应的标记
    if (what) 
    {
        php_charmask((unsigned char*)what, what_len, mask TSRMLS_CC);
    } 
    else 
    {
        php_charmask((unsigned char*)" \n\r\t\v\0", 6, mask TSRMLS_CC);
    }
    //使用mode变量是因为 php_trim这个函数共同用于ltrim, rtrim, trim
    //mode == 1表示ltrim
    //mode == 2表示rtrim
    //mode == 3表示trim

    //这里使用与运算 技巧如下当mode等于1(0001B)或者3(0011B)的时候,通过& 1(0001B)得到大于0的值; 当mode等于2(0010B)或者3(0011B)的时候,通过& 2(0010B)得到大于0的值。

    //感慨一下,,真厉害,,,从来没想过还能这么搞。。。。膜拜一下。。。ofo
    if (mode & 1) 
    {
        for (i = 0; i < len; i++) 
        {
        //找到第一个不在标记字符串中的下标
            if (mask[(unsigned char)c[i]]) 
            {
                trimmed++;
            } 
            else 
            {
                break;
            }
        }
        len -= trimmed;
        c += trimmed; //移动指针即可清除首端字符
    }
    if (mode & 2) 
    {
        for (i = len - 1; i >= 0; i--) 
        {
            if (mask[(unsigned char)c[i]]) 
            {
                len--;
            } 
            else 
            {
                break;
            }
        }
    }
    //这里涉及到zend内核的一些知识了,return_value是一个很特殊的参数。等我懂了就来补充这里。

    if (return_value) {
        RETVAL_STRINGL(c, len, 1); //一个宏用于返回定长字符串
    } else {
        return estrndup(c, len); //复制长度为len的字符串
    }
}

chr

character

string chr(int $ascii)

返回整数$ascii对应的ASCII码
例如:

echo chr(69);
echo chr(325);
//E E

超过256,将会对256取余,但是这不是PHP取余的,而是C语言的影响,源代码如下:

long c;
char temp[2];
/省略zend获取参数代码
temp[0] = (char)c; 
//将一个long类型转化为char时,发生强制类型转化,出现截断现象
/*
    325 => 0000 ... 0000 0001 0100 0101B (32bit)
    69 => ‭ 0000 ... 0000 0000 0100 0101B (32bit)
    69截断前后无变化,但是325截断以后恰好就是69 所以PHP代码中两个chr结果一样。
*/
temp[1] = '\0';

chunk_split

string chunk_split ( string $body [, int $chunklen = 76 [, string $end = "\r\n" ]] )

将一个字符串使用某个字符串等分开,使用$chunklen指定长度,$end指定结尾需要添加的字符串。默认长度为76,默认的分隔符号是\r\n,最后一部分的长度可能不到$chunklen
例如:

$a = '12312nsdkfugsdfbaekrg23895yu2893hrsdbfaf';
var_dump(chunk_split($a, 12, "EOF\n"));
/*string '12312nsdkfugEOF
sdfbaekrg238EOF
95yu2893hrsdEOF
bfafEOF
' (length=56)
*/

一般用于ASCII等分,如果$body是UTF8字符串,不是很好分割,首先UTF8是不定长编码,不能完全以3个字节的倍数拆分。例如:

$a = '你好啊';
var_dump(chunk_split($a, 3, ","));
//string '你,好,啊,' (length=12)

$a = '你1好2啊';
var_dump(chunk_split($a, 3, ","));
//由于不定长编码所以后面不能正确显示
//string '你,1�,�2�,��,' (length=15)

所以如果确实需要对汉字进行这种操作,并且混用了数字或者字母,那么最好使用定长编码,例如UTF-16,所以首先进行一下转换

$a = '你1好2啊';
$tmp = mb_convert_encoding($a, 'UTF-16', 'UTF-8');
var_dump(
        mb_convert_encoding(
                chunk_split($tmp, 2, 
                    mb_convert_encoding(',', 'UTF-16', 'UTF-8')
                ), 'UTF-8', 'UTF-16'));
//mb_convert_encoding(',', 'UTF-16', 'UTF-8')这里必须把,分隔符也要使用UTF16编码,不然加入字符串以后仍会出现乱码。另外一般情况下UTF16是两个字节,但是有时候也有4个字节的。

源代码分析:

chunks = srclen / chunklen;
restlen = srclen - chunks * chunklen; //计算剩余长度

//p和q分别是指向原串和目的串的指针 chunklen即为分割大小 p必须小于原串减去分割块大小 不然会出现拷贝了一些不属于自己的内存单元,比如原串大小为10 块大小为4 第一次拷贝0-3 第二次4-7 第三次8-11(这个不应该出现,所以p不能超过这里的7)
for (p = src, q = dest; p < (src + srclen - chunklen + 1); ) 
{
    memcpy(q, p, chunklen);
    q += chunklen; //移动目的串指针,准备追加结尾字符串
    memcpy(q, end, endlen);
    q += endlen; //移动目的串指针,准备复制下一个小块
    p += chunklen; //移动原串指针,准备使用下一个小块
}
//如果还有剩余的长度 再拷贝一次
if (restlen) 
{
    memcpy(q, p, restlen);
    q += restlen;
    memcpy(q, end, endlen);
    q += endlen;
}

convert_​uudecode

string convert_uudecode ( string $data )

解码一个uuencode编码字符串,可以搜索一下uuencode,是一种字符转换方式,类似于base64

convert_​uuencode

string convert_uuencode ( string $data )

使用uuencode编码字符串,函数与convert_uudecode是互逆函数。

count_​chars

mixed count_chars ( string $string [, int $mode = 0 ] )

统计字符串中所使用的字符信息,通过mode调整返回值,默认是0
- 0 返回数组,使用字节值作为key,包括所有的字节的使用情况(无论是否出现过)
- 1 同0,但是返回大于零(使用过)的字节值的次数
- 2 同1,但是返回等于零(从未使用过)的字节值出现次数
- 3 返回字符串,包含使用过的字符,按照ASCII排序
- 4 返回字符串,包含没使用过的字符,按照ASCII排序
通过mode可以看出,模式0的数组 = 模式1的数组 + 模式2的数组;模式3的字符串 + 模式4的字符串等于全部256个字符。
例如:

$test = 'abcdefgh1211111';
var_dump(count_chars($test, 0));
var_dump(count_chars($test, 1));
var_dump(count_chars($test, 2));
var_dump(count_chars($test, 3));
var_dump(count_chars($test, 4));
/*
array (size=256)
  ...
  84 => int 0
  85 => int 0
  86 => int 0
  87 => int 0
  88 => int 0
  89 => int 0
...
  93 => int 0
  94 => int 0
  95 => int 0
  96 => int 0
  97 => int 1
  98 => int 1
  99 => int 1
  100 => int 1
  101 => int 1
  102 => int 1
  103 => int 1
  104 => int 1
...
array (size=10)
  49 => int 6
  50 => int 1
  97 => int 1
  98 => int 1
  99 => int 1
  100 => int 1
  101 => int 1
  102 => int 1
  103 => int 1
  104 => int 1

array (size=246)
  0 => int 0
  1 => int 0
  2 => int 0
  3 => int 0
  4 => int 0
  5 => int 0
  6 => int 0
  7 => int 0
  8 => int 0
  9 => int 0
  10 => int 0
  more elements...

string '12abcdefgh' (length=10)

string '�   

 !"#$%&'()*+,-./03456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ijklmnopqrstuvwxyz{|}~€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬�' (length=246)

*/

源码猜测,既然每个模式之前存在一个的加法关系,所以我觉得应该是扫描一遍字符串,统计出使用情况,然后根据mode值,调整返回值。

//扫描统计
while (len > 0) 
{
    chars[*buf]++;
    buf++;
    len--;
}

if (mymode < 3) 
{
    array_init(return_value); //zend宏初始化数组
}

for (inx = 0; inx < 256; inx++) 
{
    switch (mymode) {
        case 0: //统计所有的出现次数
            add_index_long(return_value, inx, chars[inx]);//zend宏在return_val所指向的数组中加入inx => chars[inx]
            break;
        case 1:
            if (chars[inx] != 0)  //只加入不为0的
            {
                add_index_long(return_value, inx, chars[inx]);
            }
            break;
            case 2:
            if (chars[inx] == 0)  //只加入为0的
            {
                add_index_long(return_value, inx, chars[inx]);
            }
            break;
        case 3:
            if (chars[inx] != 0)  //出现过 放入字符串中 由于inx从0开始自增,所以自然而然的就是排序的 下同
            {
                retstr[retlen++] = inx;
            }
            break;
        case 4:
            if (chars[inx] == 0)  
            {
                retstr[retlen++] = inx;
            }
            break;
    }
}

ofo 该函数暂未考虑多字节,如果确实有需要,可能要使用自己实现的函数,试试md_XXX开头的函数。

crc32

int crc32 ( string $str )

生成CRC校验,第一次知道CRC概念的时候,还是在学习计算机网络的时候。

文档上说,由于PHP的int是带符号的,所以生成的CRC在大部分32位系统上呈现负数,你可能需要使用printf之类的函数,并且使用%u
与这个函数类似的还有md5() sha1() hash() crypt

explode

array explode ( string $delimiter , string $string [, int $limit ] )

使用一个字符串将另一个字符串分割成数组,这个函数需要先指定分割字符,然后是被分割的字符,最后是一个可选的限制参数
- 0 返回仅有一个元素的数组
- >0 返回最多limit个元素
- <0 返回的数组中,不包括最后的-limit个元素

$number = '123,123,2,321,434,543,3';
var_dump(explode(',', $number));
var_dump(explode(',', $number, 0));
var_dump(explode(',', $number, 5));
var_dump(explode(',', $number, -5));
/*
array (size=7)
  0 => string '123' (length=3)
  1 => string '123' (length=3)
  2 => string '2' (length=1)
  3 => string '321' (length=3)
  4 => string '434' (length=3)
  5 => string '543' (length=3)
  6 => string '3' (length=1)

array (size=1)
  0 => string '123,123,2,321,434,543,3' (length=23)

array (size=5)
  0 => string '123' (length=3)
  1 => string '123' (length=3)
  2 => string '2' (length=1)
  3 => string '321' (length=3)
  4 => string '434,543,3' (length=9)

array (size=2)
  0 => string '123' (length=3)
  1 => string '123' (length=3)

*/

可以发现,当limit没有写的时候,会完全分割开;
为0时,相当于返回原串,为1,效果应该和0相同
为其他正数时,分割出的数组至少保证前limit-1个元素是分割开的,剩余的全部合在一起
为负数时,就是去掉末尾的-limit个元素,只保留前几个元素

fprintf

int fprintf ( resource $handle , string $format [, mixed $args [, mixed $... ]] )

将使用$format格式化后的字符串写入流,该函数使用方法的C语言的类似。
$handle一般使用fopen函数打开后返回的资源变量,$format和C语言一致,%d %c %s什么的。

get_​html_​translation_​table

hex2bin

string hex2bin ( string $data )

bin2hex互补,将十六进制的字符串转为ASCII字符串。

$a = 'abcd';
echo bin2hex($a);
echo hex2bin(bin2hex($a));

源码上,应该需要进行a或者A的判断,然后把原来的右移,改为左移。
一起看看:

for (i = j = 0; i < target_length; i++) {
    char c = old[j++]; //取出16进制编码的字符串的某一个字符 代表高4bit
    if (c >= '0' && c <= '9') {
        str[i] = (c - '0') << 4;
    } else if (c >= 'a' && c <= 'f') {
        str[i] = (c - 'a' + 10) << 4;
    } else if (c >= 'A' && c <= 'F') {
        str[i] = (c - 'A' + 10) << 4;
    } else {
        efree(str);
        return NULL;
    }
    c = old[j++]; //低4bit
    if (c >= '0' && c <= '9') {
        str[i] |= c - '0';  //进行与运算 低4位之前全是0 现在与上新的低4bit,组成一个完整的8bit字符
    } else if (c >= 'a' && c <= 'f') {
        str[i] |= c - 'a' + 10;
    } else if (c >= 'A' && c <= 'F') {
        str[i] |= c - 'A' + 10;
    } else {
        efree(str);
        return NULL;
    }
}

html_​entity_​decode

string html_entity_decode ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") ]] )

htmllentities函数互逆

htmlentities

string htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] )

几乎和htmlspecialchars,除了该函数会转换所有具有HTML实体的字符。如果字符串中有中文最好使用htmlspecialchars函数,否则可能会出现乱码。

htmlspecialchars_​decode

string htmlspecialchars_decode ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 ] )

htmlspecialchars互逆。

htmlspecialchars

string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] )

将特殊字符转换为HTML实体。
通过设置$flags可以设置一下处理细节,比如不转换单引号,也可以设置文档类型
通过$encoding设置字符串的编码,默认使用当前的字符。
如果关闭了double_encode,就不会转换现有的HTML实体。
该函数能转换的字符有限只有:

字符替换后的结果
&&amp;
&quot;
&#039; /&apos;
>&lt;
<&gt;

implode / join

string implode ( string $glue , array $pieces )
string implode ( array $pieces )

使用(或者不用)$glue将数组合并成一个字符串,各元素之前使用$glue隔开,和explode互补。

$arr = ['1', '2', '3'];
var_dump(implode($arr));
var_dump(implode(',', $arr));
/*
string '123' (length=3)

string '1,2,3' (length=5)
*/

这个数组的元素可以使用整型,浮点型,字符串, 对象或者混用。对象必须自己实现__toString()方法.

lcfirst

string lcfirst ( string $str )

使一个字符串的第一个字符小写(大写请参考ucfirst)

$a = 'Acd Rty';
echo lcfirst($a);
//acd Rty

源代码:

r = str;
*r = tolower((unsigned char) *r);

levenshtein

int levenshtein ( string $str1, string $str2

计算两个字符之间的编辑距离,即通过替换,插入,删除等操作把$str1替换成$str2的最短距离。
最短距离,可以近似的描述两个单词之间的相似性。

localeconv

ltrim

string ltrim ( string $str [, string $character_mask ] )

删除字符串开头(左边)的某些字符,与rtrim类似

md5_​file

string md5_file ( string $filename [, bool $raw_output = false ] )

计算文件的MD5散列值,相似的函数还有sha1_file

md5

string md5 ( string $str [, bool $raw_output = false ] )

计算字符串的MD5散列值

metaphone

money_​format

nl_​langinfo

nl2br

string nl2br ( string $string [, bool $is_xhtml = true ] )

new line to br
在字符串中的新行中插入<br/>或者<br> ,类似于做字符串替换。

number_​format

ord

int ord ( string $string

返回字符的ASCII编码,与chr是互逆函数。

parse_​str

print

int print( string $arg)

与echo相似,但是print仅能使用一个参数,这是语言结构,可以不用( ) ;

printf

类似于C语言的printf

quoted_​printable_​decode

quoted_​printable_​encode

quotemeta

rtrim

string rtrim ( string $str [, string $character_mask ] )

删除字符串右边的空白字符(或者自定义字符)
细节描述,请参考ltrim

setlocale

similar_​text

soundex

sprintf

sscanf

str_​getcsv

str_​ireplace

str_​pad

string str_pad ( string $input , int $pad_length [, string $pad_string = " " [, int $pad_type = STR_PAD_RIGHT ]] )

字符串充填,将字符串使用另一个字符串(在左边,右边,或者同时)充填至指定长度。

var_dump(str_pad('123', 6, 'A', STR_PAD_LEFT));
var_dump(str_pad('123', 6, 'ABCD', STR_PAD_LEFT));

var_dump(str_pad('123', 6, 'A', STR_PAD_BOTH));
var_dump(str_pad('123', 6, 'AB', STR_PAD_BOTH));
/*
string 'AAA123' (length=6)
string 'ABC123' (length=6)
string 'A123AA' (length=6)
string 'A123AB' (length=6)
*/

从输出结果可以看到,如果不能完全被充填,用来充填的字符串会被缩短,
另外如果使用STR_PAD_BOTH方式,左右两边如果不能均分,右边会多一点。
来看看源代码究竟是怎么回事儿吧:

switch (pad_type_val) {
    case STR_PAD_RIGHT:
        left_pad = 0;
        right_pad = num_pad_chars;
        break;

    case STR_PAD_LEFT:
        left_pad = num_pad_chars;
        right_pad = 0;
        break;

    case STR_PAD_BOTH:
        left_pad = num_pad_chars / 2;
        //左边充填长度等于充填长度的一半
        right_pad = num_pad_chars - left_pad;
        //右边充填长度等于充填长度减去左边的长度 由于计算机除法的特殊性,导致左边充填长度 小于右边的,且刚好差一
        break;
}


for (i = 0; i < left_pad; i++)
    result[result_len++] = pad_str_val[i % pad_str_len]; //在结果字符串中放入左边需要充填的字符,通过%循环放置

memcpy(result + result_len, input, input_len); //复制原始字符串
result_len += input_len; //更新长度

for (i = 0; i < right_pad; i++)
    result[result_len++] = pad_str_val[i % pad_str_len];//充填右边

在我们看了源代码之后,之前的疑问就解决了。

str_​repeat

string str_repeat ( string $input , int $multiplier )

将一个字符串重复$multiplier次,并且返回结果。这个函数有点像:

function repeat($str, $k)
{
    $res = '';
    for ($i = 0; $i < $k; $i++) {
        $res .= $str;
    }
    return $res;
}

调用一下试试:

echo str_repeat('123', 0); //返回空串
echo str_repeat('123', 3); //正常
echo str_repeat('123', -3); //报错

源码猜测,应该是提前分配空间 然后复制,或者直接使用memcpy:

result = (char *)safe_emalloc(input_len, mult, 1); //利用zend宏分配大小 分配的大小等于input_len * mult + 1 满足复制要求

if (input_len == 1) {
    memset(result, *(input_str), mult); //特别的 如果输入的字符串只有一个字符,直接把这片内存区域设置为这个字符
} else {
    char *s, *e, *ee;
    int l=0;
    memcpy(result, input_str, input_len);
    s = result;
    e = result + input_len;
    ee = result + result_len;

    while (e<ee) {
        l = (e-s) < (ee-e) ? (e-s) : (ee-e);
        memmove(e, s, l);
        e += l;
    }
}

str_​replace

mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

$subject中,含有$search的部分替换为$replace,如果设置了$count,将会返回发生替换的次数。

$count = 0;
var_dump(str_replace('a', 'b', 'aaaaa', $count));
echo $count;
//bbbbb 5

str_replace不仅仅可以用于字符串,也可以用于数组。

var_dump(str_replace('a', 'b', ['a', 'b', 'aa']));
/*
array (size=3)
  0 => string 'b' (length=1)
  1 => string 'b' (length=1)
  2 => string 'bb' (length=2)
*/
var_dump(str_replace(1, 2, [1, 12,  111]));
/*
array (size=3)
  0 => string 'b' (length=1)
  1 => string 'b' (length=1)
  2 => string 'bb' (length=2)
*/

数组里面的元素,会被当做字符串。
这个函数源码使用了太多了的宏,看不懂。。。。QAQ

str_​rot13

string str_rot13 (string $str)

对字符串执行ROT13转换

echo str_rot13('abcdxyzm123');
//nopqklmz123
$arr = '';
for($i = 33; $i <= 126; $i++){
    $arr .=  chr($i);
}
var_dump($arr);
var_dump(str_rot13($arr));
/*
string '!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~' (length=94)

string '!"#$%&'()*+,-./0123456789:;<=>?@NOPQRSTUVWXYZABCDEFGHIJKLM[\]^_`nopqrstuvwxyzabcdefghijklm{|}~' (length=94)
对比可以看出这个函数,仅仅会影响A-Za-z的字符。
*/

应该是可以通过简单的取余就可以实现,另外不知道这个函数有啥用?

str_​shuffle

string str_shuffle ( string $str )

随机打乱一个字符串。
源代码

n_elems = len;

if (n_elems <= 1) {
    return;
}//长度不足1 无需打乱

n_left = n_elems;

while (--n_left) { //循环len次
    rnd_idx = php_rand(TSRMLS_C);
    RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX); 
    //利用宏产生随机数,猜测范围应该在0-n_left之间
    if (rnd_idx != n_left) {
        temp = str[n_left];
        str[n_left] = str[rnd_idx];
        str[rnd_idx] = temp;
    } //交换
}

str_​split

array str_split ( string $string [, int $split_length = 1 ] )

将字符串转化为数组,数组中每个元素的字节不超过$split_length

var_dump(str_split('12345', 3));
/*
array (size=2)
  0 => string '123' (length=3)
  1 => string '45' (length=2)
*/

不用于explode使用分割字符将字符串分割为数组,str_split只能按照固定大小分割,分割出来的数组,除了最后一个元素大小不一样,其余元素字节数应该是固定的
如果要对多字节字符串按照字符分割(不是字节),建议转化为定长编码,然后按照一定的倍数,改写函数。

str_​word_​count

strcasecmp

int strcasecmp ( string $str1, string $str2)

二进制安全比较字符串,不区分大小写。区别于strcmp

二进制安全:所谓二进制安全指的是在一个二进制文件上所执行的不更改文件内容的功能和操作,本质上是讲操作输入作为元素的、无任何特殊格式意义的数据流。比如用PHP的string存储图形或者音频的二进制数据流,那么里面一些比如\0的字节,不应该作为字符串结束标志。

var_dump(strlen("123 \0 123\0"));
//int 10
echo strcasecmp('ab', 'Ab'); //0
echo strcasecmp('ab', 'A');  //1

strchr

strstr的别名

别名的出现 一方面是两个名称都非常合适,另一方面是为了确保向后兼容性。

strcmp

int strcmp ( string $str1, string $str2)

strcasecmp唯一的不同就是不是区分大小写的。在这个函数里面小写字母比大写字母大,所以推测函数使用ASCII直接进行比较。

echo strcmp('Ab', 'a');  //-1

strcoll

int strcoll ( string $str1 , string $str2 )

基于区域设置的字符串比较,非二进制安全。
区域设置通过setlocale修改

strcspn

strip_​tags

string strip_tags ( string $str [, string $allowable_tags ] )

去除字符串中的HTML标签,如果设置了$allowable_tags那么这里面的标签不会去掉。

var_dump(strip_tags('<p><span>123</span>456</p>');
//string '123456' (length = 6)
var_dump(strip_tags('<123>456</123>'));
//string '456' (length=3)

这个函数并不是完全针对HTML标签,实际上只要包含在<>的都会去掉。

stripcslashes

string stripcslashes ( string $str )

这个函数与addcslashes是一个相反的函数,也就是把之前添加了C语言风格的\n,\r什么的去掉。

var_dump(stripcslashes('\n\n\n'));
/*
string '


' (length=3)
*/

stripos

mixed stripos ( string $haystack , string $needle [, int $offset = 0 ] )

字符串查找函数,查找$haystack$needle首次出现的位置,这个函数不区分大小写。
找不到时会返回false,字符串从0开始编号

var_dump(stripos('ABCDEFG', 'DE')); //3
var_dump(stripos('ABCDEFG', 'de')); //3
var_dump(stripos('ABCDEFG', 'K')); //false

stripslashes

string stripslashes ( string $str )

这个函数与stripcslashes类似,都拥有一个相反的函数,该函数的相反函数就是addslashes.

$str = addslashes("\\\\");
var_dump($str);
var_dump(stripslashes($str));
/*
string '\\\\' (length=4)

string '\\' (length=2)

*/

stristr

string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] )

默认返回在$haystack中第一次出现$needle到字符串尾的所有字符串。如果设置了$before_needle为true,那么会返回,从字符串头到第一次出现$needle处的所有字符串(不包括$needle)。如果找不到这样的元素会返回false。这个函数是strstr的 不区分大小写版本,猜测函数中的i表示ignore的意思。

echo stristr('1234567', '4'); //4567
echo stristr('1234567', '8'); //false
echo stristr('1234567', '4', true); //

strlen

int strlen ( string $string )

获取字符串的长度,类似于C语言函数,但是不完全相同,并不会把字符\0作为字符串的结束符。

echo strlen("123 \0 456");
//输出9 6个可见字符,2个空格,1个\0 而不是输出4

这是一个以单字节ASCII为基础的函数,如果需要测量多字节字符串,参考md_strlen()

strnatcasecmp

strnatcmp

strncasecmp

strncmp

strpbrk

strpos

mixed strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

$haystack中查找$needle首次出现的位置,如果设置了$offset,就会从当前开始查找,找不到输出false

echo strpos('12345678', '123'); //0
echo strpos('12345678', '123', 2);  //false

如果为负值,文档上说会从距离尾部-$offset处,开始查找。但是实际在5.8版本测试时,报错!

strrchr

string strrchr ( string $haystack , mixed $needle )

查找指定字符在$haystack中最后出现的位置及其之后的所有字符串。$needle可以使用字符串,但是仅使用第一个字符。如果使用了数字,将会转换为其所对应的ASCII字符。

echo strrchr('12345613456', '123'); //13456
echo strrchr('1234561A3456', 65); //A3456

strrev

string strrev ( string $string )

反转字符串,相当于把一个字符倒序遍历。

echo strrev('1234') // 4321

strripos

int strripos ( string $haystack , string $needle [, int $offset = 0 ] )

查找指定字符串首次出现的位置,通过offset设置字符串的起始位置。

echo strripos('1234523', '23'); //5
echo strripos('1234523', '23', 4); //5
echo strripos('1234523', '23', -4); //1

如果offset为正数,那么查找的范围为offset到字符串尾部,如果为负数,那么查找范围为0~offset处。找不到时会返回false,该函数是不区分大小写的。

strrpos

int strripos ( string $haystack , string $needle [, int $offset = 0 ] )

函数strripos的不区分大小写版本。

strspn

strstr

stristr函数的不区分大小写版本,用法相同,二进制安全函数。

strtok

strtolower

string strtolower ( string $string )

将字符串中的字母全部转换为小写,字母与区域有关。

echo strtolower('AbCd'); //abcd

strtoupper

string strtoupper( string $string)

将字符串中的字母全部转换为大写,与strtolower不完全可逆。

strtr

substr_​compare

substr_​count

substr_​replace

substr

trim

string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )

函数ltrimrtirm结合使用的效果,同时去除字符串两侧的空白字符(或者指定字符)。

ucfirst

string ucfirst ( string $str )

lcfirst相似,把字符串的第一个字母大写,同样对于字母而言,转换依赖区域设置。

ucwords

string ucwords ( string $str [, string $delimiters = " \t\r\n\f\v" ] )

将字符串中的每个单词的首字母大写,单词之间,用$delimiters分割。

echo ucwords('my name is li lei');
//My Name Is Li Lei

vfprintf

int vfprintf ( resource $handle , string $format , array $args )

vprintf函数的结果输出到$handle的方法。

vprintf

int vprintf ( string $format , array $args )

printf类似,但是vprintf接受一个数组参数,而不是可变参数。

vprintf("%d %d %d", [1,2,3,4]);
//输出1 2 3 参数可以多,但是绝对不能少

返回的int表示字符串的长度。

vsprintf

string vsprintf ( string $format , array $args )

vprintf相似,不输出字符,而是返回字符串

wordwrap

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gscsdlz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值