2.1 C#的基本语法
C#代码的外观和操作方式与C++和Java非常相似。初看起来,其语法比较混乱,
不像书面英语和其他语言。但是,在C#编程中,使用的样式是比较清晰的,不用花太多的力气就可以编写出可读性很强的代码。
与其他语言的编译器不同,无论代码中是否有空格或回车符或tab字符(这些字符统称为空白字符),C#编译器都不考虑这些字符。这样格式化代码时就有很大的自由度,但遵循某些规则将有助于使代码易于阅读。
C#代码由一系列语言组成,每一个语句都用一个分号来结束。因为空格被忽略,所以一行可以有多个语句,但从可读性的角度来看,通常在分号后面加上回车符,这样就不能在一行上放置多个语句了。但一句代码放在多个行上是可以的。
C#是一块结构的语言,所有的语句都是代码块的一部分。这些块用花括号来界定(“{”和“}”),代码块可以包含任意多行语句,或者根本不包含语句。注意花括号字符不需要附带分号。
所以,简单的C#代码如下所示:
{ <code line 1,statement 1>; <code line 2,statement 2> <codeline 3,statement 3>; }
其中<code linex,statement y>部分并不是正真的C#代码,而是用这个文本作为C#语句的占位符。注意在这段代码中,第2,3行代码是同一个语句的一部分,因为在第2行的末尾没有分号。
在这个简单的代码中,还使用了缩进格式,使C#代码的可读性更高。这不是某些人的发明,而是一个标准规则,实际上在默认情况下VS会自动缩进代码。一般情况下,每个代码都会有自己的缩进级别,即它向右缩进了多少。代码块可以互相嵌套,而被嵌套的块要缩进得多一些。
{ <code line 1>; { <code line 2>; <code line 3>; } <codeline 3>; }
前面代码的续写通常也要所近得多一些,如上面第一个示例中的第3行代码。
在C#代码中,另一个常见的语句是注释。注释并不是严格意义上的C#代码,但代 码最好有注释。注释就是解释,即给代码添加描述性文本,编译器会忽略这些内容。在开始处理比较长的代码段时,注释可用于给正在进行的工作添加提示,例如“这行代码要求用户输入一个数字”,或“这段代码由Bob编写”。C#添加注释的方式有两种。可以在注释的开头和结尾放置标记,也可以使用一个标记,其含义是“这行代码的其余部分是注释”。在C#编译器忽略回车符的规则中,后者是一个例外,但这是一种特殊情况。
要使用第一种方式标记注释,可以在注释的开头加上“/*”,在末尾加上“*/”。这些注释符号可以在单独一行上,也可以在不同的行上,注释符号之间的所有内容都是注释。注释中唯一不能输入的是“*/”,因为它会被看作注释结束标记。所以下面的语句是正确的。
/* This is a comment */
/* And so…
…is this!*/
但下面的语句会产生错误:
/*Comments often end with “*/”characters*/
注释结束符号后的内容(“*/”后面的字符)会被当作C#代码,因此产生错误。
另一个添加注释的方法是用“//”开始一个注释,其后可以编写任何内容,只要这些内容在一行上可即可。下面的语句是正确的:
// 双行注释
但下面的语句会失败,因为第二行代码会解释为C#代码:
//So is this,
But this bit isn’t.
这类注释可用于语句的说明,因为他们都放在一行上:
<A statement>; //Explanation of statement
前面说过有两种方法给C#代码添加注释。但在C#中,还有第三类注释,严格地说,这是//语法的扩展。他们都是单行注释,用三个“/”符号来开头,而不是两个。
/// 特殊的注释
在正常情况下,编译器会忽略他们,就像其他注释一样,但可以配置VS,在编译项目时,提取这些注释后面的文本,创建一个特殊格式的文本文件,该文件可用于创建文档说明书。
特别要注意的一点是,C#代码是区分大小写的。与其他语言不同,必须使用正确的大小写形式输入代码,因为简单地用大小写字母代替小写字母会中断项目的编译。
2.2 变量
首先我们应该说明一下为什么计算机语言会需要变量,我们来看一个例子。假如你现在要去买一台电脑,假设我们知道这台电脑的标价是5000元,而现在恰逢国庆节打折,折扣率是10%,我们现在来计算这台电脑的价格。一般情况下我们会这样计算:首先我们要求出折扣了多少钱5000*10%=500元,然后我们只需要用5000-500就可以求出真实价格4500元。很显然在这里又一个问题:我们开始算出来的500这个折扣额需要在后面使用,在日常生活中,我们可以把这个数写在纸上或记住,然后再做后面的运算。那么对于计算机来说需要怎么做才能完成任务呢,事实上,计算机会把这个值记在内存里,以便进行下面的运算,这就用到了变量。什么是变量?变量就是程序语言中存储数据的基本单元。
计算机操作如下:
1. 首先定义变量存储电脑价格5000。
2. 执行价格*10%求出折扣额。
3. 将折扣额这个中间结果存入变量。
4. 将价格与折扣额相减。
5. 将真是的价格存入结果变量。
显而易见,变量对应一块能存东西的内存单元。程序语言通常使用变量来存储数据,使用变量可以引用存储在内存中的数据,并随时根据需要显示数据或修改数据。另外如前所述,变量是有类型的,不同类型的变量可以存储不同数据类型的数据。数据类型的概念我们稍后再说,下面来看一下C#中变量定义的语法:
数据类型 名 变量名
或
数据类型名 变量名=初始值
比如我们可以定义整型的年龄变量:
int age=20;
上面我们定义了一个整型的变量age,并且让这个变量的初始值为20。当你定义一个变量后,系统会根据此变量的数据类型为这个变量分配一块存储数据的内存,此后可以通过变量名来引用这个变量(就好比人名可以引用某个人一样)。
2.2.1 简单类型
变量中,简单类型实际上就是值类型,值类型的数据类型基本上可以归纳为三类:
第一类是整数型,包括int,long等,他们都可以定义整数变量。第二类是浮点型,它们包括float,double等,他们可以定义小数类型的变量。第三类是字符型和布尔型,包括char,bool等类型,他们可以定义字符串或者逻辑类型的变量。
整数类型的常用类型有(如下表)):
名 称 |
符号 |
大小(字节) |
范 围 |
字节类型 |
sbyte |
1 |
-128到127 |
无符号字节类型 |
byte |
1 |
0到255 |
整型 |
int |
4 |
-2147483648到2147483647 |
无符号整型 |
uint |
4 |
0到4294967295 |
短整型 |
short |
2 |
-32768到32767 |
无符号短整型 |
ushort |
2 |
0到65535 |
长整型 |
long |
8 |
-9223372036854775808到9223372036854775807 |
无符号长整型 |
ulong |
8 |
0到18446744073709551615 |
整数型也叫整形,是最常用的数据类型。使用整数定义的变量只能存储整型的数字,各种整型变量对应的内存参照表中的“大小”一栏,变量能保存的数值范围参照表中“范围”一栏。我们可以用整型定义人的年龄,国家的人口,日期的天数以及商品的数量等。
你可能会用疑问,不就是一个整数么,为什么整数需要这么多数据类型,而且你会发现每一种数据类型都有无符号和有符号两种。实际上,不管是int还是byte,不管是有符号还是无符号,都是为了更精确的说明和体现变量的真正含义,比如你定义天数最好使用ushort,因为天数没有负数并且天数的范围刚好适合ushort,一旦你这样定义了,那么如果给天数一个负数或者给天数一个特大的数,编译器将提示你这个数字不合法。这就可以初步保证正确的使用该变量。
整数型就先介绍到这里,下面我们来看常用的浮点型(如下表):
名 称 |
符号 |
大小(字节) |
范 围 |
浮点型 |
float |
4 |
+- |
双精度浮点型 |
double |
8 |
|
高精度浮点型 |
decimal |
16 |
浮点型可以表示小数或整数值,也因此浮点型的变量可以保存整数和小数两种数字。虽然说浮点型也可以保存整数数字,但浮点型真正的用途是来表示有精度要求的小数。比如正弦值等。
各类浮点型变量的内存大小参照上表中“大小”一栏,通常越大的浮点型能保存的数值精度越高。
对于浮点型的数字通常要使用后缀来指明其数据类型。对于decimal类型的数字要使用后缀m或M;对于float类型的数字要使用后缀f或F;对于double类型的数字要使用后缀df或D,如20.4d等。这里要注意:如果一个小数没有使用后缀,那么此小数数值默认情况下是double类型。如果你将一个double类型的数值给一个float变量就会发生类型不匹配的错误,如:
float m=2.2;
“2.2”默认为double型,要给浮点型变量赋值应该为:
float m=2.2f;
上面介绍了整数型和浮点型,最好我们来看字符型和布尔型(如下表):
名 称 |
符号 |
大小(字节) |
范 围 |
字符型 |
char |
2 |
16位 Unicode 字符 |
布尔型 |
bool |
1 |
true 和false |
字符型变量用于保存和表示世界上已知书面语言中的一个字符。对于C#中的字符
型,熟悉C/C++语言的朋友要特别注意,在C/C++语言中char型大小为一个字节,只能表示一个英文字符,而C#中字符型有两个字节,可以表示世界上任何语言的字符。在C#中表示一个字符时应该带有单引号,字符类型变量的定义和使用方法如下:
char enchar=’M’;
char cnchar=’ 国’;
对于布尔型,它可以用来表示逻辑判断的“真”和“假”。翻开逻辑学相关的书籍你会找到“真”和“假”的含义,我们说,给一个命题比如“所有人是动物“,如果这个命题成立,我们就认为此命题返回的结果为“真”,反之返回的结果为“假”。逻辑学中使用真和假来表示逻辑判断的结果,C#语言使用ture和false两个值来表示逻辑判断的真和假,这是C#语法。布尔型变量定义和使用方法如下:
bool trbool=true;
bool fsbool=false;
bool mybool=x>y;
到现在为止,我们介绍完了C#中所有值类型的数据类型。最后我们来看一下值类型的一个综合示例:
using System; namespace myText { Class Text { static void Main(string[] args) { int cx=10,cy=12,cr=0; cr=cx*cy; Console.WriteLine(“长方形的长是:{0},宽是:{1}”,cx,cy); Console.WriteLine(“长方形的面积是:{0}”,cr); double sx=12,sy=10.5; Console.WriteLine(“三角形的底是:{0},高是:{1}”,sx,sy); Console.WriteLine(“三角形的面积是:{0}”,sx*sy/2); char sx=’C’,sy=’N’; Console.WriteLine(“{0}{1}表示中国”,sx,sy); bool bh=cx>cy; Console.WriteLine(“{0}>{1}是{2}的”,cx,cy,bh); } } }
运行结果:
长方形的长是:10,宽是:12
长方形的面积是:120
三角形的底是:12,高是:10.5
三角形的面积是:63
CN表示中国
10>12是False的
上面的程序我们使用了刚才介绍的大部分数据类型。
2.2.2 变量的命名
变量在定义时涉及到数据类型和变量名两个元素,数据类型是系统定义好的关键
字,而变量名是可以自己定义的。这里着重说一下变量名的命名规则,变量名的命名主要有三条规则,变量名的构成规则必须满足下面条件:
l 变量名可以由字母 数字 _(下划线)组合而成。
l 变量名必须以字母或_(下划线)开头。
l C#语言中某些词(如 int或 float等)称为保留字,具有特殊意义,不能用作变量名。
要注意的是,C#语言中变量名区分大小写,因此变量age和Age是两个不同的变
量。实际上,C#程序中有许多需要命名的对象,例如变量名,方法名,类名等,为这些对象起一个名字来标识这些对象,这些名字都称作标识符,变量名就是变量标识符。C#语言规定同一种标识符不能重名,在这里也就说变量名不能重名,这是变量定义时要注意的问题。至此,我们可以来演练一下变量的定义了:
string welcom=”欢迎进入C#世界”;
int age=20;
double money=30000;
char c=’A’;
从上面的例子我们也可以看出,变量和数据类型有着密切的关系,我们说不同的变
量代表着不同的内存存储空间,并且这块存储空间是固定大小的,这样就决定了变量有一定的存储范围,如果变量的值超出这个范围就会发生错误。而数据类型就决定了变量占用内存的大小,因此数据类型对于变量来说非常重要。
2.2.3 变量的声明和赋值
学完变量的命名规则后,变量的声明和赋值是非常简单的。变量在声明的时候首先要知道所定义的变量是什么类型的,在去声明你所定义的变量;变量的赋值——变量可以在声明的时候赋值,也可以声明后在下面用到该变量时对其进行赋值。下面我们来看下变量的声明和赋值的示例:
int age=20;//在声明变量时直接给变量赋值
或
int age;
age =20;//先声明变量,在对变量进行赋值
总的来讲,变量的声明和赋值的语法是:
数据类型 变量名;
变量名=初始值;
或
数据类型 变量名=初始值;
2.3运算符和表达式
上一节我们学习了变量,那么变量和变量之间怎联系起来呢?今天我们来学习运算符和表达式。
在程序语言中,变量是字词,通过运算符将变量连接成表达式,表达式相当于语言中的短句。运算符最常见的就是加、减、乘、除,这些运算符每一个小型的计算器都有。当然程序语言支持的运算符不止这些,每个程序语言提供的运算符号稍有些不同,但大体上都一样,在C#语言中主要有以下几种运算符:
★ 算术运算符
★ 关系运算符
★ 逻辑运算符
★ 赋值运算符
运算符操作数的个数,又可分为一元运算符和二元运算符,一元运算符连接一个操作数,二元运算符连接两个操作数,我们常见的加、减、乘、除都是二元运算符,他们需要连接两个操作数。
运算符连接操作数构成表达式,操作数可以是变量和常数(单独的一个数字或字符串等我们都可以称作常数)。许多小的表达式可以构成大的表达式。如“(x+y)+(x-y)”中间的加号连接两个小的表达式构成一个复杂的表达式,此时这些小表达式我们也可以认为是操作数,也就是说操作数也可以是表达式。事实上C#中的表达式和小学数学中的算式有些相似。
★ 2.3.1算术运算符
下面我们首先来介绍算术运算符,算术运算符是我们最常见的运算符,如下图所示:
算术运算符 |
作 用 |
示 例 |
+ |
加法操作 |
1+2,x+y |
- |
减法操作 |
2-1,x-y |
* |
乘法操作 |
2*3,x*y |
/ |
除法操作 |
4、2,x/y |
% |
取余数操作 |
7%2=1,23%10=3 |
++ |
自增操作 |
x++,++x |
-- |
自减操作 |
x--,--x |
算术运算符用来连接操作数执行算术运算。其中前四种都很熟悉了。取余运算又叫取模运算,是用来取得余数,比如我们要取得12除以5的余数可以使用“12%5”,结果是2.关于自增“++”和自减“--”运算符的用法需要注意,我们可以用一种替代算法来解释他们。如果“x++”或者“++x”单独出现在一个语句中那么都相当于“x=x+1”(注意:“x++”和“++x”在一定范围下是有区别的),相对应的自减也类似。
关于算术操作符就介绍到这里,下面我们来看一个示例:
usingSystem; usingSystem.Text; namespaceText { class program { static void Main(string[] args) { inta=5%2; doubleb=a+2*5/2.5; int x=5; inty=++x; intz=x++; Console.WriteLine(“a={0},b={1}”,a,b); Console.WriteLine(“x={0},y={1},z={2}”,x,y,z); } } }
运行结果:
a=1,b=5
x=7,y=6,z=6
按F5键运行后,运行结果如上,这里重点要注意z和y的值。运行结果中z和y都为6,你可以把上面的“++”符号换成“--”符号运行,结果z和y都为4.有时我们也形象的称自增或自减变量“参与表达式运算”为“使用”,如果递增运算符在变量的前面,那么变量先自我递增然后在“使用”,在这里的“使用”是指“x赋值给y”。如果自增运算符在变量后面,那么变量先“使用”再自我递增。即“++x”是“先运算后赋值“,“x++”是“先赋值后运算”。
2.3.2关系运算符
事实上,关系运算符就是我们在小学三年级学过的的那些大于 小于 等于等。C#中关系运算符用于测试两个数或者两个表达式之间的关系。关系运算符连接操作数构成关系表达式,关系表达式的计算结果为逻辑值true和false,如果此关系式表达成立则返回true,否则返回false。C#中的关系表达式大都是我们所熟悉的,如下表所示:
关系运算符 |
作 用 |
示 例 |
> |
大于 |
3>2,x>y |
< |
小于 |
2<3,y<x |
>= |
大于等于 |
3>=3,x>=y |
<= |
小于等于 |
2<=3,y<=x |
== |
等于 |
2==3,x==y |
!= |
不等于 |
2!=3,x!=y |
关系表达式得到的结果是逻辑值“真”和“假”。我们在前面提到过,在C#中“真”和“假”使用布尔类型来表示,“真”用小写true来表示,“假”用小写false来表示,它们描述了表达式所表达的关系是否成立,如下所示:
boolr=3>4; //关系不成立则r为false
boolr=3>2; // 关系成立则r为true
关系表达式也有一些很复杂的,比如“(a+b)>(a-b)”等复合表达式,关系表达式主要用在条件判断语句中(如if语句等,我们后面将会介绍),表示如果某个条件成立就去执行一个操作,如:
using System; using System.Text; namespace Text { class Program { static void Main(string[] args) { int a=1,b=2; if(a<b) { Console.WriteLine(“a小于b”); } } } }
运行结果:
a小于b
2.3.3逻辑运算符
逻辑运算符通常连接关系表达式从而表示更复杂的关系。一般来说,逻辑运算符通常使用在if语句中连接一个或多个条件构成符合条件。要注意的是,逻辑运算符连接成的表达式还是关系表达式,返回值的类型也是布尔型,下表是C#中用到的逻辑运算符。
逻辑运算符 |
作 用 |
描 述 |
&& |
逻辑“与”操作 |
“并且”的意思 |
|| |
逻辑“或”操作 |
“或者”的意思 |
! |
逻辑“非”操作 |
“不”或“非”的意思 |
在日常生活中经常出现复杂的条件选择,不如下面这个例子:
“假如我有钱或者我长得帅,那么我可以找个漂亮的女朋友。”
这里的“我有钱”和“我长得帅”两个条件之间的“或者”就相当于使用了逻辑运算符“||”,我们再举一个C#中的例子:
if(a>b && a!=0) r=b/a;
这个式子意思是:假如a大于b并且a不为零,那么求b除以a的结果。
逻辑“非”相当于“不”,会对原来的值取反,比如:
“他不是个好人”就等效于“他!=好人”。
“他不不是个好人”就等效于“他!!好人”。
两个“非”运算符可以省略掉所以任何逻辑表达式不会同时出现两个并列的“非”符号,那是很无聊的写法。你可以简单的将逻辑运算符“&&”理解为“并且”,将 “||”理解为“或者”,“!”理解为“不”,这样有助于你对代码的理解。下表列举了所有逻辑运算符在各种各种运算情况下的结果,仔细观察会发现里面是有规律的的:
运 算 |
结 果 |
运 算 |
结 果 |
!true |
false |
false && false |
false |
!false |
true |
true || true |
true |
true && true |
true |
true || false |
true |
true && false |
false |
false || false |
false |
通过上面的表我们可以得出结论:
● 对于 && 操作,只有当两个条件都为true时结果才为true。
● 对于 || 操作,只要任何一个条件为true则结果为true。
示例:
using System; namespace Text { class Program { static void Main(string[] args) { floatprice1=27.3f; //第一种商品的价格 floatprice2=57.0f; //第二种商品的价格 int n1=2; //第一种商品的数量 int n2=3; //第二种商品的数量 floatdiscount=0.2f; //折扣 //总消费金额 doubletotal=price1 * n1 + price2 * n2; //如果总消费额大于200或者买的每种商品的价格都超过了100则打折 if(total>200||(price1>100&& price2>100)) { total=total*(1-discount); Console.WriteLine(“折后总消费额为:{0}”,total); } else Console.WriteLine(“总消费额为:{0}”,total); } } }
运行结果为:
折后总消费额为:180.4799
上面的例子我们首先定义了两个价格和两个数量变量。价格变量定义成浮点型时因
为价格很可能存在小数,数量定义成整型是因为数量只能时整数。然后我们使用算术表达式求出所有的购买商品的总额,并保存到total变量中,total变量采用double类型只是为了演示double的用法,实际上用float型也可以。最后我们使用if语句根据条件来执行不同的代码块,假如if语句后面的括号中关系表达式返回true,则执行折扣计算相关代码,如果返回false则不计算折扣直接显示消费总额。
下面来看一个综合性的示例,猜猜它的运行结果?
class Person { static void Main() { char cSex='男'; //性别 int iHeight=175; //身高 float fWeight=65.55f; //体重,float型需要加f bool bIsMarriage=false; //婚否,取值:true(表示已婚);false(未婚) string sName; //字符串类型 sName="张秋枫"; System.Console.WriteLine("***************************");//"":字符串 System.Console.WriteLine(cSex); System.Console.WriteLine(iHeight); System.Console.WriteLine(fWeight); System.Console.WriteLine(bIsMarriage); System.Console.WriteLine(sName); System.Console.WriteLine("********************************"); } }
2.3.4赋值运算符
赋值运算符是给一个变量赋一个值,听起来像废话,实际上这个小小的赋值作用非
常大,她会指示系统向变量对应的内存存入一个值。赋值运算符就是我们前面见到的“x=2”表达式中间的那个等于号。这里要注意赋值符号和“等于”号的区别,赋值运算符是一个“=”号,而两个“==”号才是我们前面介绍的的关系运算中表示相等关系的“等于”号。除了基本的赋值符号外,C#中还支持复合赋值运算符号。下表中左边一列是复合赋值运算符,中间一列是示例,右边一列是与左边运算符等效的运算:
赋值运算符 |
示 例 |
描 述 |
= |
x=2 |
给x赋值2 |
+= |
x+=2 |
相当于x=x+2 |
- |
x-=2 |
相当于x=x-2 |
/= |
x/=2 |
相当于x=x/2 |
*= |
x*=2 |
相当于x=x*2 |
%= |
x%=2 |
相当于x=%22 |
表中那些复合赋值运算符实际上就是后面描述部分的一个缩写形式,只不过那种省略的写法执行效率比较高,这是从C语言继承下来的特性,所以提倡使用前面的那种省略的写法。赋值运算符的计算执行是从右往左进行,比如我们常见的“x=x+2”,实际上是先计算了“x+2”然后再把这个结果给x,所以运算结果后x会增加2,如果出现连写的赋值运算,则计算是从右往左逐个赋值,如:“x=y=a”,则结果x y都等于a,下面是一个经典的交换两个数的算法:
int a=1,b=2;
b=(a+b)-(a=b);
一句话执行完后a、b的值将互换,a变为2,b变为1。计算首先从右边开始,先计算左边括号里面的“a+b”,结果为3,然后计算右边括号里面的值,右边括号里面的值计算完后结果为2,同时a已经等于了2。最后,左边括号里面的结果3减去右边括号里面的结果2得到结果1,这个1赋值给b,那么b就是1了,交换完毕。从上面的例子我们不难看出,系统运算的每一步在内存中都会暂存结果。上面的两个括号的结果先计算完,然后再把这两个结果进行相减,最后将减的结果进行赋值。
C#示例:
using System; namespace MyText { class Text { static void Main(string[]args) { int num=4567; int thousand,hundred,ten,indiv; thousand=num/1000; num%=1000; hundred=num/100; num%=100; ten=num/10; indiv=num%10; num=indiv * 1000+te n*100+hundred * 10+thousand; Console.WriteLine(“反转后的数是:{0}”,num); } } }
运算结果:
反转后的数是:7654
注意:赋值运算右边表达式的值必须和被赋值对象数据类型相同,如:
int a=3.3f;
float b=‘a’;
上面的第一个表达式右边是浮点型数字而左边是整型的变量,这样是不对的。同样第二条语句右边是字符,左边是浮点型的变量,这样赋值也是不合理的。如果赋值运算两边是引用类型,那么类型也必须兼容。一般来说,你完全可以把变量当作是一个特定的容器,比如装番茄酱的瓶子,对此你不能将辣椒酱装在里面,在进行赋值操作时要特别注意这一点。当然后面我们会介绍数据类型转换的相关知识,有了数据类型的转换你就可以把辣椒酱装到番茄酱瓶子里了,你就可以把浮点型赋值给整型了。
2.3.5 运算符的优先级
现在,你几乎已经了解所有的运算符,是你大显身手的时候了,那么你能计算下面的式子吗: r=(2-1)* 3 + !2 – 5% 2 * 2 && 3;
你如果没有接触过其他程序语言,相信你应该傻眼儿了,这么多运算符应该先算哪个呢?我们在小学时就知道运算符有优先级,我们知道乘法和除法的优先级高于减法运算,而括号的优先级最高,一个式子既有加减又有乘除还有括号,那么计算的顺序是:括号里面的—>乘除-->加减,如“3*4+2/(5+2+1)”式子,结果是:“12.25”。我们知道C#中的运算符远比数学中的运算符多,而且这些运算符都可以出现在同一个表达式中,那么我们的优先级是怎样的呢?
C#中运算符优先级从高到低排列如下表所示:
运算符号 |
结合性 |
描述 |
运算符号 |
结合性 |
描述 |
() |
从左到右 |
括号优先级最高 |
=,!= |
从左到右 |
等号,不等号 |
++,--,! |
从右到左 |
递增,递减,逻辑非运算符 |
&& |
从左到右 |
逻辑 与 |
*,/,% |
从左到右 |
乘,除,取模操作 |
|| |
从左到右 |
逻辑 或 |
+,- |
从左到右 |
加 减运算 |
=,+=,*=,/=,%=,-= |
从左到右 |
赋值运算符和复合赋值运算符 |
<,<=,>,>= |
从左到右 |
小于 小于等于 大于 大于等于 |
运算符的结合性是指同时出现多个该运算符时的计算方向。比如优先级最高的括号,如果在一个表达式中出现多个括号,那么将从左向右依次计算这些括号里面的内容。再比如大于小于号,如果几个大于 小于号连接在一起,那么是从左到右进行计算的。通常,能接两个操作数的运算符称作二元运算符,比如“+”号,接一个操作数的我们称作一元运算符,比如“!”和“++”等。从上面的优先级例子可以看出,除了括号外,一元运算符的优先级最高。除此之外,从大的范围来讲算术运算符的优先级高于关系运算符,关系运算符的优先级高于逻辑运算符,优先级最低的是赋值运算符。
示例:
using System; namespace Text { class Program { static void Main(string[] args) { int y=2002; if(y % 4 == 0 && y % 100!=0 ||y % 400== 0) Console.WriteLine(”{0}年是闰年”,y); else Console.WriteLine(”{0}年不是闰年”,y); } } }
上面是一个求闰年的算法。假如某年能被400整除那么这年是闰年,如果某年不能被100整除并且能被4整除,那么这年也是闰年,也就是说这两个条件满足其中的一个就是闰年。上面的if语句中优先级最高的运算符是“%”号,所有的“%”计算完了再计算“==”号,然后计算“&&”号,最后计算“||”号,最终结果false,所以2002年不是闰年。这里注意的是,上面的式子不够好,虽然实现了功能,但看起来令人头晕,所以我们提倡多用括号,善于用括号,上面的式子应改为:
If((y % 4 == 0 && y % 100!=0) ||(y %400 == 0))
很显然加了括号的式子含义明了,代码工整,直观易懂。这属于代码规范的范畴。多种运算符同时出现的地方不是什么算术表达式,而是像上面那样的条件表达式中。计算运算符的优先级是件头痛的事,加上括号后会使问题变得简单化。
另外,在上面使用运算符号时你可能也注意到了一个问题,这个问题原不属于运算符的优先级的问题,是关于长表达式跟数据类型有关的问题。问题是如果这个表达式中存在各种数据类型的数值怎么办,如下面的式子:
double r=1 + 1/2 + 2.0;
上面式子中r的值为3而不是3.5。对于混合数据类型表达式的计算,结果按照最高精度为准,超过精度的一概被“切”掉,比如“1/2”结果是0,本来计算的结果是0.5,但大家都是整型所以结果是整型,小数点后数字都被“切”掉了。如果将“1/2”变成“1/2.0”,那么结果就是0.5,因为2.0是浮点型,所以结果也是浮点型。长表达式无非就是许多小表达式组合计算的结果,比如上面那个式子,首先计算“1/2”结果是0,然后计算“1+0+2.0”,结果是double类型的3.0。
关于运算符和表达式的内容我们就介绍到这里,要特别注意的是:运算符的优先级以及混合数据类型表达式的计算问题。
|
选择题:
1. 下列变量的声明正确的是()
A.int 1name;
B.int _name;
C.int float;
2. 下面
问答题:
1. 本章中学了几种运算符?他们的优先级从高到低的顺序是什么?
|
在本章中,我们主要学习了:
u C#的基本语法
u 变量的简单类型
u 变量的命名规则
u 运算符和表达式
u 运算符的优先级
练习项目: |
学过变量和表达式,请大家发挥自己的想象,做一个和本章紧密相连的项目:
需达到效果如下:
在这个项目中,每种运算符至少用一个说明你掌握了此类运算符;运算中要考虑运算符的优先级;声明的变量类型要恰当。