第一章:C语言概述及如何上机运行C程序
1.C语言概述
1.1C语言的发展过程
C语言是在70年代初问世的。一九七八年由美国电话电报公司(AT&T)贝尔实验室正式发表了C语言。同时由B.W.Kernighan和D.M.Ritchit合著了著名的"THE C PROGRAMMING LANGUAGE"一书。通常简称为《K&R》,也有人称之为《K&R》标准。但是,在《K&R》中并没有定义一个完整的标准C语言,后来由美国国家标准协会(American National Standands Institute)在此基础上定制了一个C语言标准,于一九八三年发表。通常称之为ANSI C。
1.2当代最优秀的程序设计语言
早期的C语言主要是用于UNIX系统。由于C语言的强大功能和各方面的优点逐渐为人们认识,到了八十年代,C开始进入其它操作系统,并很快在各类大、中、小和微型计算机上得到了广泛的使用,成为当代最优秀的程序设计语言之一。
1.3C语言的特点
1. C语言简洁、紧凑,使用方便、灵活。ANSI C一共只有32个关键字:
auto break case char const continue
default
do double else enum extern float
goto if int long register return
short
signed static sizeof struct switch
typedef union
unsigned void volatile while
9种控制语句,程序书写自由,主要用小写字母表示,压缩了一切不必要的成分。
2.运算符丰富。共有34种。C把括号、赋值、逗号等都作为运算符处理。从而使C的运算符类型极为丰富,可以实现其它高级语言难以实现的运算。
3.数据结构类型丰富。
4.具有结构化的控制语句。
5.语法现在不太严格,程序设计自由度大。
6.C语言允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作。因此有人把它称为中级语言。
7.生成目标代码质量高,程序执行效率高。
8.与汇编语言相比,用C语言写的程序可移植性好。
但是,C语言对程序员要求也高,程序员用C写程序会感到限制少、灵活性大,功能强,但较其它高级语言在学习上要困难一些。
1.4面向过程和面向对象的程序设计思想
面向过程:"面向过程"是一种以事件为中心的编程思想。就是分析出解决问题所需要的步骤,然后用函数吧这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象:"面向对象"(Object Oriented,简称OO)是一种以事物为中心的编程思想。
1.5简单的C程序介绍
【例1.1】
void main()
{
printf("hello world!\n");
}
main是主函数的函数名,表示这是一个主函数。
每一个C源程序都必须有,且只能有一个主函数(main函数)。
函数调用语句,printf函数的功能是把要输出的内容送到显示器去显示。
printf函数是一个由系统定义的标准函数,看在程序中直接调用。
【例1.2】
#include <math.h>
#include <stdio.h>
main()
{
double x,s;
printf("input number:\n");
scanf("%lf",&x);
s=sin(x);
printf("sine of %lf is %lf\n",x,s);
}
include称为文件包含命令
扩展名为.h的文件称为头文件
定义两个实数变量,已被后面程序使用
显示提示信息
从键盘获得一个实数x
求x的正弦,并把它赋值给变量s
显示程序运算结果
main函数结束
第二章:数据类型、运算符和表达式
C数据类型
1.基本类型:整形、字符型、实型(浮点型)[单/双精度型]、枚举类型
2.指针类型
3.构造类型:数组类型、结构体类型、共用体类型
4.空类型
关于数据类型
1.基本数据类型:基本数据类型最主要的特点是,其值不可以再分解为其它类型。也就是说,基本数据类型是自我说明的。
2.构造数据类型:构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个"成员"或"元素"。每个"成员"都是一个基本数据类型或又是一个构造类型。在C语言中,构造类型有以下几种:
数组类型、结构体类型、共用体类型结构体类型
共用体(联合)类型
3.指针类型:指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个变量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量,因此不能混为一谈。
4.空类型:在调用函数值时,通常应向调用者返回一个函数值。这个返回的函数值是具有一定数据类型的,应在函数定义及函数说明中给以说明,例如在例题中给出的max函数定义中,函数头为:int max(int a,int b);其中"int"类型说明符即表示该函数的返回值为整形量。但是也有一类函数,调用后并不需要向调用者返回函数值,这种函数可以定义为"空类型"。其类型说明符为void。在后面函数中还要详细介绍。
注:在本章中,我们先介绍基本数据类型中的整型、浮点型和字符型。其余类型在以后各章中陆续介绍。
常量与变量
对于基本数据类型量,按其取值是否可以改变又分为常量和变量两种。
在程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量。
它们可与数据类型结合起来分类。例如,可分为整型常量、整型变量、浮点常量、浮点变量、字符常量、字符变量、枚举常量、枚举变量。在程序中,常量是可以不经说明而直接引用的,而变量则必须先定义以后使用。
(整型量包括整型常量、整型变量。)
常量和符合常量
在程序执行过程中,其值不发生改变的量称为常量。
符号常量:用标识符代表一个常量。在C语言中,可以用一个标识符来标示一个常量。
符号常量在使用之前必须先定义,其一般形式为:
#define 标识符 常量与变量
其中#define也是一条预处理命令(预处理命令都以#开头),称为宏定义命令(在后面预处理程序中将进一步介绍),其功能是把该标识符定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。
习惯上符号常量的标识符用大写字母,变量标识符用小写字母,以示区别。
【例3.1】符号常量的使用
#define PRICE 30 //用标识符代表一个常量,称为符号常量。
void main() //符号常量与变量不同,它的值在其作用域内不能改变,也不能再被赋值。
{
int num,total;
num=10; //使用符号常量
total=num*PRICE; //1.含义清楚
printf("total=%d",total); //2.能做到"一改全改"
}
再来说说变量
其值可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储单元。变量定义必须放在变量使用之前。一般放在函数体开头部分。要区分变量名和变量值是两个不同的概念。
例如:int k = 3;
k <—— 变量名称
3 <—— 变量的值
0x0010ff <—— 变量的地址
整型数据
1.整型常量的表示方法
整型常量就是整常数。在C语言中,使用的整常数有八进制、十六进制、和十进制三种。
1)十进制整常数:十进制整常数没有前缀。其数码为0~9.
以下各数是合法的十进制整常数:237、-568、65536、1627;
在程序中是根据前缀来区分各种进制数的。因此在书写常数时不要把前缀弄错早餐结果不正确。
2)八进制整常数:八进制整常数必须以0开头,即以0作为八进制的前缀。数码取值为0~7.八进制数通常是无符号数。
以下各数是合法的八进制数:015(十进制为13)、0101(十进制为65)、0177777(十进制为65535);
3)十六进制整常数:十六进制整常数的前缀为0X或者0x。其数码取值为0~9,A!F或a~f。
以下各数是合法的十六进制整常数:0X2A(十进制为42)、0XA0(十进制为160)、0XFFFF(十进制为65535);
4)整型常数的后缀:在[16=>64]位字长的机器上,基本整型的长度也为16位,因此表示的数的范围也是有限定的。
十进制无符号整常数的范围为0~65535[2^16],有符号数为-32768~+32767。
八进制无符号数的表示范围为0~0177777。
十六进制无符号数的表示范围为0X0~0XFFFF或0x0~0xFFFF。
如果使用的数超过了上述范围,就必须用长整型数来表示。长整型数是用后缀"L"或"l"来表示的
2.整型变量
1)整型数据在内存中的存放形式
例如:int k = 3;
k <—— 变量名称
3 <—— 变量的值
0x0010ff <—— 变量的地址
另外:这里的3在内存中是以二进制的形式保存的。
补充:内存中的二进制存储(常识:一个字节BYTE=8位bit)
数值是以补码表示的:
。正数的补码和原码相同;
。负数的补码:将该数的绝对值的二进制形式按位取反再加1。
例如:求-10的补码
10的原码:00001010
取反: 11110101
再加1: 11110110 [-10在内存中的存储形式:第一位是符号位]
[附]宽带2M[BPS] => 200kb(1024*2/8)
2.整型变量的分类
(注意:这里占多少个字节跟系统和编译器规定有关!可以在编译器上自己试试查看)
1)基本型:类型说明符为int,在内存中占4个字节。
2)短整型:类型说明符为short int或short。所占字节和取值范围均值与基本类型相同。
3)长整型:类型说明符为long int或long,在内存中占4个字节。
4)无符号型:类型说明符为unsigned。
3.实型变量
由于实型变量是由有限的存储单元组成的,因此能提供的有效数字总是有效的。如下例:
【例3.6】实型数据的[舍入误差]
void main(){
float a,b;
a=12346.789e5;
b=a+20;
printf("%f\n",a);
printf("%f\n",b);
}
补充:
(1)1.0/2*3
(2)3/2
(3)1/3*3
编程(1):
#include <stdio.h>
void main(){
printf("%f\n",1.0/3*3);
}
编程(2):...
编程(3):...
字符型数据
字符型数据包括[字符常量]和[字符变量]。
字符常量:字符常量是用单引号括起来的一个字符。
例如'a'、'b'、'='、'+'、'?' 都是合法的字符常量。
在C语言中,字符常量有以下特点:
1)字符常量只能用单引号括起来,不能用双引号或其它括号。
2)字符常量只能是单个字符,不能是字符串。
3)字符可以是字符集中任意字符。但数字被定义为字符型只会就不能参与数值运算。如'5'和5是不同的。'5'是字符常量,不能参与运算。
字符变量:字符变量用了存储字符常量,即单个字符。
字符变量的类型说明符是char。字符变量类型定义的格式和书写规范都与整型变量相同。
例如:char a,b;
转义字符:转义字符是一种特殊的字符常量。转义字符以反斜杠"\"开头,后跟一个或几个字符。转义字符具有特殊的含义,不同于字符原有的意义,故称"转义"字符。例如,在前面各例题printf函数的格式串中用到的"\n"就是一个转义字符,其意义是"回车换行"。转义字符主要用来表示那些用一般字符不便于表示的控制代码。
转义字符:转义字符的意义:ASCII代码
\n:回车换行:10; \t:横向跳到下一制表位置:9; \b:退格:8;
\r:回车:13; \f:走纸换页:12; \\:反斜杠符"\":92;
\':单引号符:39; \":双引号符:34; \a:鸣铃:7;
\ddd:1~3位八进制数所代表的字符; \xhh:1~2位十六进制数所代表的字符
【例3.8】转义字符的使用。
void main(){
int a,b,c;
a=5;b=6;c=7;
printf("ab c\tde\rf\n");
printf("hijk\tL\bM\n");
}
字符数据在内存中的存储形式及使用方法
每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。
如x的十进制ASCII码是120,y的十进制ASCII码是121.对字符变量a,b赋予'x'和'y'值:
a = 'x';
b = 7;
实际上是在a,b两个单元内存放120和55的二进制代码
八进制|十六进制|十进制|字符
00|00|0|null 100|40|64|@
01|01|1|soh 101|41|65|A
02|02|2|stx 102|42|66|B
03|03|3|etx 103|43|67|C
...
07|07|7|bel
10|08|8|bs
...
17|0f|15|si
20|10|16|dle
...
30|18|24|can 130|58|88|X
31|19|25|em
32|1a|26|sub 132|5a|90|Z
...
41|21|33|! 141|61|97|a
... ...
60|30|48|0
... ...
72|3a|58|9
... 172|7a|122|z
字符型数据
【例3.9】向字符变量赋以整数。
void main(){
char a,b;
a=120;
b=121;
printf("%c,%c\n",a,b);
printf("%d,%d\n",a,b);
}
本程序中定义a,b为字符型,但在赋值语句中赋以整型值。从结果看,a,b值的输出形式取决于printf函数格式串中的格式符,当格式符为"%c"时,对应输出的变量值为字符,当格式符为"%d"时,对应输出的变量值为整数。
【例3.10】小写字母换成大写字母
void main(){
char a,b;
a='a';
b='b';
a=a-32;
b=b-32;
printf("%c,%c\n%d,%d\n",a,b,a,b);
}
比较:char a=33; 和 int a=33;
void main()
{
char a;//1字节 8位 省内存
int b;//4字节
a = 33;
b = 33;
printf("%c,%c\n%d,%d\n",a,b,a,b);//!,! \n 33,33
}
字符串常量
字符串常量是由一对双引号括起来的字符序列。例如:"CHINA"、"C program"、"$12.5"等都是合法的字符串常量。
字符串常量和字符常量是不同的量。它们之间主要有以下区别:
(补充:char占八位而已!)
1)字符常量由单引号括起来,字符串常量由双引号括起来。
2)字符常量只能是单个字符,字符串常量则可以含一个或多个字符。
3)可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。
例如:可以char a='a'; 不能char a = "a";
4)字符常量占一个字节(8位)内存空间。字符串常量占的内存字节数等于字符串中字节数加1.增加的一个字节中存放字符"\0"(ASCII码为0)。这是字符串结束的标志。
例如:字符串"C program"在内存中所占的字节为:
【对应ASCII码存放】|C| |p|r|o|g|r|a|m|\0|
字符常量'a'和字符串常量"a"虽然都只有一个字符,但在内存中的情况是不同的。
'a'在内存中占一个字节,可表示为 |a|
"a"在内存中占两个字节,可表示为 |a|\0|
变量赋初值
在程序中常常需要对变量赋初值,以便使用变量。语言程序中可有多种方法为变量赋初值。本小节介绍在作变量定义的同时给变量赋以初值的方法。这种方法称为初始化。在变量定义中赋值的一般形式为:
类型说明符 变量1=值1,变量2=值2,...;
例如:
int a=3;
int b,c=5;
float x=3.2,y=3f,z=0.75;
char ch1='K',ch2='P';
各类数值型数据之间的混合运算
变量的数据类型是可以转换的。转换的方法有两种,一种是自动转换,一种是强制转换。自动转换发生在不同数据类型的量混合运算时,有编译系统自动完成。自动转换遵循以下规则:
1)弱参与运算量的类型不同,则先转换成同一类型,然后进行运算。
2)转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算。
3)所以的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,在作运算。
4)char型和short型参与运算时,必须先转换成int型。
算术运算符和算术表达式
运算符的优先级:C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应先与"-"结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为"左结合性"。而自右至左的结合方向称为"右结合性"。最典型的右结合性运算符是赋值运算符。如x=y=z,由于"="的右结合性,应先执行y=z再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
算术表达式和运算符的优先级和结合性
下面是C语言中所使用的运算符的优先级和结合性:
优先级|运算符|结合性
(最高)| () [] -> .|自左至右
| !~ ++ -- + - * & sizeof|自右至左
| * / %|自左至右
| + -
| << >>
| < <= > >=
| == !=
| &
| ^
| |
| &&
| ||
| ?: |自右至左
| = += -= /= %= &= ^= |= <<= >>= |自右至左
(最低)| ,|自左至右
自增、自减运算符
自增1运算符:自增1运算符记为"++",其功能是使变量的值自增1。
自减1运算符:自减1运算符记为"--",其功能是是变量的值自减1。
自增1,自减1运算符均为单目运算符,都具有右结合性。可有以下几种形式:
++i i自增1后再参与其它运算。
--i i自减1后再参与其它运算。
i++ i参与运算后,i的值再自增1.
i-- i参与运算后,i的值再自减1.
在理解和使用上容易出错的是i++和i--。特别是当它们出在较复杂的表达式或语句中时,常常难于弄清,因此应仔细分析。
【例3.16】
void main()
{
int i=8;
printf("%d,%d\n",++i,i);//9,8
printf("%d\n\n",i);//9
printf("%d,%d\n",--i,i);//8,9
printf("%d\n\n",i);//8
printf("%d,%d\n",i++,i);//8,8
printf("%d\n\n",i);//9
printf("%d,%d\n",i--,i);//9,9
printf("%d\n\n",i);//8
printf("%d,%d\n",-i++,i);//-8,8
printf("%d\n\n",i);//9
printf("%d,%d\n",-i--,i);//-9,9
printf("%d\n\n",i);//8
}
第三章:顺序程序设计
——最简单的C程序设计
介绍:从程序流程的角度来看,程序可以分为三种基本结构,即顺序结构、分支结构、循环结构。这三种基本结构可以组成所有的各种复杂程序。C语言提供了多种语句来实现这些程序结构。本章介绍这些基本语句及其在顺序结构中的应用,使读者对C程序有一个初步的认识,为后面各章的学习打下基础。
(以下对一些基本的C语句进行介绍,知道的可以跳过!!)
C程序的执行部分是由语句组成的。程序的功能也是由执行语句实现的。
C语句可以分为以下五类:
1)表达式语句:表达式语句有表达式加上分号";"组成。其一般形式为:表达式; 执行表达式语句就是计算表达式的值。
例如:x=y+z;赋值语句;y+z;加法运算语句,但计算结果不能保留,无实际意义;i++;自增1语句,i值增1。
2)函数调用语句;由函数名、实际参数加上分号";"组成。其一般形式为:函数名(实际参数); 执行函数语句就是调用函数体并把实际参数赋予函数定义中的形式参数,然后执行被调函数体中的语句,求取函数值(在后面函数中会再详细介绍)。
例如:printf("C program");//调用库函数,输出字符串。[printf/scanf不引入头文件stdio.h也可以使用,在编译器中声明了]
3)控制语句:控制语句用于控制程序的流程,以实现程序的各种结构方式。它们由特定的语句定义符组成。C语言有九种控制语句。可以分为以下三类:
1>条件判断语句:if语句、switch语句;
2>循环执行语句:do while语句、while语句、for语句;
3>转向语句:break语句、goto语句[地址跳转]、continue语句、return语句;
4)复合语句:把多个语句用括号{}括起来组成的一个语句称复合语句。在程序中应把复合语句看成是单条语句,而不是多条语句。
例如:
{
x=y+z;
a=b+c;
printf("%d%d",x,a);
}
复合语句内的各条语句都必须以分号";"结尾,在括号"}"外不能加分号。
5)空语句:只有分号";"组成的语句称为空语句。空语句是什么也不执行的语句。在程序中空语句可用来作空循环体。
例如:
while(getchar()!='\n')
{
;
}
本语句的功能是,只要从键盘输入的字符不是回车则重新输入。这里的循环体为空语句。
赋值语句:赋值语句是由赋值表达式再加上分号构成的表达式语句。其一般形式为:变量=表达式;
赋值语句的功能和特点都与复制表达式相同。他是程序中使用最多的语句之一。
在赋值语句的使用中需要注意以下几点:
1.由于在赋值符"="右边的表达式也可以又是一个赋值表达式,因此下述形式:
变量=(变量=表达式);//a=b=c=d=e=5;
是成立的,从而形成嵌套的情形。
其展开之后的一般形式为:
变量=变量=...=表达式;//e=5;d=3;c=d;b=c;a=b;
2.注意在变量说明中给变量赋初值和赋值语句的区别。
给变量赋初值是变量说明的一部分,赋初值后的变量与其后的其它同类变量之间扔须用逗号间隔,而赋值语句则必须用分号结尾。
例如: int a=5,b,c;
3.在变量说明中,不允许连续给多个变量赋初值。
如 int a=b=c=5; 必须写为 int a=5,b=5,c=5;
而赋值语句运行连续赋值。
4.注意复制表达式和赋值语句的区别。赋值表达式是一种表达式,它可以出现在任何运行表达式出现的地方,而赋值语句则不能。
下述语句是合法的:if((x=y+5)>0) z=x; 语句的功能是,若表达式 x=y+5大于0则z=x。
下述语句是非法的:if((x=y+5;)>0) z=x; 因为 x=y+5;是语句,不能出现在表达式中。
数据输入输出的概念及在C语言中的实现
1)所谓输入输出是以计算机为主体而言的。
2)本章介绍的是向标准输出设备显示器输出数据的语句。
3)在C语言中,所有的数据输入/输出都是由库函数完成的。因此是函数语句。
4)在使用C语言库函数时,要用预编译命令#include将有关"头文件"包含到源文件中。使用标准输入输出函数时要用到"stdio.h"文件,因此源文件开头应有以下预编译命令:
#include <stdio.h>或#include "stdio.h"
stdio是standard input&output的意思。
5)考虑到printf和scanf函数使用频繁,系统运行在使用这两个函数时可不加#include <stdio.h>或#include "stdio.h"
格式输入与输出
scanf函数(格式输入函数):scanf函数称为格式输入函数,即按用户指定格式从键盘上把数据输入到指定的变量之中。
1.scanf函数的一般形式:scanf函数是一个标准函数,它的函数原型在头文件"stdio.h"中,与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。
scanf函数的一般形式为:scanf("格式控制字符串",地址列表);
其中格式控制字符串的作用与printf函数相同,但不能显示非格式字符串,也就是不能显示提示字符串。地址列表中给出各变量的地址。地址是由地址运算符"&"后跟变量名组成的。
使用printf函数时还要注意一个问题,那就是输出列表中求值顺序。不同的编译系统不一定相同,可以从左到右,也可以从右到左。Turbo C是按从左到右进行的。请看下面两个例子:
【例4.5】
void main()
{
int i=8;
printf("%d,%d,%d,%d,%d,%d\n",++i,--i,i++,i--,-i++,-i--);//8,8,7,8,-7,-8
}
【例4.6】
void main()
{
int i=8;
printf("%d\n",++i);//9
printf("%d\n",--i);//8
...
}
这两个程序的区别是用一个printf语句和多个printf语句输出。但从结果可以看出是不同的!!
顺序结构程序设计举例
【例4.14】输入三角形的三边长,求三角形面积。
已知三角形的三边长a,b,c,则改三角形的面积公式为:
area=√s(s-a)(s-b)(s-c)
其中s=(a+b+c)/2
源程序如下:
#include <math.h>
void main()
{
float a,b,c,s,area;
scanf("%f,%f,%f\n",&a,&b,&c);
s=(a+b+c)/2.0;
area=sqrt(s*(s-a)*(s-b)*(s-c));
printf("a=%7.2f,b=%7.2f,c=%7.2f,s=%7.2f\n",a,b,c,s);
printf("area=%7.2f\n",area);
}
【例4.15】求ax²+bx+c=0方程的根,a,b,c由键盘输入,设b²-4ac>0。求根公式为:
x1=(-b±√(b²-4ac))/2a p=-b/2a
令q=√(b²-4ac)/2a,q=√(b²-4ac)/2a
则x1=p+q
x2=p-q
源程序如下:
#include <math.h>
void main()
{
double a,b,c,disc,x1,x2,p,q;
scanf("a=%lf,b=%lf,c=%lf\n",&a,&b,&c);
disc = b*b-4ac;
p = -b/(2*a);
q = sqrt(disc)/(2*a);
x1 = p+q;
x2 = p-q;
printf("\nx1=%5.2f\nx2=%5.2f\n",x1,x2);
}
第三章 分支程序设计[最常用的C程序设计]
关系运算符和表达式
关系运算符:在程序中经常需要比较两个量的大小关系,以决定程序下一步的工作。比较两个量的运算符称为关系运算符。
运算符的优先次序:
表达式 | 优先级
()(小括号) [](数组下标) .(结构成员) ->(指针型结构成员) | 最高
!(逻辑非) .(位取反) -(负号) ++(加1) --(减1) &(变量地址)| ↑
*(指针所指内容) type(函数说明) sizeof(长度计算)
*(乘) /(除) %(取模)
+(加) -(减)
<<(位左移) >>(位右移)
<(小于) <=(小于等于) >(大于) >=(大于等于)
==(等于) !=(不等于)
&(位与)
^(位异或)
|(位或)
&&(逻辑与)
||(逻辑或)
?:(?表达式)
= += -=(联合操作)
,(逗号运算符) | 最低
在C语言中有以下关系运算符:
1) < 小于
2) <= 小于或等于
3) > 大于
4) >= 大于或等于
5) == 等于
6) != 不等于
关系运算符都是双目运算符,其结合性均为左结合。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,前四个<,<=,>,>=的优先级相同,高于==,!=,==和!=的优先级相同。
关系表达式的一般形式为:表达式 关系运算符 表达式
例如:a+b>c-d x>3/2 'a'+1<c -i-5*j==k+1 都是合法的关系表达式。
由于表达式也可以又是关系表达式。因此也允许出现嵌套的情况。
例如;a>(b>c) a!=(c==d) 等。
关系表达式的值是"真"和"假",用"1"和"0"表示。
如:5>0的值为"真",即为"1"。
(a=3)>(b=5)由于3>5不成立,故其值为假,即为0。
【例5.1】
void main()
{
char c='k';
int i=1,j=2,k=3;
float x=3e+5,y=0.85;
printf("%d,%d\n",'a'+5<c,-i-2*j>=k+1);
printf("%d,%d\n",1<j<5,x-5.25<=x+y);
printf("%d,%d\n",i+j+k==-2*j,k==j==i+5);
}
在本例中求出各种关系运算符的值。字符变量是以它对应的ASCII码参与运算的。对于含多个关系运算符的表达式,如k==j==i+5,根据运算符的左结合性,先计算k==j,该式不成立,其值为0,在计算0==i+5,也不成立,故表达式值为0。
逻辑运算符和表达式[逻辑运算符及其优先次序]
C语言提供了三种逻辑运算符:
1) && 与运算
2) || 或运算
3) ! 非运算
与运算符&&和或运算符||均为双目运算符。具有左结合性。非运算符!为单目运算符,具有右结合性。逻辑运算符和其它运算符优先级关系可表示如下:
!(非) -> &&(与) -> ||(或)
1>int i; i = 3&&5; => i=1;
1>int i; i = 3&&0; => i=0;
2>int i, a=3, b=5; i = 0||5; => i=1;
3>i=5; => !i=0;//注释:解释说明。。
3>i=0; => !i=1;/*注释:解释说明。。*/
【注】"&&"和"||"低于关系运算符,"!"高于算术运算符。
[最低]赋值运算符->&&和||->关系运算符->算术运算符->!(非)[最高]
按照运算符的优先顺序可以得出:
a>b && c>d 等价于 (a>b) && (c>d)
!b==c||d<a 等价于 ((!b)==c) || (d<a)
a+b>c && x+y<b 等价于 ((a+b)>c) && ((x+y)<b)
【例】int a=1,b=2,c=0;
printf("%d\n",a||b&&c);//1
printf("%d\n",(a||b)&&c);//0
逻辑运算的值
逻辑运算的值也为"真"和"假"两种,用"1"和"0"来表示。其求值规则如下:
1.与运算 &&:参与运算的两个量都为真时,结果才为真,否则为假。
例如: 5>0 && 4>2 由于5>0为真,4>2也为真,相与的结果也为真。
2.或运算 ||:参与运算的两个量只要有一个为真,结果就为真。两个量都为假时,结果为假。
例如: 5>0 || 5>8 由于5>0为真,相或的结果也就为真。
3.非运算 !:参与运算量为真是,结果为假。参与运算量为假时,结果为真。
例如: !(5>0) 结果为假。
虽然C编译在给出逻辑运算值时,以"1"代表"真","0"代表"假"。但反过来在判断一个量是为"真"还是"假"时,以"0"代表"假",以非"0"的数值昨晚"真"。
例如:由于5和3均为非"0"因此 5&&8的值为"真",即为1.
又如:5||0的值为"真",即为1。
逻辑表达式
逻辑表达式的一般形式为:表达式 逻辑运算符 表达式
其中的表达式可以又是逻辑表达式,从而组成了嵌套的情形。
例如:(a&&b)&&c 根据逻辑运算符的左结合性,也可写为:a&&b&&c
逻辑表达式的值是式中各种逻辑运算的最后值,以"1"和"0"分别代表"真"和"假"。
【例5.2】
void main()
{
char c='k';
int i=1,j=2,k=3;
float x=3e+5,y=0.85;
printf("%d,%d\n",!x*!y,!!!x);//0,0
printf("%d,%d\n",x||i&&j-3,i<j&&x<y);//1,0
printf("%d,%d\n",i==5&&c&&(j=8),x+y||i+j+k);//0,1
}
if语句
用if语句可以构成分支结构。它根据给定的条件进行判断,以决定执行某个分支程序段。C语言的if语句有三种基本形式。
第一种形式为基本形式:if(表达式) 语句
其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。其过程可表示为下图:
int a,b,max;
printf("\n input two numbers:");
scanf("%d,%d",&a,&b);//默认换行分割,此处为","分割
max=a;
if(max<b) max=b;
printf("max=%d",max);
第二种形式为:if-else
if(表达式)
语句1;
else
语句2;
int a,b;
printf("input two numbers:");
scanf("%d%d",&a,&b);
if(a>b){
printf("max=%d",a);
}else{
printf("max=%d",b);
}
第三种形式为 if-else-if形式
前两种形式的if语句一般都用于两个分支的情况。当有多个分支选择时,可采用if-else-if语句,其一般形式为:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
...
else
语句3;
char c;
printf("input a character: ");
c=getchar();
if(c<32) printf("This is a control character\n");
else if(c>='0'&&c<='9') printf("This is a digit\n");
else if(c>='A'&&c<'Z') printf("This is a capital letter");
else if(c>='a'&& c<'z') printf("This is a small letter");
else printf("This is an other character\n");