C语言程序设计期末总复习.docx
《C语言程序设计期末总复习.docx》由会员分享,可在线阅读,更多相关《C语言程序设计期末总复习.docx(32页珍藏版)》请在冰点文库上搜索。
C语言程序设计期末总复习
C语言程序设计期末总复习
一、基本概念
※所谓词法记号,是指程序中具有独立含义的不可进一步分割的单位,具体地说,C语言的词法记号可分成5类:
关键词、标识符、常量、运算符、分隔符。
※关键词是C语言中预定义的符号,他们有固定的含义,用户所定义的任何名字都不得与它们冲突。
※标识符是用户自行定义的符号。
用来标识常量、变量、函数、标号等。
C语言要求,所有标识符必须先定义/说明后使用。
ANSI规定,标识符是由字母或下划线(_)开头,后跟零个或多个字母、下划线和数字中任何一个符号所组成的符号序列。
※C语言是区分大小写的,因此,int是关键词,而Int则是标识符。
※分隔符用于分隔各种词法记号,常用的分隔符有:
[](){}*.:
=;#。
※C语言中,为解决具体问题,要采用各种类型的数据,数据类型不同,它们所能表达的数据范围、精度和所占据的存储空间均不相同。
※有符号整数在内存中以补码表示,其最高位为1时表示负数,最高位是0时表示非负数。
※浮点型用来表示实型数据。
浮点型分为两种:
单精度和双精度,分别以float和double表示。
※字符型用char表示,一般用8位来存放一个字符,实际上存放的是该字符的ASCII码值。
在整型常数后跟有字母l或L时,表示该整型常量是长整型常量。
※字符型常量是用单引号括起来单一字符,一个字符常量的值就是该字符的ASCII码值。
※字符串常量是双引号括起来的零个、一个或多个字符的序列。
编译程序自动地在每一个字符串末尾添加串结束符’\0’。
一个字符串常量在程序正文中出现,即代表此字符串常量的首地址。
※一个变量由一个名字来标识,变量在内存中占据一定的存储单元,该存储单元存放变量的值。
变量名与内存中的某一存储单元相联系,而变量值是指存放在该存储单元的数据的值。
变量被说明后,根据其类型的不同,拥有大小不同的存储单元。
没有定义/说明的变量,就没有存储单元,因而不能使用。
※对于除法运算符(‘/’),若除数和被除数均为整数,则商只取整数部分,舍弃小数部分,如6/4=1;而若除数或被除数中,只要有一个为实数,则结果是double型的。
如:
6/4.0=1.5。
取模运算符%,它求出%两侧的两个整形数据整除后的余数。
※++、--运算符只能用于变量,而不能用于常量和表达式。
++、--运算符可以作为变量的前缀,也可以作为变量的后缀,但用作前缀时,++和--表示先增加或减少再取其值,而用作后缀时,++和--表示先取其值再增加或减少。
※关系运算符有:
>、>=、<、<=、==、!
=,关系运算符的优先级低于算术运算符。
若关系成立,则表达式值为零非整数(系统实现时往往为1);若不成立,则表达式值为零。
可见,在C语言中是用非0整数表示真,用0表示假。
※逻辑运算符有:
&&、||、!
逻辑与符号&&的运算规则:
若左右两个操作数均为非零,则返回值为非零,否则返回值为假。
※逻辑或符号||的运算规则:
若左右两个操作数有一个为非零,则返回值为非零,否则返回零。
逻辑非符号!
的运算规则:
把非零操作数转换为零,而把零操作数转换为非零。
※C语言中,&&和||是短路运算符号。
即在从左向右求解一个或多个&&相连的表达式中,只要遇到一个操作数为零,就不再做后面的&&运算,整个表达式的结果为零。
而在从左向右求解一个或多个||相连的表达式中,只要遇到一个操作数为1,就不再做后面的||运算,整个表达式的结果为1。
※赋值运算符:
=
赋值表达式:
由赋值运算符组成的表达式
一般形式为:
<变量><赋值运算符><表达式>
※条件表达式:
一般形式:
<表达式1>?
<表达式2>:
<表达式3>
含义:
首先计算<表达式1>的值,若为非零,则表达式的值为<表达式2>,否则表达式的值为<表达式3>。
举例:
max=(a>b)?
a:
b/*将a、b两数中的较大值送给max*/
※逗号运算符:
逗号表达式:
一般形式为:
<表达式1>,<表达式2>如:
a=3*8,a+2先求a=3*8,得24,然后求解a+2,得26。
故表达式的值为26。
※类型转换
当表达式中出现不同类型的操作数时,要按规则将其转换成同一类型,再做运算。
转换规则是:
精度低的操作数类型转换成精度高的操作数类型,占用内存少的操作数类型转换成占用内存多的操作数类型,数据范围小的操作数类型转换成数据范围大的操作数类型。
这种类型转换是系统自动进行的,无需程序员参与。
※强制转换:
其一般形式是:
(<类型名>)<表达式>例如:
(float)i;若i是整型,则(float)i是float型,但i仍然是整型,(float)i只是一个中间结果。
※允许在说明变量的同时对其初始化。
例如:
intsum=0;/*sum的类型为整型,初始值为0*/
※赋值语句:
由赋值表达式加上一个分号组成,如:
sum=a+b;而sum=a+b则是一个赋值表达式。
※格式输出函数printf
格式:
printf(控制字符串,参数1,参数2,……)
控制字符串:
用双引号括起来的字符串。
包括两种信息:
1.格式说明:
由"%"和转换字符组成,如:
%d、%f等,其作用是将与其对应的数据按格式说明指定的格式输出。
格式说明总是以”%”开头,以转换字符结束。
要特别注意,格式串中格式说明的个数,必须与要输出的数据的个数相等,且数据的类型与相应的格式符一致。
常见格式符的含义是:
d:
十进制整数;f:
浮点小数;c:
单个字符;s:
字符串;u:
无符号整数。
2.普通字符:
即按照原样输出的字符
※putchar函数:
格式:
putchar(c)功能:
输出字符变量c的值
※scanf函数:
格式:
scanf(控制字符串,参数1,参数2,……)
控制字符串中包括普通字符和格式说明,控制字符串中还可以包含空格、制表符或换行符,但这些均被忽略。
对控制字符串中的普通字符,在输入中要输入与这些字符相同的字符;控制字符串中的格式说明是由字符%开始,到转换字符(其含义与printf的含义相同)结束。
控制字符串后面的所有参数都必须是地址形式的。
※getchar函数格式:
getchar(),功能:
接受用户从键盘输入的单个字符。
※一个C语言的程序在能正常运行之前,必须经过编辑、编译和连接这三个步骤。
编辑是指利用文本编辑器,输入、修改C语言的源程序(这是一个文本文件),编译是指利用C语言的编译系统将C语言的源程序翻译成一个二进制的目标文件(目标文件仍然是不能运行的),连接是指利用C语言的编译系统将C语言的一个或多个目标文件和C语言本身的库文件连接成一个可执行文件。
※程序调试:
通过运行程序,发现并改正程序中错误的过程称为程序调试。
通过了编译和连接的C语言源程序,应该说已经没有语法错误了,但很可能还有逻辑错误,任何编译系统都找不出逻辑错误,这只能靠程序员自己去发现并改正。
在TurboC2.0中,主要的程序调试手段有:
单步执行、设置断点、设置观察窗口。
单步执行程序可按F7或F8(按F7可将单步执行延伸到被调用函数的内部,按F8的单步执行仅限于主调函数内),按Ctrl+F7组合键可以添加多个变量到观察窗口,按Ctrl+F8组合键可以设置断点。
※语句可以分为五大类:
1.表达式语句:
表达式的后面加一个分号
⑴赋值语句
⑵自加减运算符构成的表达式语句
⑶逗号表达式语句
2.空语句:
只有一个分号,作为语句结束符
3.复合语句:
由"{"和"}"把一些变量说明和语句组合在一起,又称语句块。
如:
{inta=0,b=1,sum;sum=a+b;printf("%d",sum);}
4.函数调用语句:
由一个函数调用加上一个分号组成,如:
printf("Thisisafunctioncall");
5.控制语句,共有9种,即:
⑴if语句
⑵switch语句
⑶while语句
⑷do-while语句
⑸for语句
⑹break语句
⑺continue语句
⑻goto语句
⑼return语句
※C语言提供两种分支判断语句:
if语句和switch语句。
其中if语句是单或双分支语句,switch语句是多分支语句,每一种分支语句都有各自的适用场合,编程时由程序员根据具体情况决定使用哪一种分支语句。
※if语句的一般形式:
if(<表达式>)
<语句1>
[else
<语句2>]
注:
[]中的内容是可选的。
即,if后面可以没有else,但else前面不能没有if。
这里的语句1和语句2被称为if-else结构中的内嵌语句,内嵌语句与程序中的其它独立语句是有区别的,语句1和语句2可以是单条语句也可以是复合语句,整个if-else语句,在程序中被看成是一条语句。
例如,可以充当循环语句的循环体而无需加上一对花括号。
if后面圆括号中的表达式,可以是任何表达式,总之在C程序中是以非零为真,以零为假。
表达式为真时执行语句1,否则执行语句2,语句1和语句2只能执行其中之一。
if语句是可以嵌套的,即if语句中的内嵌语句1和内嵌语句2仍然可以是if语句,这就构成了if语句的嵌套。
而且C语言并不限制嵌套的层次。
这时,尤其要注意if与else的配对关系,为了避免嵌套的if-else的二义性,C语言规定:
else与其前最近的且尚未配对的if配对。
有时,为了明确if与else的配对关系添加一对花括号是必要的,花括号内是一个相对独立的程序单元,花括号内的if与花括号外的else没有关系。
※switch语句的一般形式是:
switch(<表达式>)
{case<常量表达式1>:
<语句序列1>
case<常量表达式2>:
<语句序列2>
:
:
case<常量表达式n>:
<语句序列n>
default:
<语句序列n+1>
}
case后面必须是常量表达式,而不能是包含变量的表达式,case和常量之间要有空格,case后面的常量之后有":
",且所有的case和default包含在"{}"里,语句序列中的最后一条语句应该是break,以保证执行完某一语句序列后能跳出switch结构,多个常量表达式可以共用一个语句序列。
※循环结构又称重复结构,可以完成重复性、规律性的操作。
C语言共有三种类型的循环语句:
while、do-while和for
※while循环的一般格式:
while(<表达式>)
<循环体>
其语义是:
当<表达式>的值为非零时,则执行<循环体>,然后再判断<表达式>的值,只要它不为零,继续执行<循环体>,如此重复,直到<表达式>的值为零为止。
while循环是判断表达式在先,执行循环体在后,若表达式一开始就为假,则循环体一次也不执行。
※do-while语句的一般格式是:
do
<循环体>
while(<表达式>);
其语义是:
先执行<循环体>,再判别<表达式>,若<表达式>的值为非零,则重复执行<循环体>,直到<表达式>的值为零为止。
do-while循环是先执行循环体,后判断表达式,即使表达式一开始就为假,循环体也能执行一次。
※这两种循环的一般使用形式是:
循环开始前要设置好循环的初始条件,在循环体中要有改变循环条件的语句,以保证循环能正常结束,否则将形成所谓的死循环。
※for语句的一般形式:
for语句是比前面两种循环功能更强的一种循环语句。
for循环的格式如下:
for(<表达式1>;<表达式2>;<表达式3>)
<循环体>
三个表达式之间必须用分号(;)隔开。
※for语句的执行过程如下:
①首先计算<表达式1>。
②求<表达式2>的值,若其值为非零,执行<循环体>,然后转③执行,若<表达式2>的值为零,则结束for语句。
③求解<表达式3>,转②执行。
for循环的三个表达式可以是C语言中任何有效的表达式。
一般情况下,<表达式1>是用来设置循环初始状态的,<表达式2>是用来设置循环结束条件的,<表达式3>是用来改变循环条件的。
※在一个循环内又完整地包含另一个循环,称为循环的嵌套,即循环体本身包含循环语句。
前面介绍了三种类型的循环,它们自己本身可以嵌套,如在for循环中包含另一个for循环。
也可以互相嵌套,例如可以在for循环中包含一个while循环或者do-while循环等等。
※break语句的形式为:
break;
语义:
跳出当前的switch语句或当前的循环语体。
一般情况下,break语句放在if语句中,其作用是为终止循环多提供一个出口。
※continue语句的一般形式为:
continue;
语义为:
结束本次循环,即跳过循环体中尚未执行的语句,接着进行循环条件的判定。
continue语句只用在for,while,do-while等循环体中,常与if语句一起使用。
其作用是在满足if语句条件的情况下,有选择地执行循环语句。
※goto语句的一般形式为:
goto <语句标号>;
语义是:
无条件地转向<语句标号>处。
goto语句通常与if语句连用,在满足某一条件时,程序跳到标号处执行。
使用goto语句会打乱各种有效的控制语句,造成程序结构不清晰。
goto语句应该慎用、少用。
※结构化程序设计:
结构化程序设计是一种程序设计的思想和规范。
其要点有两个,其一是:
任何程序设计问题均可用顺序、循环和选择(即分支)这三种基本程序结构予以解决。
其二是:
程序的总体组织结构化,也就是将程序设计问题进行一步步的分解,一直分解到一个个层次清楚、功能单一、相互独立的子问题,而每一个子问题都可以用一个程序模块予以解决,最后再用各种层次的调度模块,把这些子模块有机地组织起来。
结构化程序设计很像是儿童搭积木。
程序设计是一项充满挑战的创造性的工作,仅仅熟练掌握一、两种程序设计语言是远远不够的,程序设计更需要方法论的指导。
※C语言中有标准库函数和自定义函数。
C程序往往由多个函数组成,函数是C程序的基本组成单位,所谓函数就是一个功能单一又相对独立的程序模块,函数通过参数传递和返回值与外界相关联。
main函数是C程序的总入口,由main来调用其他函数,其他函数之间可以相互调用,也可以自己调用自己。
※函数定义的一般形式:
<类型标识符><函数名>([<参数说明部分>])
{<说明部分>
<语句部分>
}
<函数名>是一个用户定义的标识符,方括号表示是可选项。
<参数说明部分>的一般形式为:
<类型标识符><参数>,{,<类型标识符><参数>,}
<函数体>由花括号括起的部分称为函数体,它由<说明部分>和<语句部分>共同组成,函数的功能是由函数体完成的。
<返回值>:
函数名前面的<类型标识符>表明了从函数返回的值是什么类型,它可以是int,float,char等,函数也可以不返回任何值,这时类型标识符就用关键字void表示,void的含义是空。
<返回语句>:
在函数定义的<语句部分>中,可以有一返回语句,返回语句有两种格式:
(1)return;//表示该函数无返回值
(2)returnr;或return(r);//把r作为返回值
※函数调用形式:
<函数名>([<实参表列>])
<实参表列>可以省略,可以包含一个或多个实参,多个实参之间需用逗号隔开。
实参与形参必须一一对应。
※C语言的参数传递规则:
是按值传递,即把实在参数的值拷贝到相应的形参中去,形参和实参占用不同的存储单元,被调用函数中改变形参的值不会改变实参的值。
※函数说明的一般形式:
<类型标识符><函数名>([<参数表列>]);
最后一个分号(;)不可少,这是编译程序用来区分函数说明和函数定义的标志。
即有分号表示函数说明,无分号表示函数定义。
若函数定义在前,调用在后,则无需说明,只有当调用在前,定义在后时,才需要函数说明。
※函数的调用和返回:
弄清楚在函数调用和返回时系统做了哪些工作,对于理解函数的一般调用、嵌套调用尤其是递归调用至关重要。
在函数调用时,首先要保护好主调函数的现场,主要是保存好主调函数中局部变量(含形参)的值和返回地址的值(函数调用语句下一条语句的地址),接着程序的控制流程转到了被调函数,为被调函数中的局部变量和形参分配存储单元,实参的值拷贝给形参,执行被调函数直至结束。
在被调函数中遇到return语句或执行到最后一行,则被调函数执行结束。
被调函数执行结束后,释放被调函数中局部变量所占的存储单元,按照当初保存起来的返回地址,程序控制流程返回到主调函数,恢复当初保存起来的主调函数中的局部变量的值。
(这一段不要求掌握)
※变量出现的有效区域称为变量的作用域。
变量占据内存的时间期限为生命期。
※变量的存储类别决定了变量的作用域和生命期,变量的存储类别共有四种:
自动型(auto)、外部型(extern)、静态型(static)和寄存器型(register)。
存储类别小结
存储类别
自动型
外部型
静态型
寄存器型
出现范围
函数内部
任何可出现说明部分的位置
函数内部
函数内部
判别方法
在函数内部(包括main)中缺省存储类别说明的变量
在函数外部缺省存储类别说明的变量
显式出现static
显式出现register
作用域
说明该变量的函数或复合语句
出现说明的位置开始到程序正文结束
说明该变量的函数内
说明该变量的函数内
生命期
说明该变量的函数被调用时
整个程序执行期
整个程序执行期
说明该变量的函数被调用时
注意:
外部变量一定要在函数外定义,出现在函数内且带有extern的是外部变量的说明。
※文件包含形式:
#include"文件名"
或为:
#include<文件名>
双引号或尖括号的区别:
用双引号:
则系统先在引用被包含文件的C源程序所在的文件目录中寻找,若找不到,再按系统指定的标准方式寻找其他目录;
用尖括号:
则仅查找按系统标准方式指定的目录。
文件包含实际上就是在编译时用被包含文件的内容来取代文件包含那一行。
※宏替换又称宏定义,分为不带参数和带参数两种。
不带参数宏定义的一般形式为:
#define<标识符><字符串>
宏替换的作用范围是定义它的源文件。
宏替换的本质是在编译时用<字符串>取代宏名标识符。
※带参数的宏定义的一般形式是
#define<标识符><参数表><字符串>
例如:
#definesquare(x)x*x
若出现square(a+b),则被替换成a+b*a+b,显然,若要求结果为(a+b)*(b+a),可用以下方法:
#definesquare(x)(x)*(x)
一般地,宏定义指令中出现的参数在单词串均用圆括号括起。
※条件编译:
不是对全部源文件进行编译,而是对其中一部分内容只在满足一定条件时才进行编译,即需要对一部分内容指定编译的条件。
条件编译指令有以下三种形式:
(1)#ifdef<标识符>
<程序段1>
[#else
<程序段2>]
#endif
(2)#ifndef<标识符>
<程序段1>
[#else
<程序段2>]
#endif
(3)#if<表达式>
<程序段1>
[#else
<程序段2>]
#endif
※关于数组的主要知识点:
✧数组是同种类型数据元素的集合;
✧数组元素占据一块地址连续的内存空间;
✧数组名代表这块内存空间的首地址;
✧用数组名结合下标的方式访问数组中的元素。
一维数组:
只有一个下标的数组。
犹如所有的数据只排成一行。
二维数组:
有两个下标的数组。
犹如所有的数据排成多行。
n维数组:
有n个下标的数组。
注意:
二维数组可以看成是元素是一维数组的一维数组。
n维数组可以看成是元素是n-1维数组的一维数组。
※一维数组定义的一般形式为:
<类型说明符><数组名>[<常量表达式>]
例如:
inta[10];定义了一个名为a的数组,此数组中有10个整型数据,数组的下标从0到9,数组中的数据元素是:
a[0],a[1],…a[9]。
※一维数组的初始化有多种方法,具体如下:
(1)对数组全部元素初始化,如:
staticinta[10]={0,1,2,3,4,5,6,7,8,9};
(2)对数组部分元素初始化,如:
staticinta[6]={0,1,2,3};相当于:
staticinta[6]={0,1,2,3,0,0};
(3)对数组全部元素显式赋值时可不指定数组长度,如:
inta[]={0,1,2,3,4};
相当于:
inta[5]={0,1,2,3,4};
注意:
只有静态数值型数组元素的初始默认值才是0。
※在C语言中,二维数组的元素是按行存储的,即在内存中先放第一行元素,再放第二行元素……。
※二维数组的初始化有以下四种形式:
1)按行依次对二维数组赋初值
staticinta[2][5]={{1,2,3,4,5},{15,16,14,16,17}};
2)将所有数据写在一个花括号内,按数组排列的顺序对各数组元素赋初值。
staticinta[2][5]={1,2,3,4,5,15,16,14,16,17};
3)可以对部分元素显式赋初值
staticinta[2][3]={{1},{4}};
4)若对全部元素显式赋初值,则数组第一维的元素个数在说明时可以不指定,但第二维的元素个数仍然不能缺省。
inta[][3]={1,2,3,4,5,6};
※字符数组是数组元素类型为字符的数组,字符数组中的每一个元素为字符。
字符数组说明的一般形式是:
char<数组名>[<常量表达式>]
※字符数组初始化:
charch[8]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’};
※对字符串的初始化有两种简写形式,例如
charstr[]="Astring";
charstr[]={"Astring"};
系统会自动在字符串后添加一个串结束符’\0’。
※地址:
内存中存储单元的顺序号,从0起一维连续编号。
这个地址称为物理地址。
存储单元以字节为单位。
出现在程序中的地址是逻辑地址。
逻辑地址要按照某种方式转换成物理地址。
逻辑地址常用4位十六进制数来表示。
※引用变量的地址:
在变量名前加取地址运算符(&),如:
inti;floatf;charc;inta[10];
&i,&f,&c,&a[5],对数组a,数组名a就表示这个数组的首地址(即元素a[0]的地址)而无需写&a。
※对于字符串常量,直接写出字符串,就表示此串常量的地址,而不必加取地址运算符。
指针变量:
其值是地址且其值可变。
指针常量:
其值是地址且其值不可变。
※指针变量的一般形式:
<类型标识符>*<标识符>;
<标识符>:
是指针变量名;
<类型标识符>:
指针所指变量的数据类型;
*:
说明指针变量的标志。
例如:
inti;int*p;floatf;
p=&i;/*正确*/
p=&f;/*则错误*/
※一个指针变量只能指向某一类型的变量,不能再去指向其他型的变量。
※字符’*’出现在定义语句中其含义是指针变量的标志;字符’*’,出现在可执行语句中其含义是按地址取值运算符。
例如:
inti=5,j;int*p;p=&i;j=*p;(此时,j=5)。
*和&的作用相反,两者的作用可以相互抵消。
例如:
*&p=p&*p=p。
※数组名是指针常量,它代表数组的首地址,