关闭

写给懂C语言的人的PHP语法入门

535人阅读 评论(0) 收藏 举报
分类:
如果你学过C语言,现在想学习PHP,第一步当然是掌握基本语法。PHP的基本语法与C极其相似,但也有一些独特之处,本文通过对比的方式,按照学习C语言语法的顺序,介绍PHP的基本语法,希望能帮助熟悉C的人快速入门。
首先明确一个思想,PHP语法与C最大的不同之处在于PHP重实用,而C重原理。学习C的语法,培养人严谨的思维习惯,对于了解计算机的工作原理是很有帮助的。一个学过C的人开始学PHP,会对PHP过于宽松的语法感到不适应。PHP的创始人是为了更新自己的主页而设计PHP的,不是像C的创始人那样为了开发操作系统,这是两者语法风格不同的根本原因。明确了这个思想,我们就按照数据类型、常量、变量、运算符与表达式、流程控制、函数、数组这样的顺序来一一介绍PHP的基本语法并与C相对照。由于是入门,所以我们只沿着主干道前进,路边有很多美丽的风景,像正则表达式之类,我们以后再专题探索。
PHP的数据类型
PHP与C的一个显著不同是:不管常量还是变量都不需要先定义后使用(类中的变量除外),PHP根据第一次赋值的情况自动决定数据类型。想想当年学习C语言的时候,我们曾感到先定义后使用很麻烦(但是“长大后”(我是指学会C后)都体会到了它的好处),常常忘记定义,而现在少了这条规矩,反而有点不适应了。
PHP的基本变量类型有整型(Integer)、浮点型(Float)、字符串(String)(这是C没有的,但C++有String类)以及布尔型(Boolean)(C没有,但是C++有)。构造类型有数组和对象。此外还有两个特殊类型:空值(NULL)(C也有)和资源(Resource)。
常量
在PHP中定义常量的方式在学习C的人看来有点不可思议,竟然是用一个define函数实现的,PHP的函数实在是太厉害了,后面我们会看到定义数组也是由函数完成的,我们真得感谢PHP无比丰富的函数库,它们成就了PHP的易用和强大。
define函数原型:bool define(string name,value,[,bool case_insensitive])
第三个参数如果是TRUE,则表示常量名是大小写不敏感的,反之就是敏感的,默认是敏感的。我们还是遵照习惯,保持常量名称大小写敏感吧。
例: 
复制PHP内容到剪贴板 
PHP代码:

<?php
  define(“C1”,”Hello PHP World!”);
  echo C1;
?>


以上代码的运行结果是输出常量C1的值(Hello PHP World!)。
这里顺便介绍一下,<?php和?>是PHP代码的定界符,将PHP代码同HTML代码区分出来,PHP代码的语句以分号结束,这是我们习惯的,另外PHP的注释符号也与C一样,你该知道的,我就不说了……这个echo就相当于C的printf或C++的cout,但是严格地说不是格式化的输出,要想格式化也很容易,你把HTML代码写进去就行了,比如你要输出结束后换行,那你就写成define(“C1”,”Hello PHP World!<br>”);好了。注意,PHP也支持‘\n’作为换行符,但是它的含义仅仅相当于在HTML里敲个回车,浏览器里看还是在一行上的。
变量
除了不用定义,C语言用户最不习惯的就是所有的变量名前都要带个$,你可能会抱怨PHP的设计者太财迷了,但抱怨完了你还得这么写,写PHP程序,Shift键的使用率陡增!我突然发现一个这样做的好处是:常量不带$,因此常量与变量的区分变得很明显,更重要的是,你再也不用担心自定义变量名同PHP关键字冲突了,你可以定义一个变量叫$if,$for等(当然,正式情况下还是不要这样做的好,过过瘾就行了)。
与C相同的是,PHP的变量名是大小写敏感的,并且命名方式遵循C标识符的命名原则,还记得吗?
如果你懂点C++,知道引用的概念,下面这段就可以跳过,只要记住PHP也支持引用。否则花点时间看下面这段或是去看看C++引用的概念也行。 
复制PHP内容到剪贴板 
PHP代码:

<?php
$var1=100;
$var2=&$var1;
$var2=200;
echo $var1.”<br>”;
echo $var2;
?>


