《C语言程序设计》基本知识点解答三.docx
《《C语言程序设计》基本知识点解答三.docx》由会员分享,可在线阅读,更多相关《《C语言程序设计》基本知识点解答三.docx(19页珍藏版)》请在冰豆网上搜索。
![《C语言程序设计》基本知识点解答三.docx](https://file1.bdocx.com/fileroot1/2022-11/25/c1d071c6-aa40-48f6-9715-6d471dda07e3/c1d071c6-aa40-48f6-9715-6d471dda07e31.gif)
《C语言程序设计》基本知识点解答三
C语言程序设计基本知识点解答(三)
第五章选择结构程序设计
Q116Ø如何进行选择结构的程序设计?
(选择结构)
A116Ø“选择结构”也可以叫做“分支结构”。
在一个合理的“选择结构”中,总是先进行某个条件的判断,然后根据判断的结果选择执行预先设定的操作。
其流程图如下:
可见,要想实现“选择结构”,需要2个条件:
①能表达条件判断的运算符:
即关系运算符和逻辑运算符
②能实现判断并选择的控制语句:
即if和switch语句
Q117Ø什么是关系运算符?
(关系运算符)
A117Ø关系运算符也叫“比较运算符”,用于对两个数据进行比较判断的。
C语言中一共有6种关系运算符,分别是<小于、<=小于等于、>大于、>=大于等于、==等于、!
=不等于。
用这6种运算符按规定把运算量连接起来构成的式子就是关系表达式。
其中,参与关系运算的数据可以是常量、变量或任何合法的表达式。
比如:
a*a<=100、NowIndex==MaxIndex。
所有6种关系运算符的优先级都比算术运算符低,而==等于、!
=不等于两个运算符的优先级又比其它四个关系运算符低。
所有6种关系运算符的结合性都是从左向右。
Q118ØC语言中如何表示一个关系表达式的值?
(关系表达式)
A118Ø关系表达式进行的是关系运算,也就是“比较运算”。
比较的结果只可能有两个:
“真”或“假”。
对应于实际生活中,就是“成立”还是“不成立”,“正确”还是“不正确”,“对”还是“不对”这样一些比较和判断的结果。
可见,关系运算的结果的特点是:
只有两种可能的结果;任何时候答案只可能是其中的一个;两种可能是相互对立不可能同时出现的。
这样的特点正对应于数学上的“逻辑值”:
“真”或“假”。
所以最终的结论就是:
关系表达式的值是“逻辑值”,即“真”或“假”。
C语言中分别以“1”和“0”来代表。
就是说,如果关系表达式的值为“真”,则得到整数1;如果值为“假”,则得到整数0。
比如关系表达式3>5的值就等于0,而关系表达式5>3的值就等于1。
有了这样的处理,一个关系表达式就可以作为其它表达式的一部分从而构成更复杂的表达式了。
比如:
(3>5)+(3!
=5)、x=(y==z)等等。
Q119Ø当a=3,b=2,c=1时,为什么关系表达式a>b>c的值却是“假”的?
(关系表达式)
A119Ø计算机语言中的表达式并不是数学表达式。
如果是一个数学式子a>b>c,它表示b同时大于c和小于a,的确是对的。
但是在C语言中,这个关系表达式实际上等价于(a>b)>c。
这样计算一下:
(a>b)是“真”,值为1;1>c当然是“假”。
Q120Ø什么是逻辑运算符?
(逻辑运算符)
A120Ø逻辑运算实际上是复合的关系运算,即要判断一个大命题的成立与否,不仅要判断其中的各个小命题是否成立,还取决于每个小命题的成立与否是如何影响大命题的成立的。
C语言有3种逻辑运算符,分别是&&逻辑与(双目)、||逻辑或(双目)、!
逻辑非(单目)。
Q121Ø逻辑运算符的运算规则是什么?
(逻辑运算符)
A121Ø逻辑运算是关系比较运算结果之间进行的运算,所以参与逻辑运算的运算量必须是逻辑量(即值为“真”或“假”的量),而逻辑运算的结果也必然是逻辑值(“真”或“假”,以下分别用“True”或“False”代表)。
●&&逻辑与的运算规则是:
全部运算量都为“T”,逻辑与运算才为“T”;
只要有一个运算量为“F”,逻辑与运算即为“F”
比如想判断x的绝对值是否小于5,那么对应的逻辑表达式是:
x>-5&&x<5。
●||逻辑或的运算规则是:
全部运算量都为“F”,逻辑或运算才为“F”;
只要有一个运算量为“T”,逻辑或运算即为“T”
比如想判断x的绝对值是否大于5,那么对应的逻辑表达式是:
x<-5||x>5。
●!
逻辑非的运算规则是:
运算量为“T”,逻辑非运算则为“F”;
运算量为“F”,逻辑非运算则为“T”
比如关系表达式x>0,实际上和逻辑表达式!
(x<=0)是等价的。
总结一下,逻辑运算的规则就如下表所示:
其中:
a、b代表逻辑量。
T代表“真”值,F代表“假”值。
Q122Ø既然前面说“参与逻辑运算的运算量必须是逻辑量”,那为什么C语言中还有诸如5&&3这样的逻辑表达式?
(逻辑表达式)
A122Ø这是因为在C语言中,除了可以求解到关系表达式本身就是逻辑值的值,还可以求解出任何合法的表达式的“逻辑值”。
这是基于这样的一个规定和处理方式:
当需要求解任何一个表达式的逻辑值是“真”是“假”时,认为该表达式的值为非整数0时是“逻辑真”,而等于整数0时是“逻辑假”。
按照这样的规定,上述逻辑运算规则表在C语言中就可以扩展为下表了:
其中a、b代表任何类型的数据(可以是常量、变量或表达式)。
所以,有5&&3这样的逻辑表达式也就不奇怪了。
按照上表,5和3都是“逻辑真”,则5&&3仍然是“真”,所以这个表达式的值等于1。
Q123Ø=运算符与==运算符有什么区别?
(赋值运算符)(等于运算符)
A123Ø=运算符与==运算符有本质上的区别,千万不要混淆或误用=与==运算符。
●=是“赋值运算符”。
赋值表达式中,赋值运算符的左边只能是变量。
●==是“等于关系运算符”。
关系表达式中,等于运算符的两边可以是常量、变量或任何合法的表达式。
由于上述的本质区别,所以如果误用或混用,则会产生严重的后果。
比如:
(a=1)==(b=2)是一个合法的等于关系表达式,而如果少写一个=号,则变成了
(a=1)=(b=2),这却是一个非法的赋值表达式了,编译的时候就会给出错误信息。
又比如:
假设a=1,则判断a是否和100相等的表达式应该是a==100的关系表达式,它的值也应该是“逻辑假”的,即等于0。
但是如果一旦少写一个=号,则变成了a=100的赋值表达式,这个表达式的值等于100,是“逻辑真”的,显然和正确的结果产生了误差。
更严重的是变量a的值还在求解赋值表达式的过程中被改变了。
更更严重的是,这样的错误不会在编译时容易地发现,它隐藏的很深,非常不容易排除。
Q124Øif语句有哪些语法形式?
(if)
A124Øif语句有两种语法形式:
①只使用单独的if。
其形式为if(表达式)语句;
比如if(x>0)sign=1;
其执行过程如右图所示
②使用成对的if和else。
其形式为
if(表达式)语句1;
else语句2;
比如:
if(x>0)sign=1;
elsesign=-1;
其执行过程如左图所示
其中的“语句”、“语句1”、“语句2”称之为if或else的内嵌语句。
注意:
C语言规定,if或else的内嵌语句只能是一个语句,不能超过一个语句。
Q125Ø什么叫if嵌套语句?
(if)(嵌套)
A125Ø在if或else的内嵌语句中又包含一个或多个if语句时,称为if语句的嵌套。
常用于多重条件,多个分支的选择判断控制。
比如:
if(x!
=0)
if(x>0)y=1;
elsey=-1;
elsey=0;
其执行流程图如图所示:
Q126Øelse能否单独使用构成选择结构?
(else)(嵌套)
A126Ø绝对不能。
else必须和if在一起构成选择结构语句。
也就是说,有一个else就必须有一个if和它配对。
其实道理很简单,没有“如果”哪有“否则”呢?
Q127Ø什么是if嵌套语句中if和else的配对问题?
(if)(嵌套)
A127Ø正如上个问题所言,else是不能单独出现的,而if却可以单独构成一个语句,那么,在if嵌套语句中就存在else和if如何配对的问题。
即是说,当if和else的数目不相等时,到底每个else和哪个if在一起组成一个语句的问题。
在C语言中,if与else的配对原则是:
从if嵌套语句的最里层的else开始向外,依次将else与在它前面的离它最近的还未配对的if配对。
比如:
if(x!
=0)
if(x>0)y=1;
elsey=-1;
elsey=0;
其配对结果是:
①if(x!
=0)
②if(x>0)y=1;
②elsey=-1;
①elsey=0;
而如果是如下语句:
if(x!
=0)
if(x>0)y=1;
elsey=0;
则配对结果是:
①if(x!
=0)
②if(x>0)y=1;
②elsey=0;
如果不注意上述配对原则,那么就很有可能出现这样的情况:
编译系统的理解和程序员的本意发生偏差,使程序运行结果出错。
这样的错误也是很难发现的。
Q128Ø那么,如何避免在if嵌套语句中出现实际的配对和所设计的配对发生误差的情况?
(if)(嵌套)
A128Ø仔细分析一下就会发现,在if嵌套语句中之所以会发生配对误差,根本的原因在于if可能单独出现。
实际效果就是if的数目大于else的数目。
针对问题出现的原因,有以下解决办法:
①只把要嵌套的语句放在else后面,这样由于每个else前面只有一个if,所以不会出错。
比如:
y=0;
if(x>=0)
if(x>0)y=1;
elsey=-1;
容易出错,
而
if(x<0)y=-1;
else
if(x>0)y=1;
elsey=0;
不易出错。
②如果嵌套语句必须放在if后面,就把它用大括号括起来,或给每个if语句都加上else。
比如:
y=0;
if(x>=0)
{
if(x>0)y=1;
}
elsey=-1;
y=0;
if(x>=0)
if(x>0)y=1;
else;
elsey=-1;
都不易出错。
Q129Ø什么是switch语句?
(switch)
A129Øswitch语句是多条件多分支选择语句,类似于if语句的第三种形式,即if嵌套语句。
switch语句中会使用4个C关键字:
switch、case、default和break。
其语法构成如下:
switch(表达式)
{
case常量表达式1:
语句1;break;
case常量表达式2:
语句2;break;
......
case常量表达式n:
语句n;break;
default:
语句n+1;
}
其中,粗体部分是必不可少的。
switch语句的执行流程图如下:
从流程图可见,关键字break的作用是结束它所在的switch语句的执行。
Q130Øswitch语句使用中有何注意事项?
(switch)
A130Øswitch的语法相对比较复杂,使用中需注意以下几点:
(1)switch语句中,switch后的表达式可以是任何类型的表达式,系统求解它的具体值而不是逻辑值。
这一点是和if语句不一样的。
对于if语句,系统求解其后的表达式的逻辑值。
(2)每一个case后面的表达式只能是常量表达式,即能求解出具体值的表达式,而绝不能是变量或表示范围判断的关系表达式或逻辑表达式。
通常其类型是和switch后的表达式相对应的。
同时,每一个常量表达式的值必须互不相同,否则会出现互相矛盾的现象。
下面就是一个正确的switch语句:
chargrade;
switch(grade)
{
case'E':
printf("Excellent\n");break;
case'G':
printf("Good\n");break;
case'B':
printf("Bad\n");break;
default:
printf("Godknows\n");break;
}
而下面这个就是一个错误的switch语句:
intscore;
switch(score)
{
case>89:
grade='E';break;
case>79:
grade='G';break;
case<60:
grade='B';break;
default:
printf("Godknows\n");break;
}
(3)如果switch语句中在每个case和default分支后均加上break语句,则每个case和default分支的出现顺序并不影响程序的流程和执行结果。
比如
switch(grade)
{
case'E':
printf("Excellent\n");break;
case'G':
printf("Good\n");break;
case'B':
printf("Bad\n");break;
default:
printf("Godknows\n");break;
}
和
switch(grade)
{
case'B':
printf("Bad\n");break;
case'G':
printf("Good\n");break;
case'E':
printf("Excellent\n");break;
default:
printf("Godknows\n");break;
}
和
switch(grade)
{
default:
printf("Godknows\n");break;
case'B':
printf("Bad\n");break;
case'G':
printf("Good\n");break;
case'E':
printf("Excellent\n");break;
}
的执行结果是完全相同的。
Q131Ø如何进行选择结构的程序设计?
A131Ø要想正确进行选择结构的程序设计,有三点很重要:
①要深刻理解C语言关于求解表达式的逻辑值的规定;
②要能根据具体问题写出正确的判断表达式。
在大多数情况下,判断表达式都是关系表达式或逻辑表达式;
③要掌握if语句和switch语句的执行流程,从而在已经形成的判断表达式基础上,用它们去正确实现具体问题中的流程。
具体的例子请参考课本中相关的例题。
第六章循环结构程序设计
Q132Ø什么叫循环结构?
(循环结构)
A132Ø循环结构是指重复执行某部分固定的代码。
有两种循环结构:
有限循环和无限循环。
有限循环是指在某个条件满足时重复执行,不满足时结束;而无限循环是指无条件的重复执行或循环结束条件永远不满足的情况。
我们编写程序时应该写有限循环。
通常一个循环结构包含以下四个组成要素,即:
循环初始化、循环变量或循环计数器、循环继续条件(循环终止条件)、循环体(重复执行的代码)。
不管用哪个控制语句实现循环结构,总能找到这四个部分。
Q133ØC语言中如何实现循环结构?
(循环结构)
A133ØC语言中一共有四种方式来实现循环结构,它们分别是:
●if语句+goto语句
●while语句
●do...while语句
●for语句
注意:
后面3种是专门的循环控制语句。
任何一个问题,如果需要循环结构,那么用上述四种方式中的任何一种均可以实现。
只不过对于不同的问题,用不同的方式实现起来效率和代码简洁清晰程度不一样而已。
而其中第一种实现方式实际上就是构成循环结构的本质。
Q134Øgoto语句是什么作用?
(goto)
A134Øgoto语句称为“无条件跳转语句”,即不判断任何条件就实行程序流程的直接跳转。
而if语句不一样,if语句称为“条件跳转语句”,总要根据一个条件的真假来决定流程的转向。
goto语句的用法很简单:
goto语句标号;其作用就是使程序流程直接转到语句标号所指的地方去执行。
比如下面这段代码:
#include
voidmain()
{
intnum,n;
ReInput:
printf("Pleaseinputainteger:
");
scanf("%d",&num);
if(num<0)
{
printf("Dataerror.Pleasereinput.\n");
gotoReInput;
}
……
}
其中的ReInput就是一个语句标号。
语句标号就好比给语句起了一个名字,用来标志一个语句。
它的命名规定和变量名是一样的。
语句标号除了出现在goto语句的后面,还将在程序中某个语句的前面出现,这是它的出现方式是后面带上一个冒号(:
),已示和其它标志符的区别。
由于goto语句恶作用,上述程序的执行流程如下图所示:
有流程图上很容易看出,由于goto语句的无条件跳转,使得处于goto语句和goto语句跳转去的语句标号之间的代码被重复执行了,这就构成了一个循环结构。
Q135Øif语句和goto语句如何构成循环结构?
(if)(goto)(循环结构)
A135Ø实际上这个问题从上面的流程图很容易得到答案。
别忘了,一个程序的整体执行过程总是从上到下依次顺序执行的,而循环是重复执行其中的部分代码。
那么如何才能让这些代码被重复执行呢?
答案就是goto语句。
利用goto语句的无条件跳转,就可以使处于goto语句和goto语句跳转去的语句标号之间的代码被重复执行,这就构成了一个循环结构。
第一步解决了,第二个问题是如果只是单独用goto语句构成循环结构,那么一定是“无限循环结构”,因为goto语句是无条件跳转,到goto就重复,无法结束重复的过程。
这个问题如何解决呢?
答案是if语句。
虽然goto语句不判断条件,但是if语句要判断条件,只要把goto语句作为if的内嵌语句就行了。
因此,if+goto就是循环结构的构成本质。
Q136Ø请举例说明用if语句和goto语句构成循环?
(if)(goto)(循环结构)
A136Ø例如:
编程计算1×2×3×…×n,n=10
●为什么可以用循环?
因为数据有规律的递增且都是乘法运算。
●循环的是什么?
每次产生一个新数据并把它乘到上次的结果中。
●什么时候结束循环?
当新产生的数据大于10的时候就停止上述循环过程。
●怎样实现循环控制?
goto语句可以无条件跳转,用于跳到循环开始的地方;if语句是条件分支语句,用于判断循环结束条件是否满足。
如果满足,则循环结束并输出计算结果;如果不满足,则利用goto语句返回继续循环。
根据以上分析,拟定出以下算法:
S1:
prod=1
S2:
n=1
S3:
prod=prod×n
S4:
n=n+1
S5:
如果n≤10,则返回到S3;否则,结束
按照该算法编写程序如下:
#include
voidmain()
{
longintprod=1;intn=1;
Loop:
if(n<=10)
{
prod=prod*n;n++;gotoLoop;
}
printf("1*2*3*…*%d=%ld\n",n–1,prod);
}
其执行流程图如下:
Q137Ø上面程序中如何确定循环结构的四个要素?
(循环结构)
A137Ø如图所示:
Q138Øwhile语句如何构成循环?
(while)
A138Øwhile语句的用法是:
while(表达式)循环体语句;
此处的循环体语句也称为while语句的内嵌语句,即不是单独存在而是属于while一部分的语句。
前面已经说过,循环结构的本质是if+goto,那么while如何构成循环的呢?
这是因为这个关键字本身所构成语句的执行过程中就已经隐含了if+goto。
下面是while语句的执行流程图:
从流程图中可以清楚地看到,在while语句的执行过程中隐含了用if判断条件,用goto直接跳转的流程。
现在用while语句来实现计算1×2×3×…×n,n=10,代码如下:
#include
voidmain()
{
longintprod=1;intn=1;
while(n<=10)
{
prod=prod*n;n++;
}
printf("1*2*3*…*%d=%ld\n",n–1,prod);
}
其执行流程如图所示,可见与用if和goto语句实现的结果是完全相同的。
Q139Øwhile语句的语法是while(表达式)循环体语句;其中的循环体语句中并没有出现{},为什么在上面程序中while后出现了{}呢?
(while)
while(n<=10){prod=prod*n;n++;}
A139Ø前面已经讲过,while后面的循环体语句也叫做while的内嵌语句,而C语言的编译器规定任何时候内嵌语句都只能是一个语句,即编译器只把while后面的第一个语句当作时while的循环体语句。
而实际程序当中,往往要循环执行的语句不止一个语句,那么如何解决这个问题呢?
答案就是复合语句。
所谓复合语句是指用一对大括弧{}把若干个原本独立分离的语句括起来,成为一个复合语句。
如:
{inta=1;a++;printf("a=%d\n",a);}。
而复合语句在语法上只是一个语句,因此可以放在while后面,既满足了实际问题要重复执行多个语句的需要,又符合内嵌语句只能是一个语句语法要求。
Q140Ø如果不把要重复执行的多个语句形成复合语句,结果会是怎样?
(while)
A140Ø后果是不可预料的。
既有可能是程序运行结果不正确,更严重的可能会是程序陷入无限循环当中。
比如对于下面这个while语句,正确的应该把循环体用大括号括起来
while(n<=10)
{
prod=prod*n;n++;
}
如果不括起来,就变成了如下的语句:
while(n<=10)
prod=prod*n;n++;
原本只有一个while语句,却变成了两个语句,即
while(n<=10)
prod=prod*n;
和
n++;
即是说,只有prod=prod*n;被编译器认为是循环体,这显然和原意不符。
更严重的是,这个while语句是一个无限循环语句,因为循环变量n在循环过程中从不发生变化,所以循环继续条件n<=10会永远为真。
Q141Ø为什么下面这个while语句变成了无限循环语句?
(while)
while(n<=10);
{
prod=prod*n;n++;
}
A141Ø看到(n<=10)后面的分号没有,问题就在这儿。
根据while语句的语法,在while中,while后面是圆括号括起来的一个表达式,在这对括号后面就应该是循环体的语句。
上面出问题的这个while语句中,在括号后面的是一个分号,那么。
这个分号所代表的一个空语句就被编译器认为是循环体语句,而原本的循环体却