《C语言程序设计》基本知识点解答(三)

C语言程序设计基本知识点解答(三)

第五章选择结构程序设计

Q116 如何进行选择结构的程序设计?(选择结构)

A116 “选择结构”也可以叫做“分支结构”。在一个合理Array的“选择结构”中,总是先进行某个条件的判断,然后根据

判断的结果选择执行预先设定的操作。其流程图如下:

可见,要想实现“选择结构”,需要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)是等价的。 总结一下,逻辑运算的规则就如下表所示:

T F T F F T T

T F ! a T

F F ! b T T T T F

F a && b

F

T a || b T F F

F

b a

其中:a 、b 代表逻辑量。T 代表“真”值,F 代表“假”值。

Q122 既然前面说“参与逻辑运算的运算量必须是逻辑量”,那为什么C 语言中还有诸如 5 && 3 这样的逻辑表达式?(逻辑表达式)

A122 这是因为在C 语言中,除了可以求解到关系表达式本身就是逻辑值的值,还可以求解出任何合法的表达式的“逻辑值”。这是基于这样的一个规定和处理方式:当需要求解任何一个表达式的逻辑值是“真”是“假”时,认为该表达式的值为非整数0时是“逻辑真”,而等于整数0时是“逻辑假”。按照这样的规定,上述逻辑运算规则表在C 语言中就可以扩展为下表了:

10100非01

10! a 1

00! b 11非0非00

0a && b

1a || b 非000

b a

其中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; else sign=-1; 其执行过程如左图所示

其中的“语句”、“语句1”、“语句2”称之为if 或else 的内嵌语句。注意:C 语言规定,if 或else 的内嵌语句只能是一个语句,不能超过一个语句。

Q125 什么叫if 嵌套语句?(if )(嵌套)

A125 在if 或else 的内嵌语句中又包含一个或多个if 语句时,称为if 语句的嵌套。常用于多重条件,多个分支的选择判断控制。比如: if(x != 0)

if(x > 0) y = 1; else y = -1; else y = 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; else y = -1; else y = 0;

其配对结果是:

①if(x != 0)

②if(x > 0) y = 1;

②else y = -1;

①else y = 0; 而如果是如下语句:

if(x != 0)

if(x > 0) y = 1; else y = 0;

则配对结果是:

①if(x != 0)

②if(x > 0) y = 1;

②else y = 0;

如果不注意上述配对原则,那么就很有可能出现这样的情况:编译系统的理解和程序员的本意发生偏差,使程序运行结果出错。这样的错误也是很难发现的。

Q128 那么,如何避免在if嵌套语句中出现实际的配对和所设计的配对发生误差的情况?(if)(嵌套)

A128 仔细分析一下就会发现,在if嵌套语句中之所以会发生配对误差,根本的原因在于if可能单独出现。实际效果就是if的数目大于else的数目。针对问题出现的原因,有以下解决办法:①只把要嵌套的语句放在else后面,这样由于每个else前面只有一个if,所以不会出错。

比如:

y = 0;

if(x >= 0)

if(x > 0) y = 1; else y = -1;

容易出错,而

if(x < 0) y = -1; else

if(x > 0) y = 1; else y = 0;

不易出错。

②如果嵌套语句必须放在if 后面,就把它用大括号括起来,或给每个if语句都加上else。比如:

y = 0;

if(x >= 0)

{

if(x > 0) y = 1; }

else y = -1; y = 0;

if(x >= 0)

if(x > 0) y = 1; else ;

else y = -1;

都不易出错。

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语句:

char grade;

switch (grade)

{

case 'E': printf("Excellent\n"); break;

case 'G': printf("Good\n"); break;

case 'B':printf("Bad\n"); break;

default : printf("God knows\n");break;

}

而下面这个就是一个错误的switch语句:

int score;

switch (score)