这段代码的运行结果是输出两个200,分别是$var1和 $var2的值,输出的时候为了清楚加了个换行符,PHP里句点(.)是字符串的连接符。
为什么只给$var2赋了200,而$var1也变成了200呢,你还可以试试只改变$var1的值,你会发现这两个变量似乎被绑在一起了。其实语句$var2=&$var1;中的&符号的含义是将变量名$var2也指向$var1所在的存储空间,也就是说$var2并不是一个新变量,而是$var1的另一个名字,它们对应的是同一段内存空间,不管使用谁都是访问的同一个变量,$var2就叫做对$var1的引用。引用有什么好处?以后再说。C语言的基本概念(变量名、变量地址、变量值)清楚的话,理解起来应该没有什么困难,如果基本概念不清楚,还是先“温故”再“知新”吧。
顺便说一个有意思的事,如果你在把上面的echo语句写成:
echo “The value of $var1 is ”.$var1.”<br>”;
那么你得到的输出将是:The value of 200 is 200
还记得吗,在初学C语言时你很可能犯过把变量名放在字符串里想输出它的值,结果得到的是变量名,而现在,你的“理想”实现了,而你却又不习惯了,呵呵。原来PHP在使用双引号作为字符串的定界符时,会自动把变量名替换成相应的值,这样的做法使得我们输出含变量的字符串时变得非常方便,一对双引号下来就可以了。如果你想保持变量名原样输出,那么可以用单引号做字符串的定界符(当然还有其它办法,你可以仔细研究一下PHP的字符串)。还是要感谢C的严格要求,如果C像PHP这样的话,我们恐怕到现在也搞不清变量名、变量值这些概念。
变量的作用域
PHP的变量作用域与C很类似,在此不准备多说。局部变量在所存在的函数内部有效,全局变量作用域是文件作用域(限于单个PHP文件),若局部变量同全局变量重名,同C的处理方式,全局的被屏蔽。稍微麻烦一点的是,要想在函数内访问全局变量,需使用global关键字声明,否则的话PHP就认为是一个与全局变量同名的局部变量。 
复制PHP内容到剪贴板 
PHP代码:

<?php
$a=1;
function func()
{
   echo "The value of a is:".$a;
}
func();
?>


以上代码没有输出1,为什么呢?PHP把函数里的$a看作是一个全新的局部变量,此$a非彼$a(函数体外的全局变量),此$a未赋值,因此输出为空。如果我们要想在函数体内部访问全局变量$a的值,须在访问之前声明一句:global $a; 这样PHP就知道要访问的是全局变量$a了。
还有一种方法是利用PHP的系统数组$GLOBALS,该数组是PHP系统自动生成和维护的,它记录了所有全局变量。echo $GLOBALS[“a”]; 即可输出其中$a的值。
PHP的静态变量仅在局部函数域中存在,同C是完全相同的。
PHP有一种特殊的动态变量,名字听起来很容易让人认为就是C语言的普通变量(动态的、局部的),但这个动态的含义有点特殊,它是指变量名可以动态赋予!也就是说,可以让应用程序的最终用户为变量指定名字! 
复制PHP内容到剪贴板 
PHP代码:

<?php
$a="newname";
$$a="content";   //newname本是$a的值,但是$$a的含义是以$a的值为名的变量
echo $newname; //$$a等价于 $newname
echo $a;
?>


运算符和表达式
PHP在运算符和表达式方面和C极其类似,有算术、逻辑、关系、位运算符及相应的表达式,也有条件运算符(:?)及其表达式,同样还是我们开始提到的那个思想,实用为上,很多限制被取消了,相对较宽松。举个例子: 
复制PHP内容到剪贴板 
PHP代码:

<?php
$a="1";
$b=1;
if ($a==$b) echo "Equal!";
else echo "Not Euqal!";
?>


