字符串 (String)

字符串是一系列字符的集合。如 “abc”. 在 PHP 中,一个字符代表一个字节,一个字节 (Byte) 有 8 比特 (bit). PHP 仅支持 256 字符集,因此 PHP 本身不支持 Unicode 字符集.

This means that PHP only supports a 256-character set, and hence does not offer native Unicode support.

那么 PHP 是如何做到支持 Unicode 字符集的,答案是在于 PHP 底层字符串实现中,PHP 的字符串是一个由字节组成的数组再加上一个整数指明缓冲区长度。并没有如何将字节转换字符的信息。那么字符串如何编码和解码,这些全部由使用者来决定编码方式.

字符串会被按照该脚本文件相同的编码方式来编码。因此如果一个脚本的编码是 ISO-8859-1,则其中的字符串也会被编码为 ISO-8859-1,以此类推。不过这并不适用于激活了 Zend Multibyte 时;此时脚本可以是以任何方式编码的(明确指定或被自动检测)然后被转换为某种内部编码,然后字符串将被用此方式编码存入由字节组成的数组.

The answer is that string will be encoded in whatever fashion it is encoded in the script file. Thus, if the script is written in ISO-8859-1, the string will be encoded in ISO-8859-1 and so on. However, this does not apply if Zend Multibyte is enabled; in that case, the script may be written in an arbitrary encoding (which is explicitly declared or is detected) and then converted to a certain internal encoding, which is then the encoding that will be used for the string literals.

通过例子说明一下,比较易懂.

// unicode 字符集下 utf-8 编码方式
$s = '严';
var_dump(strlen($s)); // $len = strlen($s); //
/**
* int(228) 对应二进制为 11100100
* int(184) 对应二进制为 10111000
* int(165) 对应二进制为 10100101
*/
for ($i = 0; $i < $len; $i++) {
var_dump(ord($s[$i]));
}

“严” 这个字怎么会是 3 个,而不是一个呢,由于 strlen 返回的是字节数,而非字符数. PHP 底层字符串实现方式。是由字节组成的数组的。因此可以得出 PHP 对于 “严” 在 utf-8 编码方式的底层实现是由 3 个字节组成数组,而这些字节不超过 256 的值,这就是 PHP 编码方式。而解码则是通过文件编码方式取对应字节数目来找对应字面字符.

而这些数值代表什么意思,则是 utf-8 的编码方式了。严的Unicode 是 4E25(100111000100101),根据上表,可以发现 4E25 处在第三行的范围内(0000 0800 - 0000 FFFF),因此严的 UTF-8 编码需要三个字节,即格式是 1110xxxx 10xxxxxx 10xxxxxx。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的 x,多出的位补 0。这样就得到了,严的 UTF-8 编码是 11100100 10111000 10100101,转换成十六进制就是 E4B8A5。

非二进制安全

字符串由什么值来组成并无限制;特别的,其值为 0(“NUL bytes”)的字节可以处于字符串任何位置 (不过有几个函数,在本手册中被称为非 “二进制安全” 的,也许会把 NUL 字节之后的数据全都忽略). 在 C 语言里字符串都以 \0 作为结束符,而 PHP 底层是由 C 语言编写的,因此某些函数遇到 \0 的 会忽略之后字节的,从而影响程序逻辑和结果.

$string1 = "Hello";
$string2 = "Hello\0World";
// 非二进制安全, \0 在 ascii 表是 NUL '\0'
var_dump(strcoll($string1, $string2)); // 0
// 二进制安全
var_dump(strcmp($string1, $string2)); // -6

语法

  1. 单引号
  2. 双引号
  3. heredoc 语法结构
  4. nowdoc 语法结构 (自 PHP 5.3.0 起)

单引号

