`
dengbaoleng
  • 浏览: 1162817 次
文章分类
社区版块
存档分类
最新评论

PHP内置函数分析之strlen 与 mb_strlen

 
阅读更多

声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。
博客地址:PHP技术博客在CSDN也会同步更新的哦.
欢迎转载,转载请注明出处

在PHP里 有两个计算 字符串个数的函数
一个是 strlen,一个是mb_strlen;
先来看看帮助手册的定义

  • strlen

strlen — 获取字符串长度
int strlen ( string $string )
返回给定的字符串 string 的长度。

  • mb_strlen

intmb_strlen( string$str[, string$encoding] )

返回给定的字符串 string 的长度。

encoding参数为字符编码。如果省略,则使用内部字符编码。

这么看 除了mb_strlen可以传递一个 字符编码好像没有其他区别

写一个PHP程序来看看

[php]
$a="我是s斯t人";
echo strlen($a);
echo "<br>";
echo mb_strlen($a,'utf8');
[/php]


输出结果
14
6
很明显 strlen对于中文来讲,每个汉字占三个字节,$a的字节数就是14,说明 strlen计算的是字符串所占的字节数
在mb_strlen计算时,如果encoding设置为utf8,那么,中文将占一个字节 那么$a就是6

需要注意的是 mb_strlen并不是PHP内置函数,需要修改php.ini,开启 php_mbstring
好了..
我们下面就深入到PHP内核源码去看看两个函数的不同.
先看mb_strlen的定义

[c]
PHP_FUNCTION(mb_strlen)
{
int n;
mbfl_string string;
char *enc_name = NULL; int enc_name_len;

mbfl_string_init(&string);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
RETURN_FALSE;
}

string.no_language = MBSTRG(language);
if (enc_name == NULL) { string.no_encoding = MBSTRG(current_internal_encoding);
} else {
string.no_encoding = mbfl_name2no_encoding(enc_name);
if (string.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name); RETURN_FALSE;
}
}

n = mbfl_strlen(&string);
if (n >= 0) {
RETVAL_LONG(n);
} else {
RETVAL_FALSE;
}
}
[/c]

mbfl_string 是一个结构体

[c]
typedef struct _mbfl_string {
enum mbfl_no_language no_language;
enum mbfl_no_encoding no_encoding;
unsigned char *val; unsigned int len;
} mbfl_string;

[/c]


看定义就知道,这两个保存了当前字符串的语言,编码,保存的值和长度
mbfl_string_init(&string);
这个函数是初始化string;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
RETURN_FALSE;
}
这里接收传递过来的两个参数,也就是前面看到的 string和encoding,
enc_name保存编码,enc_name_len保存编码名字的长度
string.no_language = MBSTRG(language);
展开后
#define MBSTRG(v) (mbstring_globals.v)
这里将mbstring的language赋给string的no_language;

[c]

if (enc_name == NULL) {//如果没有手动设置编码,那么就使用PHP内置的编码 这个时候就与strlen相同
string.no_encoding = MBSTRG(current_internal_encoding);
}else {
//检查是否是有效的编码
string.no_encoding = mbfl_name2no_encoding(enc_name);
//如果传递来的编码无效 抛出异常
if (string.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
RETURN_FALSE;
}
}
n = mbfl_strlen(&string);//计算字符串的长度
[/c]

原来这个函数里只是验证编码
真正计算长度的函数是mbfl_strlen

[c]
int mbfl_strlen(mbfl_string *string)
{
int len, n, m, k;
unsigned char *p;
const unsigned char *mbtab;
const mbfl_encoding *encoding;
//验证编码是否有效
encoding = mbfl_no2encoding(string->no_encoding);
if (encoding == NULL || string == NULL) {
return -1;
}

len = 0;
//下面是几种不同的
if (encoding->flag & MBFL_ENCTYPE_SBCS) {//是单字节字符集 直接返回
len = string->len;
} else if (encoding->flag & (MBFL_ENCTYPE_WCS2BE | MBFL_ENCTYPE_WCS2LE)) { //宽字节每个字占2位
len = string->len/2;
} else if (encoding->flag & (MBFL_ENCTYPE_WCS4BE | MBFL_ENCTYPE_WCS4LE)) {//宽字节每个字占4位
len = string->len/4;
} else if (encoding->mblen_table != NULL) { //mblen_table是做什么的没搞清楚,望赐教
mbtab = encoding->mblen_table;
n = 0;
p = string->val;
k = string->len;
/* count */
if (p != NULL) {
while (n < k) {
m = mbtab[*p];
n += m;
p += m;
len++;
};
}
} else { //其他编码 转换成mbfl_no_encoding_wchar再计算
/* wchar filter */
mbfl_convert_filter *filter = mbfl_convert_filter_new(
string->no_encoding,
mbfl_no_encoding_wchar,
filter_count_output, 0, &len);
if (filter == NULL) {
return -1;
}
/* count */
n = string->len;
p = string->val;
if (p != NULL) {
while (n > 0) {
(*filter->filter_function)(*p++, filter);
n--;
}
}
mbfl_convert_filter_delete(filter);
}

return len;
}
[/c]

注释很清楚了..
mb_strlen就是根据encoding不同的编码,来分别计算..好像可以计算世界大部分不同的编码格式
相比 mb_strlen ,strlen就简单的多多的多的多了
开始 没有找到 strlen定义的地方,
它在 Zend/zend_builtin_functions.c里定义的

[c]
ZEND_FUNCTION(strlen)
{
char *s1;
int s1_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) {
return;
}

RETVAL_LONG(s1_len);
}
[/c]

很简单 只是获取长度而已...

这下 他们俩的区别就很清楚了...

分享到:
评论

相关推荐

    浅析PHP中strlen和mb_strlen的区别

    首先,strlen是一个内置函数,用于计算字符串中的字符数。但需要注意的是,strlen计算的是字符串所占用的字节数。这意味着在处理UTF-8编码的字符串时,一个中文字符由于占用3个字节,因此在strlen的计算下会被计为3...

    php strlen mb_strlen计算中英文混排字符串长度

    `strlen`函数是PHP内置的字符串长度函数,它返回的是字符串的字节数。对于英文字符,每个字符占用一个字节,因此`strlen`返回的长度就是英文字符串的实际字符数。然而,当字符串中包含中文字符时,由于UTF-8编码的...

    PHP中strlen()和mb_strlen()的区别浅析

    需要特别注意的是,mb_strlen()函数并不是PHP的内置核心函数,因此在使用之前必须确保已经加载了php_mbstring.dll扩展。这通常在php.ini配置文件中完成,需要确认"extension=php_mbstring.dll"这一行没有被注释掉。...

    PHP程序设计-3期(KC016) 2.8.1字符串长度 常见问题.docx

    首先,`strlen()` 函数是PHP内置的函数,用于返回字符串的长度,即字符串中的字符数量。但需要注意的是,`strlen()` 函数仅适用于单字节字符集,如ASCII,它并不考虑多字节字符(如UTF-8编码下的中文字符)。因此,...

    php2go:使用Golang来实现PHP的常见内置函数

    使用Golang来实现PHP的通用内置函数。 已经实现了约140多种功能。 安装 go get github.com/syyongx/php2go 要求 达到1.10或更高。 PHP函数 日期/时间功能 time() strtotime() date () checkdate () sleep () usleep...

    php mb_substr()函数截取中文字符串应用示例

    在进行字符串操作时,我们经常使用PHP内置的字符串函数来提取我们需要的部分,比如substr()函数。但是,当字符串包含多字节字符集,如中文、日文或韩文时,使用substr()函数可能会出现截取错误,因为这类函数默认是...

    php截取字符串函数的方法_.docx

    通过结合`wordwrap()`和`mb_strlen()`等内置函数,实现了较为灵活和实用的功能。尽管存在一定的局限性,但在大多数应用场景下都能满足需求。未来可以进一步改进该函数,以提高其对不同语言的支持能力及性能表现。

    php-mbstring-5.4.16-36.el7_1.x86_64.rpm

    多国语言并存就意味着多字节,PHP内置的字符串长度函数strlen无法正确处理中文字符串,它得到的只是字符串所占的字节数。对于GB2312的中文编码,strlen得到的值是汉字个数的2倍,而对于UTF-8编码的中文,就是1~3倍的...

    PHP实现Javascript中的escape及unescape函数代码分享_.docx

    然而,PHP并没有直接对应的内置函数,但可以通过自定义函数来实现类似的功能。本文将介绍如何在PHP中模拟JavaScript的`escape`和`unescape`。 首先,我们来看如何实现`unescape`功能。在JavaScript中,`unescape`...

    php5.4 中文函数

    例如,`mb_strlen()`用于计算字符串中字符的数量,`mb_strpos()`查找子串的位置。 2. **iconv**:用于字符编码转换,如`iconv('GBK', 'UTF-8', $str)`将GBK编码的字符串转为UTF-8。 3. **preg_replace**:正则...

    PHP程序设计-3期(KC016) 2.8.1字符串长度习题.doc

    1. `strlen()`函数是PHP内置的函数,用于计算字符串的长度,返回的是字符串中的字节数。在英文字符集中,每个字符占用一个字节,因此`strlen()`返回的就是字符个数。但在UTF-8编码中,中文字符通常占用三个或四个...

    PHP 计算字符串长度

    PHP提供了内置的`strlen()`函数,用于获取字符串的长度,即字符的数量。下面我们将深入探讨这个函数以及与字符串长度计算相关的知识点。 ### strlen()函数 `strlen()`是PHP的核心函数之一,它返回给定字符串的长度...

    php使用自定义函数实现汉字分割替换功能示例

    首先,PHP的内置函数可能无法满足所有特定需求,这时就需要创建自定义函数来处理复杂情况。在本例中,我们创建了一个名为`mbstringToArray`的函数,该函数接收两个参数:要处理的字符串和字符集编码。 ```php ...

    php实现字符串翻转的方法

    2. PHP内置函数对字符串操作的支持 - explode() 函数 explode() 函数用于使用字符串分割字符串。在本例中,它没有直接用于字符串反转,但通常可以用来以特定字符(如空格)为分隔符分割字符串,然后对得到的数组...

    php中计算中文字符串长度、截取中文字符串的函数代码

    然而,并非所有PHP环境都预装了专门处理多字节字符集(如UTF-8)的内置函数,如`mb_strlen`和`mb_substr`。当这些函数不可用时,开发者需要自定义函数来实现相同的功能。 `abslength`函数是用于计算中文字符串长度...

    php字符串函数集锦

    PHP提供了丰富的内置函数来操作和处理字符串,使得开发者可以高效地进行文本处理。以下是一些重要的PHP字符串函数及其详细说明: 1. **strlen()**:用于计算字符串的长度。例如,`strlen("你好")`将返回5,包括空格...

    PHP网站编程技术-字符串处理.doc

    如果是字符串,则利用`mb_detect_encoding()`检测字符串的编码格式,然后使用内置函数`strrev()`实现字符串翻转。如果输入的参数非字符串,函数会给出相应提示。 在处理字符串数组的过程中,使用`mb_strlen()`计算...

    利用PHP函数计算中英文字符串长度的方法

    本文将详细介绍如何利用PHP内置函数以及正则表达式来计算中英文字符串的长度,并对不同的方法进行对比分析。 首先需要明确的是,PHP中的strlen()函数用于获取字符串的字节长度,而不是字符长度。这意味着对于英文...

    基于PHP的Unicode编码转换程序.zip

    PHP提供了多种内置函数来支持Unicode,例如`mb_convert_encoding()`函数,它可以将字符串从一种编码转换到另一种编码,包括UTF-8、GBK等常见的Unicode编码格式。此外,`iconv()`函数也是一个常用的编码转换工具,它...

Global site tag (gtag.js) - Google Analytics