按照C的思维方式来看,$a是字符,$b是整型,两者比较是字符的ASCII码值与整数比较,显然不等,而PHP运行结果却是“Equal!”,看到这里,是不是有点冲破封建大家庭的礼教与心上人私奔的感觉?呵呵,抑或是惊呼PHP无法无天?接下来还有让你目瞪口呆的,若$a="1e3"; $b=1000; 依然是“Equal!”,也就是说PHP在比较时能自动将字符串“按照人的理解方式”进行转换,1e3不就是科学计数法表示的1000吗?甚至$a=”1e3HelloWorld”;都会相等,PHP将字符串转换为数值时会自动截取全部它能理解为数值的部分!其实C也允许跨越数据类型的比较,比如字符型和整型比较,C也会自动转换类型,但它是“按照计算机的思维方式”转换的,因为字符在计算机里就是按照ASCII码存储的。
PHP的“人性化”也带来了麻烦,当我们想严格比较两个变量的时候怎么办呢?于是PHP提供了一对特殊的运算符:全等(===)和非全等(!==),只有当值相当且数据类型相同时,才叫全等,两者有一不符,则非全等。此时,即使1与1.0也是非全等的,原因你一定知道吧。如果你觉得只有这样才踏实,那么恭喜你,你已经被C洗脑了。
运算符有优先级和结合性的概念,这方面和C是类似的,你也许记不清所有的优先级关系,但是没关系,我们有括号呢。
流程控制
PHP的流程控制语句是与C最像的部分了,简直可以照搬。
有两点值得注意,一是switch case语句中case后面可以写任意表达式,而不是C规定的只能是常量表达式,C的这种规定太不近人情了,以至于很多人学完了C还不知道 case score〉90:这样的写法错在哪里。现在好了,PHP里面,你可以这样写了。
再就是很奇怪的一点,if elseif else结构中间的else和if可以连在一起写。
此外,PHP还有一个独特的循环结构foreach,是专门为数组遍历准备的,稍后介绍。
函数
PHP用户自定义函数的语法与C也很类似,可想而知,由于PHP弱化数据类型的概念,所以函数的返回值类型也就弱化了,函数定义的一般形式是:
function 函数名($参数1,$参数2,……,$参数n)
{
  函数体
  return 语句返回值
}
比C的“宽松”之处在于函数可以嵌套定义,但是为了一个明晰的代码结构,还是严格要求自己的好。
这里我们再说说引用。前面提到引用其实就是给变量取个小名(专业的话叫别名),即两个或多个变量名对应同一变量存储空间。这一概念用在函数参数上特别有用,我们知道实参与形参的结合是单向值传递,即实参将它的值复制给形参,而形参变量在函数体中可能被改变,但由于形参变量会在函数返回时被撤销,所以形参不能将改变了的值传回给实参,这是学C的人都应该十分清楚的,大家都做过那个交换两个数的实验。这一机制保证了函数只能有一个返回值,当需要返回多个值的时候,我们可以使用引用做形参,这相当于把实参的地址传递给函数,函数对这个地址上的数据进行操作,当然就可以把改变保留下来。引用的概念是C++里增加的,PHP的函数也支持引用做形参。只要把C++里引用做参数的概念理解清楚了,在PHP里是完全一样的。
PHP有巨大的函数库,比如关于时间的函数就有一大堆,写PHP程序时,当你有个功能想要实现,第一件事应该是查PHP函数手册,看看有没有能满足你的要求的函数,或者是通过多个函数组合实现也行,而不是自己动手去写(练习编程技能或改进PHP者除外),记住一句老话:不要重复发明轮子。
要想掌握PHP,熟练使用常用函数是必须的,但这不是我们这篇文章的目标,有机会专题探索吧。
数组
这回甭指望我说PHP的数组和C差不多了,因为PHP的数组,简直就不是C的数组!PHP的数组应该叫做“集合”,不是紧急集合的集合,是数学意义上的集合,如果你学过数据结构就更明白了。说白了,PHP的数组就是把一堆数据(什么类型都行)放在一起。这在C里是很疯狂的想法,但是在现实中是很实用的,比如一条数据库记录可能由整型、字符串型、浮点型等不同类型的若干字段组成,如果能一次读取出来放在一个“数组”中用下标访问,是不是很方便呢?这种“数组”,是不是很像C的结构体呢?其实它比结构体还灵活,它可以自动增减数据元素。
PHP数组的定义是通过array函数实现的,一般形式为:
$数组名=array(键名=>数据, 键名=>数据, ……, 键名=>数据);
这里的键名在C中叫下标,C规定下标必须是整数且必须从0开始依次递增。在PHP里,键名非常人性化,对应的数据如果存储的是姓名,键名就可以叫name,是成绩,就可以叫score,当然你如果想用整数也可以,随你的便。如果你懒得在定义数组时指定键名,可以这样写:
$数组名=array(数据1, 数据2, ……, 数据n);
这时候PHP会按照C语言的方式按数据的先后顺序从0开始自动赋予整型键名。
PHP提供了一个特别方便的显示数组全部元素的函数print_r 
复制PHP内容到剪贴板 
PHP代码:

<?php
$arr1=array(100,200,300,400);
$arr2=array("num"=>100,"name"=>"Liuxy","score"=>98);
print_r($arr1);
echo "<br>";
print_r($arr2);
?>


以上代码的输出结果如下:
Array ( [0] => 100 [1] => 200 [2] => 300 [3] => 400 ) 
Array ( [num] => 100 [name] => Liuxy [score] => 98 )
若要定义二维数组,可以嵌套地使用array函数,同C类似,也是把二维数组的每一行看作是一个一维数组,构成每一行的一维数组可以互不相同。如: 
复制PHP内容到剪贴板 
PHP代码:
$arr=array( 
           "row1"=>array(100,200,300,400),
           "row2"=>array("num"=>100,"name"=>"Liuxy","score"=>98)
         );


PHP数组元素的访问同C类似,都是数组名[键名]的形式。
PHP数组的遍历可以通过foreach语句实现,foreach语句格式如下:
foreach (数组名 as  变量名) 数据元素处理语句;
翻译成C语言就是:
for (i=0;i<n; i++){变量名=a;其他包含“变量名”的处理语句}
foreach等价于前面的 for (i=0;i<n; i++)
as等价于“变量名”与a之间的等号,这下你明白了吧。
例如: 
复制PHP内容到剪贴板 
PHP代码:

<?php
$arr=array(1,2,3,4,5,6);
foreach ($arr as $value ) echo ”$value<br>”;
?>


输出结果是什么?想想看。
如果还想把对应的键名也同时输出出来,可以用这样的形式:
foreach ($arr as $key=>$value) echo “键名为$key的元素值为$value”;
在C中遍历二维数组我们一般用二重for循环,相应地,PHP中的foreach也可以嵌套使用,分析一下下面的程序你就明白了: 
复制PHP内容到剪贴板 
PHP代码:

<?php
$arr=array( 
             "row1"=>array(100,200,300,400),
             "row2"=>array("num"=>100,"name"=>"Liuxy","score"=>98)
           );

foreach ($arr as $key=>$value)
{
    echo "$key=>$value";
    echo "<br>";
    foreach ($value as $k=>$var) echo "$k=>$var<br>";
}
?>


PHP的数组元素是可以动态增长的,这是C里面不敢想的。为数组增加一个元素很简单,同访问数组元素一样,只不过键名是新的或者为空,如 $arr[new]=3; 或 $arr[]=3,这样做的结果是PHP为数组$arr增加一个键名为new的元素其值为3,若键名为空,则以当前整型键名的最大值加1作为默认的键名分配给新的元素。PHP的这种动态增长数组有时候很方便,但也带来隐患,比如当我们企图修改已存在的元素值而写错了键名时,就变成了新增一个元素,而这样的逻辑错误,系统是不会报错的。
可以增长就可以缩减,要想删除一个数组元素,可以使用unset函数,如删除上面新增的那个元素,可以写成 unset($arr[new])。也可以使用unset函数删除整个数组结构,如unset($arr),要注意这同逐个删除全部数组元素不同,后者还保留有数组的结构。形象地说,后者是人去楼空,但楼还在,前者连楼也拆除了。有意思的是删除数组全部元素后如果新增一个元素,它的默认键名将延续之前数组的最大键名递增,要想从0开始,可以使用array_values函数重置,如$arr=array_values($arr)。
提醒大家的是,PHP为数组的排序、查找、合并、拆分提供了大量函数,用到这些基本算法时,不用再去翻数据结构课本了,呵呵……

这个专题主要把精力集中在PHP的基本语法上,通过与C的对比来加深理解,有很多细节问题未深入讨论。学习任何东西都是一个螺旋上升的过程,我们先浏览一下知识脉络,更多的需要在实践中去体会。
下一个专题我们是不是研究一下PHP5的面向对象?你可能会说“我没学过C++”,没关系,这回我们不比较了,C++的面向对象概念是所有语言中最复杂的,而PHP5的面向对象由于是从实用出发所以比较简明,你不妨先学PHP5的面向对象,理解面向对象的概念,然后再去啃C++的OOP吧。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:110198次
    • 积分:1218
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:62篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论