定义一个字符串的最简单的方法是用单引号把它包围起来 (字符 '), 单引号无法解析变量和转义字符,要表达单引号本身则在单引号前面加个反斜杠 (), 要表达反斜杠 () 则在反斜杠前加个反斜杠 ()

// this is string
echo 'this is string';
// I'm your father
echo 'I\'m your father';
// C:\*.*?
echo 'C:\\*.*?';

双引号

用双引号 (") 把字符包围起来,PHP 双引号会把特殊字符解释以下转义序列.

双引号还有一个特点,就是会解析变量。变量解析有两个解析语法,一个是简单和一个复杂的.

  • 简单解析语法:

简单的解析方式当 PHP 解析器遇到一个美元符号($)时,它会和其它很多解析器一样,去组合尽量多的标识以形成一个合法的变量名。可用花括号限制解析范围.

$juice = 'apple';
$juices = 'apple\s';
// He drank some apple juice
echo "He drank some $juice juice." . PHP_EOL;
// He drank some apple\s juice
echo "He drank some $juices juice" . PHP_EOL;
// He drank some apples juice
echo "He drank some {$juice}s juice" . PHP_EOL;

类似的,一个 array 索引或一个 object 属性也可被解析。数组索引要用方括号(])来表示索引结束的边际,对象属性则是和上述的变量规则相同。

  • 复杂解析语法

这并不因为语法复杂而被称为复杂,而是因为它允许使用复杂的表达式.

任何具有 string 表达的标量变量,数组单元或对象属性都可使用此语法。只需简单地像在 string 以外的地方那样写出表达式,然后用花括号 {和} 把它括起来即可。由于 { 无法被转义,只有 $ 紧挨着 { 时才会被识别。可以用 {$ 来表达 {$。

 echo "This works too: {$obj->values[3]->name}";
echo "This works too: {$obj->values[3]->name}";
echo "This is the value of the var named by the return value of getName(): {${getName()}}";

Heredoc

第三种表达字符串的方法是用 heredoc 句法结构:<<<。在该运算符之后要提供一个标识符,然后换行。接下来是字符串 string 本身,最后要用前面定义的标识符作为结束标志。

结束时所引用的标识符必须在该行的第一列,而且,标识符的命名也要像其它标签一样遵守 PHP 的规则:只能包含字母、数字和下划线,并且必须以字母和下划线作为开头。

Heredoc 结构就象是没有使用双引号的双引号字符串,这就是说在 heredoc 结构中单引号不用被转义,但是上文中列出的转义序列还可以使用

$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
$juice = 'apple';
$str1 = <<<EOD
He drank some $juice juice.
EOD;
// 运用在函数中
function foo()
{
static $bar = <<<LABEL
Nothing in here...
LABEL;
}
// 运用在类中
class foo
{
const BAR = <<<FOOBAR
Constant example
FOOBAR; public $baz = <<<FOOBAR
Property example
FOOBAR;
}

Nowdoc

Nowdoc 结构很象 heredoc 结构,但是 nowdoc 中不进行解析操作。这种结构很适合用于嵌入 PHP 代码或其它大段文本而无需对其中的特殊字符进行转义

一个 nowdoc 结构也用和 heredocs 结构一样的标记 <<<, 但是跟在后面的标识符要用单引号括起来,即 <<<‘EOT’。Heredoc 结构的所有规则也同样适用于 nowdoc 结构,尤其是结束标识符的规则。

$str = <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;

单引号比双引号快?

在 PHP 7 之前,假如字符串没有存在变量替换,单引号和双引号几乎一样的。如果存在变量替换的时候是单引号比双引号要快. PHP 7 之后,却是不同,双引号与单引号几乎一样性能.

$singleCode = 'this is single string';
$doubleCode = "this is single string";
echo $singleCode;
echo $doubleCode;

第 0 到第 3 条 op line, 可以看出在没有使用变量替换的情况下,双引号的和单引号所产生的 Opcodes 是一样的.

$var = 'String';
$single_quotes_var = 'This is a '.$var;
$double_quotes_var = "This is a $var"; echo $single_quotes_var;
echo $double_quotes_var;

第 1 到 2 条与第 4 到 5 条,Opcodes 条数是一样的. PHP 7 把之前 INIT_STRING, ADD_STRING, ADD_VAR 的步骤优化成一条。优化成 FAST_CONCAT

存取和修改字符串中的字符

string 中的字符可以通过一个从 0 开始的下标,用类似 array 结构中的方括号包含对应的数字来访问和修改,比如 $str [42]。可以把 string 当成字符组成的 array. 也可以使用花括号来访问和修改 注意的是字符串操作最好针对单字节编码操作,因为字符串在 PHP 底层是字节组成的数组,用花括号 / 方括号操作多字节字符串很不安全.

在 PHP7.1.0, 还支持负字符串偏移量

用超出字符串长度的下标写入将会拉长该字符串并以空格填充。非整数类型下标会被转换成整数。

$str = 'This is a test.';
$first = $str[0];
$third = $str{2};
$last = $str[-1];
echo $first . PHP_EOL; // T
echo $third . PHP_EOL; // i
echo $last . PHP_EOL; // .
$len = strlen($str);
$str[$len+1] = 'a';
echo $str . PHP_EOL; // This is a test. a
$str1 = "我";
echo ord($str1[0]); //

PHP 开发工程师基础篇 - PHP 字符串的更多相关文章

  1. PHP 开发工程师基础篇 - PHP 数组

    数组 (Array) 数组是 PHP 中最重要的数据类型,可以说是掌握数组,基本上 PHP 一大半问题都可以解决. PHP 数组与其他编程语言数组概念不一样.其他编程语言数组是由相同类型的元素(ele ...

  2. Wi-Fi无线控制器开发例程(基础篇)

    动手来做自己的WIFI远程控制插座吧! 如果感觉视频不容易入门可以看这里 https://www.cnblogs.com/yangfengwu/p/10100152.html WIFI远程控制器系统方 ...

  3. 微信公共号的PHP开发(基础篇)——玩一下

    最近没事儿开了个微信号,写点东西给家人啊什么的看,你们想看的话就这个嘛: 然后就意外的看到imooc上的微信公众号开发相关了.每天科研的累累的,做点这个不是很累的东西吧. 微信公共号开发 一.基础 1 ...

  4. iOS开发零基础--Swift教程 字符串的利用

    字符串的介绍 字符串在任何的开发中使用都是非常频繁的 OC和Swift中字符串的区别 在OC中字符串类型时NSString,在Swift中字符串类型是String OC中字符串@"" ...

  5. Android图片开发内幕--基础篇

    前言:本来我是做电视应用的,但是因为公司要出手机,人员紧张,所以就抽调我去支援一下,谁叫俺是雷锋呢!我做的一个功能就是处理手机中的应用ICON,处理无非就是美化一下,重新与底板进行合成和裁剪,用到了很 ...

  6. java开发之基础篇2

    一.java开发环境的搭建 下载和安装jdk.版本自己看着办! 1 JAVA_HOME C:\Program Files\Java\jdk1.7.0_25 2 path C:\Program File ...

  7. Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇)

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7065294.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十四)--S ...

  8. Python 基础篇:字符串、列表操作

    字符串操作 判断是否为数字 string = "200" string.isdigit() >>false 待完善.. 列表操作 列表是我们最以后最常用的数据类型之一, ...

  9. Java开发工程师基础Math,Random,Scanner类的使用

    Math类的使用(重点) (1)数学操作类:该类没有构造函数,方法均为静态的 (2)掌握内容 A:成员变量 **E:比任何其他值都更接近e(即自然对数的底数)的double值. **PI:比任何其他值 ...

随机推荐

  1. tensorflow对鸢尾花进行分类——人工智能入门篇

    tensorflow之对鸢尾花进行分类 任务目标 对鸢尾花数据集分析 建立鸢尾花的模型 利用模型预测鸢尾花的类别 环境搭建 pycharm编辑器搭建python3.* 第三方库 tensorflow1 ...

  2. CSS把容器中的内容限制行数,在超过行数后,在最后一行显示"..."

    <style type="text/css"> .main{ width: 400px; background-color: #3498db; display: -we ...

  3. leetcode题库练习_左旋转字符串

    题目:左旋转字符串 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部.请定义一个函数实现字符串左旋转操作的功能.比如,输入字符串"abcdefg"和数字2,该函数将返 ...

  4. 解决react使用antd table组件固定表头后,表头和表体列不对齐以及配置fixed固定左右侧后行高度不对齐

    一.固定表头后表体列和表头不对齐 此问题可能在antd3.24.0版本之前都存在,反正3.16.2版本是存在这个问题的,如果是3.24.0之前的版本估计只能通过修改css样式解决. 按照官网说的: 1 ...

  5. 细说JavaScript 导出 上万条Excel数据

    首先这是个鸡肋的方法 合理的做法是 后端直接生成 前端给个链接就行了 (先说原因与过程最后上代码) 1. 先说说为什么会出现这个需求吧. : 在写运维网站时 自己粗略的看了一下bootstarp-ta ...

  6. Python操作adb命令脚本

    一.脚本代码(有错误,抓紧改进中) import os import datetime date1=datetime.datetime.now().strftime('%Y%m%d') date2=d ...

  7. 干货 | 这可能全网最好的BatchNorm详解

    文章来自:公众号[机器学习炼丹术].求关注~ 其实关于BN层,我在之前的文章"梯度爆炸"那一篇中已经涉及到了,但是鉴于面试经历中多次问道这个,这里再做一个更加全面的讲解. Inte ...

  8. Java bean常见映射工具分析和比较

    1. 概述 日常Java开发项目中,我们经常需要将对象转换成其他形式的对象,因此我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型. 进行这种转换除了手动编写大量的get/set代码,还可 ...

  9. ParallelsDesktop下Kali安装

    1. 安装镜像 镜像百度云:链接:https://pan.baidu.com/s/1TFXwmvehDdO-cwtU__TmqQ 密码:f3ow Kali官网 ,需要最新或者想下载其他版本去官网下载吧 ...

  10. PHP atan2() 函数

    实例 通过 atan2() 函数返回两个变量的反正切: <?phpecho(atan2(0.50,0.50) . "<br>");echo(atan2(-0.50 ...