{

case >89 : grade= 'E'; break;

case >79 : grade= 'G'; break;

case <60 : grade= 'B'; break;

default : printf("God knows\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("God knows\n");break;

}

switch (grade)

{

case 'B':printf("Bad\n"); break;

case 'G': printf("Good\n"); break;

case 'E': printf("Excellent\n"); break;

default : printf("God knows\n");break;

}

switch (grade)

{

default : printf("God knows\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

void main()

{

int num, n;

ReInput:

printf("Please input a integer:");

scanf("%d", &num);

if (num<0)

{

printf("Data error. Please reinput.\n");

goto ReInput;

}

……

}

其中的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 void main( ) {

long int prod = 1; int n = 1; Loop:

if (n <= 10)

goto

{

prod = prod * n; n ++; goto Loop; }

printf("1*2*3*…*%d = %ld \n", n –1, prod); }

其执行流程图如下:

Q137 上面程序中如何确定循环结构的四个要素?(循环结构) A137 如图所示:

循环变量#include void main( ){long int prod = 1; int n = 1;

Loop:

if (n <= 10) {

prod = prod * n; n ++; goto Loop;}

printf("1*2*3*…*%d = %ld\n", n –1, prod);}

n 初值=1 终值=10

循环继续条件

循环初始化

循环体

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 Array void main( )

{

long int prod = 1; int n = 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的循环体语句。而实际程序当中,往往要循环执行的语句不止一个语句,那么如何解决这个问题呢?答案就是复合语句。所谓复合语句是指用一对大括弧{ }把若干个原本独立分离的语句括起来,成为一个复合语句。如:{ int a=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语句中,在括号后面的是一个分号,那么。这个分号所代表的一个空语句就被编译器认为是循环体语句,而原本的循环体却变成了while执行结束后才能执行的语句。不幸的是,这个while 语句永远都不会结束,因为n <= 10永远都是真的。所以一定要注意,在while语句中,在圆括号后面是不应该有分号的。

Q142 for语句如何构成循环?(for)

A142 for语句的用法是:for(表达式1; 表达式2; 表达式3) 循环体语句;

此处的循环体语句也称为for语句的内嵌语句,即不是单独存在而是属于for一部分的语句。

同while语句一样,尽管for语句中没有if和goto,但是这个关键字本身所构成语句的执行过程中就已经隐含了if + goto。下面是for语句的执行流程图:

从流程图上可以看出,表达式1只在开始循环之前被求解了一次,因此表达Array式1通常都用于进行循环的初始化;表达式2 用于描述循环继续条件;表达

式3 用于循环变量的增减,从而使循环继续条件越来越不满足。

现在用for语句来实现计算1×2×3×…×n ,n=10,代码如下:

#include

void main( )

{

long int prod = 1; int n;

for (n = 1; n <= 10; n ++)

{

prod = prod * n;

}

printf("1*2*3*…*%d = %ld\n", n–1, prod);

其执行结果与用if 和goto 语句实现的结果是完全相同的。

Q143 什么是循环嵌套?(循环嵌套)

A143 循环嵌套是指在一个循环语句的循环体内又出现另一个循环控制语句。对于循环嵌套的层数不同的系统规定不同。一般来说,实际中最多就用到4层嵌套,而最常用的是双重循环。

比如编程求∑n! = 1! + 2! + 3! + ... + n! 就要用到双重循环。因为题目既要进行累乘(n!)又要进行累加(∑),具体实现代码和相关解释如下图:

外层循环变量把每次由

内层循环用于求外#include void main( ){

int n = 10 , i , j ; long int sum = 0 , prod = 1 ;for ( i = 1 ; i <= n ; i ++ ){

prod = 1 ;

for ( j = 1 ; j <= i ; j ++ )prod = prod * j ;sum = sum + prod ;}

printf(“1!+2!+3!+…+%d! = %ld\n ”, n, sum);}

内层循环计算出的阶乘值累加到变量sum 中。层循环变量i 当前值的阶乘。

Q144 break 语句用在循环控制语句中是什么作用?(break )

A144 在C 语言中,break 语句除了可以用在switch 语句中用于终止switch 语句的执行外,还可以用在while 、do...while 、for 语句的循环体当中。break 语句用在循环体中的作用是结束整个循环语句的执行,也就是说,在执行循环过程中,一旦遇到break 语句,这个循环语句就结束了继续执行该循环语句后面的语句。

比如用while 语句和break 来编程计算1×2×3×…×n ,代码如下: #include void main( ) {

long int prod = 1; int n = 1;

while (1)

{

prod = prod * n; n ++;

if (n > 10) break;

}

printf("1*2*3*…*%d = %ld \n", n –1, prod); }

程序执行流程如图:

Q145 continue 语句用在循环控制语句中是什么作用?(continue )

A145 在C 语言中,continue 语句只能用在while 、do...while 、for 语句的循环体当中。continue 语句用在循环体中的作用是结束本次循环体的执行,也就是说,在执行循环过程中,一旦遇到continue 语句,就跳过循环体中位于continue 后面的语句,接着进行下一次是否继续循环的判断。

Q146 break 语句和continue 语句有什么区别?(break )(continue ) A146 如下:

break continue

语句:

结束整个循环语句

语句:结束本次循环的执行

相关主题
相关文档
最新文档