提示:
本章为前七章节的基础知识总结,有:
“基本数据类型,运算符与表达式,循环与分支,数组”这几类知识点构成,这些知识点超级基础,所以我们直接出一些硬核又容易理解的内容进行一下讲解。
目录:
一、基本数据类型
1、主函数(main函数),有且只有一个,函数从main函数开始执行到main函数结束;
2、C语言的基本单位是:语句;且句必须以分号;为结束的标志语;
3、注释:
①//后面是多行注释;
②/* */中间可以写多行注释;
③计算机不会编译注释的内容(也就是说注释内容不执行);
4、变量:
①是一个有名字,有特定属性的一个存储单位;
②用途:存储数据;
③变量必须先定义后使用,变量的命名必须符合规范;
④变量名区分大小写;
5、标识符命名规则:
①只能由字母,数字,下划线组成;
②开头不能是数字,只能是字母或下划线;
③关键字不能作为标识符;
6、C语言的基本数据类型包括:整型(int)、实型(float)、字符型(char);
7、整型常量的表示方法:
①十进制:十进制整常数没有前缀,其数码为0~9。如:237,-568,65535,1627这些都是合理的整常数,而023(不能有前导0,那是八进制的象征)、23D(含有非十进制数码)就不是合理的整常数;
②八进制:前缀为0,数码值为0~7,八进制通常为无符号数 。如:015(十进制为13)、0101(十进制为65)、0177777(十进制为65535)这些都是合法的八进制整常数,而256(无前缀0)、03A2(含有非八进制数码)、-0127(出现了负号);
③十六进制:前缀0X或者是0x,其数码取值为0~9,A~F或a~f。如:0X2A(十进制为42)、0XA0 (十进制为160)、0XFFFF (十进制为65535);而以下各数不是合法的十六进制整常数:5A(无前缀0X)、0X3H (含有非十六进制数码);
8、实型常量的表示方法:
实型也称为浮点型(float)。实型常量也称为实数或者浮点数。在C语言中,实数只采用十进 制。它有二种形式:十进制小数形式,指数形式。①十进制数形式:由数码0~ 9和小数点组成。如:0.0、25.0、5.789、0.13、5.0、300.、-267.8230等均为合法的实数。注意,必须有小数点。
②指数形式:由十进制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为:
a E n(a为十进制数,n为十进制整数)
其值为 a*10n。
如:
2.1E5 (等于2.1*105)
3.7E-2 (等于3.7*10-2)
0.5E7 (等于0.5*107)
-2.8E-2 (等于-2.8*10-2)
以下不是合法的实数:
345 (无小数点)
E7 (阶码标志E之前无数字)
-5 (无阶码标志)
53.-E3 (负号位置不对)
2.7E (无阶码)
标准C允许浮点数使用后缀。后缀为“f”或“F”即表示该数为浮点数。如356.f 和356.是等价的。
用一段简单的程序说明一下,大家可以上机运行:
#include<stdio.h> main(){ printf("%f\n ",356.); printf("%f\n ",356); printf("%f\n ",356.f); }
9、字符常量:是单引号括起来的一个字符。如:‘a'、'b'、'='、'+'、'?'
10、字符常量的特点:
①字符常量只能用单引号括起来,不能用双引号或其它括号。
②字符常量只能是单个字符,不能是字符串。
③字符可以是字符集中任意字符。但数字被定义为字符型之后就不能参与数值运算。如'5'和5 是不同的。'5'是字符常量,不能参与运算。
11、字符串常量:字符串常量是由一对双引号括起的字符序列。如: "CHINA" , “C program” , "$12.5" 等都是合法的字符串常量。
12、字符常量和字符串常量的区别:
①字符常量由单引号括起来,字符串常量由双引号括起来;
②字符常量只能是单个字符,字符串常量则可以含一个或多个字符;
③可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。在C语言中没有相应的字符串变量。这是与BASIC 语言不同的。但是可以用一个字符数组来存放一个字符串常量。
④字符常量占一个字节的内存空间。字符串常量占的内存字节数等于字符串中字节数加1。增加的一个字节中存放字符"\0" (ASCII码为0)。这是字符串结束的标志。
如:字符串 "C program" 在内存中所占的字节为:
字符常量'a'和字符串常量"a"虽然都只有一个字符,但在内存中的情况是不同的。
'a'在内存中占一个字节,可表示为:
"a"在内存中占二个字节,可表示为:
二、运算符与表达式
1、运算符优先级:
2、C语言的运算符可分为以下几类:
①算术运算符:用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%注意运算对象必须是整型常量)、自增(++)、自减(--)共七种;
②关系运算符:用于比较运算。包括大于(>)、小于(<)、等于(==)、 大于等于(>=)、小于等于(<=)和不等于(!=)六种;
③逻辑运算符:用于逻辑运算。包括与(&&)、或(||)、非(!)三种;
④位操作运算符:参与运算的量,按二进制位进行运算。包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种;
⑤赋值运算符:用于赋值运算,分为简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)和复合位运算赋值(&=,|=,^=,>>=,<<=)三类共十一种;
⑥条件运算符:这是一个三目运算符,用于条件求值( ? : );
⑦逗号运算符:用于把若干表达式组合成一个表达式( ,);
⑧指针运算符:用于取内容(*)和取地址(&)二种运算;
⑨求字节数运算符:用于计算数据类型所占的字节数(sizeof);
⑩特殊运算符:有括号(),下标[],成员(→,.)等几种;3、强制类型转换运算符:
一般形式为: (类型说明符) (表达式)功能:把表达式的运算结果强制转换成类型说明符所表示的类型。
如:(float) a 把a转换为实型;
(int)(x+y) 把x+y的结果转换为整型;
注意:想转换的类型必须用括号括起来且放在被转换的变量之前。
4、自增、自减运算符:
自增1运算符记为“++”,其功能是使变量的值自增1;
自减1运算符记为 “--”,其功能是使变量的值自减1;
自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式:
++i i自增1后再参与其它运算。
int i=5; ++i; printf("%d",i); //输出i的值为6
i++ i自减1后再参与其它运算。
int i=5; i++; printf("%d",i); //输出i的值为6,但i++的值为5
--i i参与运算后,i的值再自增1。
int i=5; --i; printf("%d",i); //输出i的值为4
i-- i参与运算后,i的值再自减1。
int i=5; i--; printf("%d",i); //输出i的值为4,但i--的值为5
5、复合的赋值运算符:
在赋值符“=”之前加上其它二目运算符可构成复合赋值符。如:+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=。构成复合赋值表达式的一般形式为:变量 双目运算符=表达式 a += 5
它等效于
变量=变量 运算符 表达式 a=a+5
如:
a+=5; //等价于a=a+5 x*=y+7; //等价于x=x*(y+7) r%=p; //等价于r=r%p
复合赋值符这种写法,对初学者可能不习惯,但十分有利于编译处理,能提高编译效率并产生质量较高的目标代码。
6、逗号运算符和逗号表达式:
在C语言中逗号“ ,”也是一种运算符,称为逗号运算符。功能:把两个表达式连接起来组成一个表达式, 称为逗号表达式。
一般形式为:
表达式1,表达式2
求值过程:分别求两个表达式的值,并以表达式2的值作为整个逗号表达式的值。
如:
#include<stdio.h> main(){ int a=2,b=4,c=6,x,y; y=(x=a+b),(b+c); printf("y=%d,x=%d",y,x); //输出结果为:y=6,x=6。此处注意,虽然逗号运算符是以最右边的表达式的值为结果,但是此处y会先和(x=a+b)结合,因为赋值运算符的优先级高于逗号运算符 }
若程序改写成这样:
#include <stdio.h> int main() { int a=2,b=4,c=6,x,y; y=(x=a+b,b+c); printf("y=%d,x=%d",y,x); //输出结果为:y=10,x=6。因为括号运算符的优先级最高,所以可以在括号内进行算数运算符计算结束后,再对逗号运算符进行计算,取最右边式子b+c的值为整个式子的值赋值给y return 0; }
三、循环与分支
1、结构化程序的基本控制结构是:选择结构,顺序结构,循环结构;
2、关于if语句(选择结构)的三种基本形式:
①if(表达式)语句;
②if-else语句;
③if-else-if语句;
3、在使用if语句中还应注意以下问题:
①在三种形式的if语句中,在if关键字之后均为表达式。 该表达式通常是逻辑表达式或关系表达式, 但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量;if(a=5) 语句; if(b) 语句; //都是允许的。只要表达式的值为非0,即为“真”。 //如: if(a=5)…; //其中,表达式的值永远为非0,所以其后的语句总是要执行的,当然这种情况在程序中不一定会出现,但在语法上是合法的。 又如,有程序段: if(a=b) printf("%d",a); else printf("a=0"); //本语句的语义是,把b值赋予a,如为非0则输出该值,否则输出“a=0”字符串。这种用法在程序中是经常出现的。
②在if语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号;
③在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{ }括起来组成一个复合语句。但要注意的是在{ }之后不能再加分号;
例如:
if(a>b) { a++; b++; } else { a=0; b=10;} //多个语句需要用花括号给括起来,且花括号外面不放分号,因为一个花括号包含在内的东西就是一整个语句了。
4、条件运算符和条件表达式(选择结构):
条件运算符是一个三目运算符,由“ ? ”和“ :”组成,运用条件运算符可以使程序看起来更加简洁。
如:
if(a>b) max=a; else max=b; //可用条件表达式写为 max=(a>b) ?a:b; //执行该语句的语义是:如a>b为真,则把a赋予max,否则把b赋予max。
5、使用?:条件表达式时,还应注意以下几点:
①条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符。
因此,
max=(a>b)?a:b
可以去掉括号而写为:
max=a>b?a:b
②条件运算符?和:是一对运算符,不能分开单独使用。
③条件运算符的结合方向是自右至左。
例如:
a>b?a:c>d?c:d
应理解为
a>b?a:(c>d?c:d)
这也就是条件表达式嵌套的情形,即其中的表达式3又是一个条件表达式。
6、switch语句(选择结构)的注意点:
①在case后的各常量表达式的值不能相同,否则会出现错误;
②在case后,允许有多个语句,可以不用{}括起来;
③各case和default子句的先后顺序可以变动,而不会影响程序执行结果;
④default子句可以省略不用;
【举个例子---- 计算器程序】 用户输入运算数和四则运算符,输出计算结果。 #include<stdio.h> main(){ float a,b; //定义两个要被计算的数 char c; //定义要计算的符号 printf("input expression: a+(-,*,/)b \n"); scanf("%f%c%f",&a,&c,&b); //输入计算数和运算符号 switch(c) { case '+': printf("%f\n",a+b);break; case '-': printf("%f\n",a-b);break; case '*': printf("%f\n",a*b);break; case '/': printf("%f\n",a/b);break; default: printf("input error\n"); } }
若输入的a为5,运算符为 +,b为6,则运算结果为:11.000000(双精度保留6位小数)
7、break语句
<1>使用范围:switch和循环语句;
<2>在switch语句内:可使程序跳出switch而执行switch之后的语句,若没有break语句,则成为死循环无法退出;
<3>在循环语句中,while,do-while,for循环语句中,break语句可使程序终止循环而执行后面的语句;
<4>break语句对if-else的条件语句不起作用;
<5>在多层循环中,一个break语句只向外跳一层;
8、continue语句
<1>使用范围:只能用在while,do-while,for等循环体中,常与if一起使用;
<2>作用:跳过循环体中剩余的语句而执行下一次的循环,即只跳过这一层的内循环,但并不退出外循环。
9、while语句(循环结构):
一般形式为:
while(表达式)语句
其中表达式是循环条件,语句为循环体。
while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体语句。其执行过程可用下图表示。
举个例子:统计从键盘输入一行字符的个数。
#include<stdio.h> main { int i=0 ; printf("input a string:\n"); while(getchar()! ='\n') i++; //循环条件为getchar()!='\n',其意义是: 只要从键盘输入的字符不是空格(即回车)就继续循环。循环体i++完成对输入字符个数计数。从而程序实现了对输入一行字符的字符个数计数。 printf("%d",i); }
使用while语句应注意以下几点:
①while语句中的表达式一般是关系表达或逻辑表达式,只要表达式的值为真(非0)即可继续循环。
②循环体如包括有一个以上的语句,则必须用{}括起来,组成复合语句。
10、do-while语句(循环结构):
一般形式为:
do
语句
while(表达式);
do-while与while循环的区别:它先执行循环中的语句,然后再判断表达式是否为真, 如果为真则继续循环;如果为假, 则终止循环。因此, do-while循环至少要执行一次循环语句。其执行过程可用下图表示。
举个例子:求1~100求和(1+2+3+......+100=?)
#include<stdio.h> main() { int i=1,sum=0; do{ sum=sum+i; i++; } while(i<=100) printf("%d\n",sum); }
注意:当有许多语句参加循环体时,要用{}给括起来。
11、for语句
<1>一般形式:for(式①;式②;式③)语句;3
<2>应用形式:for(循环变量赋初值;循环条件;循环变量增量)语句;
<3>举例:
for(i=1;i<=100;i++)sum=sum+i;
此处的for语句可等价于while语句,相当于:
int i=1; while(i<=100) { sum=sum+i; i++; }
<4>while语句和for语句的等价:
<5>在for循环中,式①式②式③都是选择项,可以缺省,但 ; 不能省略;
<6>若省略式②,则不给循环设条件,此循环则成为死循环,如:
for(i=1;;i++)sum=sum+i;
也可以用while语句表示为:
int i=1; while(1) { sum=sum+i; i++; }
<7>若三个式子都省略,则相当于:
for( ; ; )语句;
等价于:
while(1)语句;
12、几种循环的比较
<1>四种循环都可以用来处理同一个问题,一般可以互相代替。但一般不提倡用goto型循环。<2>while和do-while循环,循环体中应包括使循环趋于结束的语句(如:不满足循环条件,或者是有break语句)。其中,for语句功能最强。
<3>用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成,而for语句可以在表达式1中实现循环变量的初始化。
四、数组
数组可分为数值数组、字符数组、指针数组、结构数组等各种类别。
1、一维数组
<1>定义方式:类型说明符 数组名[常量表达式];
<2>举例:
int a[10]; //说明整型数组a有10个元素 float b[10],c[20]; //说明实型数组b有10个元素,实型数组c有20个元素 char ch[20]; //说明字符型数组ch有20个元素
<3>一维数组元素的一般形式:数组名[下标]
<4>一维数组初始化的一般形式:类型说明符 数组名[常量表达式]={值,值......值};
2、二维数组
<1>定义方式:类型说明符 数组名[常量表达式1][常量表达式2]
<2>举例:
int a[3][4] //说明了一个三行四列的数组,数组名为a,其下标变量的类型为整型。该数组的下标变量共有3×4个 即: a[0][0],a[0][1],a[0][2],a[0][3] a[1][0],a[1][1],a[1][2],a[1][3] a[2][0],a[2][1],a[2][2],a[2][3]
<3>二维数组元素的一般形式:数组名[下标][下标]
3、字符串处理函数
字符串处理函数包含:字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。 使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件"stdio.h",使用其它字符串函数必须包含头文件"string.h"。下面是几个最常用的字符串函数。
<1>字符串输出函数 puts
①格式: puts (字符数组名)② 功能:把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串。
③举个例子:
#include"stdio.h" #include"string.h" main() { char c[]="BASIC\nBASE"; //'/n'为换行符 puts(c); //利用puts函数将定义的字符串输出 return 0; }
运行结果如下:
④从程序中可以看出puts函数中可以使用转义字符,因此输出结果成为两行。puts函数完全可以由printf函数取代。当需要按一定格式输出时,通常使用printf函数。
<2>字符串输入函数gets
①格式: gets (字符数组名)②功能:从标准输入设备键盘上输入一个字符串。
本函数得到一个函数值,即为该字符数组的首地址。
③举个例子:
#include"stdio.h" #include"string.h" main() { char st[15]; printf("input string:\n"); gets(st); puts(st); return 0; }
④当输入的字符串中含有空格时,输出仍为全部字符串。说明gets函数并不以空格作为字符串输入结束的标志,而只以回车作为输入结束。这是与scanf函数不同的。
<3>字符串连接函数strcat
①格式: strcat (字符数组名1,字符数组名2)②功能:把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志“\0”。本函数返回值是字符数组1的首地址。
③举个例子:
#include<stdio.h> #include<string.h> main() { static char st1[30]="My name is "; char st2[10]; printf("input your name:\n"); gets(st2); strcat(st1,st2); puts(st1); return 0; }
输入“想吃荔枝”的运行结果为:
④本程序把初始化赋值的字符数组与动态赋值的字符串连接起来。要注意的是,字符数组1应定义足够的长度,否则不能全部装入被连接的字符串。
<4>字符串拷贝函数strcpy
①格式: strcpy (字符数组名1,字符数组名2)
②功能:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“\0”也一同拷贝。字符数名2,也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。
③举个例子:
#include"stdio.h" #include"string.h" main() { char st1[15],st2[]="C Language"; strcpy(st1,st2); puts(st1);printf("\n"); return 0; }
运行结果为:
④本函数要求字符数组1应有足够的长度,否则不能全部装入所拷贝的字符串。
<5>字符串比较函数strcmp
①格式: strcmp(字符数组名1,字符数组名2)
②功能:按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。
字符串1=字符串2,返回值=0;
字符串2>字符串2,返回值>0;
字符串1<字符串2,返回值<0。
本函数也可用于比较两个字符串常量,或比较数组和字符串常量。
③举个例子:
#include"stdio.h" #include"string.h" main() { int k; static char st1[15],st2[]="C Language"; printf("input a string:\n"); gets(st1); k=strcmp(st1,st2); if(k==0) printf("st1=st2\n"); if(k>0) printf("st1>st2\n"); if(k<0) printf("st1<st2\n"); return 0; }
比如输入xiangchilizhi,运行结果如下:
④输入要比较的字符串后会根据每个字符的ACSLL码值进行比较,最后得出结果。
<6>测字符串长度函数strlen
①格式: strlen(字符数组名)②功能:测字符串的实际长度(不含字符串结束标志‘\0’) 并作为函数返回值。
③举个例子
#include"stdio.h" #include"string.h" main() { int k; static char st[]="C language"; k=strlen(st); printf("The lenth of the string is %d\n",k); return 0; }