3.2 典型例题分析

3.2.1 例题解析

【例3.1】若有定义int a=4, b=5, c=6;,则以下表达式中,值为0的表达式是( )。

A. a&&b

B. a<=b

C. a||b+c&&b-c

D. !((a<b)&&!c||1)

解:选项A中,&&是逻辑与运算符,其两边的值都为非零,逻辑与运算的结果为1;选项B中,判断条件为真,结果也为1;选项C中,&&的优先级高于||,而算术运算符的优先级高于逻辑运算符,所以首先计算b+c和b-c,然后求解11&&-1结果为1,最后求解a||1结果为1;选项D中,根据优先级先求解!c,结果为0。求解(a<b)结果为1,求解1&&0||1结果为1,1逻辑非后结果为0。答案为D。

【例3.2】以下程序的输出结果是( )。

main()
{  int a=2, b=1, c =3;
   if(a<b)
   if(b==1) c=0;
   else c = c+1;
   printf("%d\n", c);
}

A. 0

B. 1

C. 3

D. 4

解:程序中包含一个嵌套的if语句。C语言规定,else总是与它前面最近的不带else的语句相结合。所以本题中第一个if语句的子句是一个if-else语句,由于a<b不成立,因而不执行其内部的子句if-else,接着执行下面的输出语句,所以c的值为3。答案为C。

【例3.3】下列程序的输出结果是( )。

void main()
{  int a= - 1, b=1;
   if (++a<0 &&  !(b --<=0))  p rintf("%d %d\ n", a,b);
   else  printf("%d %d\n", b,a);
}

A. −1 1

B. 0 1 C . 1 0

D. 0 0

解:此题应用了逻辑表达式、自增自减运算规则。if语句中条件表达式的计算过程是:++a值为0,不再继续计算,即表达式值为“假”,直接执行else子句,即b=1,a=0。答案为C。

【例3.4】当a和b的值都大于0小于n时值为真,否则值为假,满足该要求的表达式是( )。

A. !(a<=0) ||!(b<=0) ||!(b>=n) ||!(a>=n)

B. a&&b&&(a<n)&&(b<n)

C. !(a<=0)&&!(b<=0)&&!(b>=n)&&!(a>=n)

D. (a==0)&&(b>0)&&(a<n)&&(b<n)

解:首先需正确理解逻辑与和逻辑非的语义,此表达式应采用逻辑与运算符,所以选项A错误。选项D中(a==0)不符合题意,选项D错误。选项B中a&&b不能完全表达题意,因为若a和b同时小于0,也会使表达式成立,但不符合题意,故选项B错误。答案为C。

【例3.5】若有定义:float w; int a,b;,则合法的switch语句是( )。

解:此题考查switch语句的书写规则以及case后常量表达式的要求。switch后的表达式应该用括号括起,选项A中缺少括号;case后常量表达式的值必须互不相同,选项B出现重复;选项C中switch表达式后多了分号;各个case和default的出现次序,语法上没有限制,所以选项D是正确的。答案为D。

3.2.2 常见错误

1. 将“==”误写成“=”

C语言中,“=”表示赋值,“==”表示关系运算符中的等于。由于疏忽,常常将用比较的地方写成了赋值。例如下面的语句:

if(x=y)
 test( );

原本欲表达比较的含义,但实际表达的是:将y的值赋值给x,并检查结果是否不等于零。

2. 注意条件语句的结构

在if语句中,如果条件为真(或假)时需要执行某任务,而该任务又包含多条语句,此时需使用“{}”把多条语句组合成复合语句。如果漏掉了“{}”,则只有第一条语句被认为是该任务的组成部分。这可能会导致一些语法错误,甚至是难以发现的逻辑错误。例如,下面的程序段:

if(x%2!=0)           /* 下面漏掉了{} */
    sum1+ =x;
    count++;
else
    sum2+= x;

编译程序认为只有语句sum1+=x;是if语句的一部分,这便产生了“illegal else without matching if”的语法错误。当然,正确的程序应该是用“{}”组合成复合语句。

3. switch语句中漏掉break

当使用switch语句时,必须确保switch选择和case标号是同一种数据类型(int、char或者enum类型,不能是float或者是double类型)。如果选择表达式的值不在列出的case标号中,则switch语句不执行任何指令。因此,最好在switch语句中使用default标号,这样确保switch语句在任何情况下都能正确执行。而break语句放置也要十分小心,如果不使用break语句,则会使流程转到下一个case标号处。

例如,根据考试成绩的等级打印出百分制数段:

switch(grade)
{ case  'A' :
      printf("80 ~ 100\n");
  case  'B' :
      printf("60 ~ 79\n");
  case  'C ':
      printf("< 60\n");
  default;
      printf(" error \n");
}

由于漏写了break语句,当grade值为A时,printf函数在执行完第一条语句后会接着执行第二、三、四条printf函数语句。正确的写法是在每个分支后再加“break”。例如:

case 'A' :
      printf("80 ~ 100 \ n");  break;