一、选择结构和条件判断
C语言有两种选择语句:
if语句,用来实现两个分支的选择结构
switch语句,用来实现多分支的选择结构
二、用if语句实现选择结构
1、用if语句处理选择结构举例
①输入两个实数,按由小到大的顺序输出这两个数。
解题思路: 只要做一次比较,然后进行一次交换即可。用if语句实现条件判断。
#include <stdio.h>
int main()
{
float a,b,t;
scanf("%f,%f",&a,&b);
if(a>b)
{ //将a和b的值互换
t=a;
a=b;
b=t;
}
printf("%5.2f,%5.2f\n",a,b);
return 0;
}
运行结果:
②输入3个数a,b,c,要求按由小到大的顺序输出。
算法步骤:
S1: if a>b,将a和b对换 (交换后,a是a、b中的小者)
S2: if a>c,将a和c对换 (交换后,a是a、c中的小者,因此a是三者中最小者)
S3: if b>c,将b和c对换 (交换后,b是b、c中的小者,也是三者中次小者)
S4: 顺序输出a,b,c
#include <stdio.h>
int main()
{
float a,b,c,t;
scanf("%f,%f,%f",&a,&b,&c);
if(a>b)
{ t=a; //借助变量t,实现变量a和变量b互换值
a=b;
b=t;
} //互换后,a小于或等于b
if(a>c)
{ t=a; //借助变量t,实现变量a和变量c互换值
a=c;
c=t;
} //互换后,a小于或等于c
if(b>c) //还要
{ t=b; //借助变量t,实现变量b和变量c互换值
b=c;
c=t;
} //互换后,b小于或等于c
printf("%5.2f,%5.2f,%5.2f\n",a,b,c); //顺序输出a,b,c的值
return 0;
}
运行结果:
2、if语句的一般形式
表达式”可以是关系表达式、逻辑表达式,甚至是数值表达式
方括号内的部分(即else子句)为可选的,既可以有,也可以没有
语句1和语句2可以是一个简单的语句,也可以是一个复合语句,还可以是另一个if语句
三、关系运算符和关系表达式
在C语言中,比较符(或称比较运算符)称为关系运算符。所谓“关系运算”就是“比较运算”,将两个数值进行比较,判断其比较的结果是否符合给定的条件。
1、关系运算符及其优先次序
~前4种关系运算符的优先级别相同,后2种也相同。前4种高于后2种。
~关系运算符的优先级低于算术运算符。
~关系运算符的优先级高于赋值运算符。
c>a+b 等效于c>(a+b)(关系运算符的优先级低于算术运算符)
a>b==c 等效于(a>b)c(大于运算符>的优先级高于相等运算符)
ab<c 等效于a(b<c)(小于运算符<的优先级高于相等运算符==)
a=b>c 等效于a=(b>c)(关系运算符的优先级高于赋值运算符)
2、关系表达式
用关系运算符将两个数值或数值表达式连接起来的式子,称为关系表达式。
关系表达式的值是一个逻辑值,即“真”或“假”。
在C的逻辑运算中,以“1”代表“真”,以“0”代表“假”。
若a=3,b=2,c=1,则:
d=a>b,由于a>b为真,因此关系表达式a>b的值为1,所以赋值后d的值为1。
f=a>b>c,则f的值为0。因为“>”运算符是自左至右的结合方向,先执行“a>b”得值为1, 再执行关系运算“1>c”,得值0,赋给f,所以f的值为0
四、逻辑运算符和逻辑表达式
1、逻辑运算符及其优先次序
运算符
含义
举例
说明
!
逻辑非(NOT)
!a
如果a为假,则!a为真;如果a为真,则!a为假
&&
逻辑与(AND)
a && b
如果a和b都为真,则结果为真,否则为假
||
逻辑或(OR)
a || b
如果a和b有一个以上为真,则结果为真,二者都为假时,结果为假
“&&”和“‖”是双目运算符,要求有两个运算对象(操作数);
“!”是单目运算符,只要有一个运算对象,优先次序:!(非)→&&(与)→‖(或), 即“!”为三者中最高的;
逻辑运算符中的“&&”和“‖”低于关系运算符“!”,高于算术运算符,逻辑运算结果不是0就是1,不可能是其他数值。而在逻辑表达式中作为参加逻辑运算的运算对象可以是0(“假”)或任何非0的数值(按“真”对待)
2、逻辑表达式
逻辑表达式:由逻辑运算符连接其他表达式构成表达式,它在程序中常用于表示复杂条件。
在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。
例:将数学关系式 20<x≤100用逻辑表达式表示,并计算当x=50时该逻辑表达式的值。
既然关系表达式和逻辑表达式的值是0和1,而且在判断一个量是否为“真”时,以0代表“假”,以非0代表“真”。那么就可以理解为什么在if语句中表达式可以是任何数值表达式。
例:判别用year表示的某一年是否闰年,可以用一个逻辑表达式来表示。闰年的条件是符合下面二者之一: ①能被4整除,但不能被100整除,如2008。②能被400整除,如2000。解:(year % 4 == 0 && year % 100 != 0) ‖ year % 400 == 0
五、条件运算符和条件表达式
条件表达式的一般格式:
表达式1 ? 表达式2 : 表达式3
条件运算符由两个符号(?和:)组成,必须一起使用。要求有3个操作对象,称为三目(元)运算符,它是C语言中唯一的一个三目运算符。
条件运算符的执行顺序: 先求解表达式1,若为非0(真)则求解表达式2,此时表达式2的值就作为整个条件表达式的值。若表达式1的值为0(假),则求解表达式3,表达式3的值就是整个条件表达式的值。
例:输入一个字符,判别它是否为大写字母,如果是,将它转换成小写字母;如果不是,不转换。然后输出最后得到的字符。
解题思路: 用条件表达式来处理,当字母是大写时,转换成小写字母,否则不转换。
#include <stdio.h>
int main()
{
char ch;
scanf("%c",&ch);
ch=(ch>='A'&&ch<='Z')?(ch+32):ch;
printf("%c\n",ch);
return 0;
}
运行结果:
程序分析:条件表达式“(ch>=‘A’&&ch<=‘Z’)?(ch+32):ch”的作用是: 如果字符变量ch的值为大写字母,则条件表达式的值为(ch+32),即相应的小写字母,32是小写字母和大写字母ASCII的差值。如果ch的值不是大写字母,则条件表达式的值为ch,即不进行转换。
六、选择结构的嵌套
注意:if与else的配对关系——else总是与它上面的最近的未配对的if配对。
如果if与else的数目不一样,为实现程序设计者的思想,可以加花括号来确定配对关系。
例:输入一个学生两门课的成绩,若平均成绩小于0,则显示“数据错误!”;否则,若平均成绩不低于90,则显示“优等生”,否则显示“加油!”。
算法设计:根据平均成绩的计算结果,将有两个大的分支:分支一:平均成绩小于0,显示“数据错误!”;分支二:平均成绩不小于0,进一步进行小分支处理。
#include<stdio.h>
int main()
{
int a1,a2,ave;
printf("输入两门课的成绩:");
scanf("%d,%d",&a1,&a2);
ave=(a1+a2)/2;
if(ave<0)
printf("数据错误!\n");
else
if(ave>=90)
printf("优等生!\n");
else
printf("要加油啊!\n");
return 0;
}
运行结果:
七、用switch语句实现多分支选择结构
switch语句的一般形式:
说明:
(1) 括号内的“表达式”,其值的类型应为整数类型(包括字符型)。
(2) 花括号内是一个复合语句,内包含多个以关键字case开头的语句行和最多一个以default开头的行。case后面跟一个常量(或常量表达式),它们和default都是起标号作用,用来标志一个位置。执行switch语句时,先计算switch后面的“表达式”的值,然后将它与各case标号比较,如果与某一个case标号中的常量相同,流程就转到此case标号后面的语句。如果没有与switch表达式相匹配的case常量,流程转去执行default标号后面的语句。
(3) 可以没有default标号,此时如果没有与switch表达式相匹配的case常量,则不执行任何语句。
(4) 各个case标号出现次序不影响执行结果。
(5) 每一个case常量必须互不相同;否则就会出现互相矛盾的现象。
(6) case标号只起标记的作用。在执行switch语句时,根据switch表达式的值找到匹配的入口标号,在执行完一个case标号后面的语句后,就从此标号开始执行下去,不再进行判断。因此,一般情况下,在执行一个case子句后,应当用break语句使流程跳出switch结构。最后一个case子句(今为default子句)中可不加break语句。
(7) 在case子句中虽然包含了一个以上执行语句,但可以不必用花括号括起来,会自动顺序执行本case标号后面所有的语句。当然加上花括号也可以。
(8) 多个case标号可以共用一组执行语句。
例:
①要求按照考试成绩的等级输出百分制分数段,A等为85分以上,B等为70~84分,C等为60~69分,D等为 60分以下。成绩的等级由键盘输入。
#include <stdio.h>
int main()
{
char grade;
scanf("%c",&grade);
printf("Your score:");
switch(grade)
{
case 'A': printf("85~100\n");break;
case 'B': printf("70~84\n");break;
case 'C': printf("60~69\n");break;
case 'D': printf("<60\n");break;
default: printf("enter data error!\n");
}
return 0;
}
运行结果:
②用switch语句处理菜单命令。在许多应用程序中,用菜单对流程进行控制,例如从键盘输入一个′A′或′a′字符,就会执行A操作,输入一个′B′或′b′字符,就会执行B操作。
#include <stdio.h>
void action1(int x,int y) //执行加法的函数
{
printf("x+y=%d\n",x+y);
}
void action2(int x,int y) //执行乘法的函数
{
printf("x*y=%d\n",x*y);
}
int main()
{
char ch;
int a=15,b=23;
ch=getchar();
switch(ch)
{
case 'a':
case 'A': action1(a,b);break; //调用action1函数,执行A操作
case 'b':
case 'B': action2(a,b);break; //调用action2函数,执行B操作
default: putchar('\a');
}
return 0;
}
运行结果:
八、选择结构程序综合举例
1、写一程序,判断某一年是否为闰年。
程序1:
#include <stdio.h>
int main()
{
int year,leap;
scanf("%d",&year);
if (year%4==0)
{
if(year%100==0)
{
if(year%400==0)
leap=1;
else
leap=0;
}
else
leap=1;
}
else
leap=0;
if (leap)
printf("%d is ",year);
else
printf("%d is not ",year);
printf("a leap year.\n");
return 0;
}
程序2:可将程序1中7~20行代码改写成以下更加简洁的语句
if(year%4!=0)
leap=0;
else if (year%100!=0)
leap=1;
else if(year%400!=0)
leap=0;
else
leap=1;
程序3:可以用一个逻辑表达式包含所有的闰年条件,将上述if语句用下面的if语句代替
if((year%4==0 && year%100!=0) || (year%400==0))
leap=1;
else
leap=0;
程序4:可以在程序中使用C 99 提供的逻辑变量和逻辑常量true和false,把leap定义为逻辑变量,它的值只能是true(即1)或false(即0)。[注意头部要加上#include <stdbool.h>]【注意有些编译系统不允许使用逻辑型变量bool】
有些C编译系统(包括VC++ 6.0)还未完全实现C 99标准,可将1、2行改为#include作为C++程序来运行
#include <stdio.h>
#include <stdbool.h>
int main()
{
int year;
bool leap;
scanf("%d",&year);
if (year%4==0)
{
if(year%100==0)
{
if(year%400==0)
leap=true;
else
leap=false;
}
else
leap=true;
}
else
leap=false;
if (leap == true)
printf("%d is ",year);
else
printf("%d is not ",year);
printf("a leap year.\n");
return 0;
}
运行结果:
2、求ax²+bx+c=0方程的解。
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c,disc,x1,x2,realpart,imagpart;
scanf("%lf,%lf,%lf",&a,&b,&c);
printf("The equation ");
if(fabs(a)<=1e-6) //a的绝对值是否小于一个很小的数(例如10^-6),若小于,就认为其为0
printf("is not a quadratic\n");
else
{
disc=b*b-4*a*c;
if(fabs(disc)<=1e-6) // 相当于disc=0
printf("has two equal roots:%8.4f\n",-b/(2*a));
else
if(disc>1e-6) // 相当于disc>0
{
x1=(-b+sqrt(disc))/(2*a);
x2=(-b-sqrt(disc))/(2*a);
printf("has distinct real roots:%8.4f and %8.4f\n",x1,x2);
}
else
{
realpart=-b/(2*a);
imagpart=sqrt(-disc)/(2*a);
printf(" has complex roots:\n");
printf("%8.4f+%8.4fi\n",realpart,imagpart);
printf("%8.4f-%8.4fi\n",realpart,imagpart);
}
}
return 0;
}
运行结果:
3、运输公司对用户计算运输费用。路程(s km)越远,每吨·千米运费越低。标准如下:
#include <stdio.h>
int main()
{
int c,s;
float p,w,d,f;
printf("please enter price,weight,discount:"); // 提示输入的数据
scanf("%f,%f,%d",&p,&w,&s); // 输入单价、重量、距离
if(s>=3000)
c=12; // 3000km以上为同一折扣
else
c=s/250; // 3000km以下各段折扣不同,c的值不相同
switch(c)
{
case 0: d=0; break; // c=0,代表250km以下,折扣d=0
case 1: d=2; break; // c=1,代表250到500km以下,折扣d=2%
case 2:
case 3: d=5; break; // c=2和3,代表500到1000km以下,折扣d=5%
case 4:
case 5:
case 6:
case 7: d=8; break; // c=4-7,代表1000到2000km以下,折扣d=8%
case 8:
case 9:
case 10:
case 11: d=10; break; // c=8-11,代表2000KM到3000km以下,折扣d=10%
case 12: d=15; break; // c12,代表3000km以上,折扣d=15%
}
f = p * w * s * (1 - d / 100); // 计算总运费
printf("freight=%10.2f\n",f); // 输出总运费,取两位小数
return 0;
}
运行结果: