描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302455899丛书名: 21世纪高等学校计算机基础实用规划教材
编辑推荐
本书集C语言的理论知识、例题、编程练习、综合设计于一体。本书配有PPT课件、例题和编程习题的程序源代码。
内容简介
本书是C语言程序设计基础教材,集理论知识、实验指导、综合设计、习题解答于一体。内容组织注重基础,突出应用,兼顾提高。书中实例以“学生数据管理”系列例题为主体,贯穿教学主要内容,前后衔接,逐步扩展,运用比较教学法讲解,易教易学。
全书共有10章,分别是程序设计概述、简单程序设计、选择结构程序设计、循环结构程序设计、数组程序设计、函数程序设计、指针程序设计、结构体程序设计、文件程序设计以及综合程序设计等,前9章在每章之后均附有实验指导,并在书后附有简明的习题解答。
本书适合作为高等院校C语言程序设计课程的教材,也可用作程序设计从业人员及程序设计爱好者的自学参考书。
全书共有10章,分别是程序设计概述、简单程序设计、选择结构程序设计、循环结构程序设计、数组程序设计、函数程序设计、指针程序设计、结构体程序设计、文件程序设计以及综合程序设计等,前9章在每章之后均附有实验指导,并在书后附有简明的习题解答。
本书适合作为高等院校C语言程序设计课程的教材,也可用作程序设计从业人员及程序设计爱好者的自学参考书。
目 录
第1章 程序设计概述 11.1 程序设计语言 11.2 算法 2 1.2.1 算法概念与算法描述 2 1.2.2 算法的逻辑结构 4 1.2.3 算法的特性 5 1.2.4 算法评价 61.3 程序设计与实现 6 1.3.1 程序设计的基本过程 7 1.3.2 编辑运行C语言程序 71.4 C语言程序的基本结构 11 1.4.1 程序的函数化结构 11 1.4.2 标识符与保留字 13 1.4.3 程序风格 14小结 14习题1 15实验1 编辑运行C语言程序 17第2章 简单程序设计 192.1 数据类型、常量与变量 19 2.1.1 数据类型 19 2.1.2 常量 19 2.1.3 变量 212.2 数据输入输出 23 2.2.1 用printf()函数输出数据 23 2.2.2 用scanf()函数输入数据 27 2.2.3 输入输出字符型数据 292.3 简单运算与常用宏命令 32 2.3.1 算术运算 32 2.3.2 赋值运算 33 2.3.3 变量自增、自减运算 34 2.3.4 逗号运算 34 2.3.5 宏命令include和define 352.4 简单程序设计举例 382.5 表达式中数据类型的转换 41*2.6 定义数据类型别名 42小结 43习题2 44实验2 简单程序设计 47第3章 选择结构程序设计 493.1 if选择结构 49 3.1.1 if选择结构程序示例 49 3.1.2 关系表达式 50 3.1.3 逻辑表达式 51 3.1.4 if命令 52 3.1.5 条件运算 603.2 switch选择结构 613.3 选择结构程序举例 63小结 68习题3 68实验3 选择结构程序设计 72第4章 循环结构程序设计 774.1 循环结构控制命令 77 4.1.1 while命令 77 4.1.2 do-while命令 79 4.1.3 for命令 804.2 循环体中的控制命令 83 4.2.1 break命令 83 4.2.2 continue命令 854.3 循环嵌套 864.4 goto命令 884.5 循环结构程序举例 89小结 100习题4 101实验4 循环结构程序设计 106第5章 数组程序设计 1095.1 一维数组程序设计 109 5.1.1 一维数组程序示例 109 5.1.2 一维数组的定义及元素引用 110 5.1.3 数值型一维数组的输入和输出 111 5.1.4 数值型一维数组的初始化 113 5.1.5 字符型一维数组的初始化 115 5.1.6 一维数组的存储 1165.2 字符串操作 116 5.2.1 字符串的输入输出 116 5.2.2 多字符串操作函数 1195.3 二维数组程序设计 122 5.3.1 二维数组的定义及元素引用 122 5.3.2 二维数组的输入和输出 123 5.3.3 二维数组的初始化 124 5.3.4 二维数组的存储 1265.4 数组应用程序举例 127小结 138习题5 138实验5 数组程序设计 143第6章 函数程序设计 1466.1 函数概述 1466.2 用户函数示例 1476.3 函数定义及调用 148 6.3.1 函数定义 148 6.3.2 函数值和return命令 149 6.3.3 函数调用 1516.4 函数嵌套和递归函数 155 6.4.1 函数嵌套 155 6.4.2 递归函数 1576.5 数组与函数 161 6.5.1 数组元素作函数参数 161 6.5.2 一维数组名作函数参数 162 6.5.3 二维数组与函数 1666.6 函数应用程序举例 1686.7 变量的作用域和存储类型 174 6.7.1 变量的作用域 174 6.7.2 变量的存储类型 176*6.8 编译连接多个源文件的C程序 178小结 180习题6 181实验6 函数程序设计 185第7章 指针程序设计 1887.1 指针概述 1887.2 指针变量的定义和使用 189 7.2.1 指针变量程序示例 189 7.2.2 定义指针变量 190 7.2.3 使用指针变量 1907.3 指针与数组 193 7.3.1 指针与一维数组 193 7.3.2 指针与二维数组 196 7.3.3 指针与字符串 199 7.3.4 指针数组 2007.4 指针作函数参数 202 7.4.1 简单变量指针作函数参数 202 7.4.2 指向数组的指针作函数参数 204 7.4.3 字符串指针作函数参数 205 7.4.4 指针数组作函数参数 207*7.4.5 使用带参数的main()函数 2097.5 指针函数 2107.6 指针应用程序举例 211小结 214习题7 214实验7 指针程序设计 221第8章 结构体程序设计 2248.1 结构体数据概述 2248.2 结构体类型和结构体变量 224 8.2.1 结构体程序示例 225 8.2.2 定义结构体数据类型 225 8.2.3 结构体变量的定义及使用 2278.3 结构体数组 230 8.3.1 结构体数组的定义及元素引用 231 8.3.2 结构体数组的初始化 231 8.3.3 结构体数组应用实例 2328.4 结构体指针变量 233 8.4.1 结构体指针变量的定义及使用 233 8.4.2 结构体指针作函数的参数 2358.5 使用链表存储数据 236 8.5.1 使用链表存储数据示例 236 8.5.2 链表的特点 237 8.5.3 动态内存管理函数 238 8.5.4 定义链表结构 2398.6 链表的基本操作 240 8.6.1 链表结点的插入 240 8.6.2 链表结点的删除 244 8.6.3 链表结点的查找 2458.7 结构体应用程序举例 249小结 255习题8 255实验8 结构体程序设计 261第9章 文件程序设计 2669.1 文件概述 266 9.1.1 文件的概念 266 9.1.2 文件的分类 267 9.1.3 文件的一般操作过程 267 9.1.4 文件类型指针 2689.2 文件的基本操作 268 9.2.1 打开和关闭文件 269 9.2.2 文件的字符读写 270 9.2.3 文件结束状态测试 272 9.2.4 文件的数据块读写 2739.3 文件的其他操作 277 9.3.1 文件位置指针定位 277 9.3.2 文件的格式化读写 280 9.3.3 文件的字符串读写 2819.4 文件应用程序举例 282小结 285习题9 285实验9 文件程序设计 289第10章 综合程序设计 29210.1 软件开发流程 29210.2 通讯录程序设计 293 10.2.1 通讯录程序需求分析 293 10.2.2 通讯录程序功能设计 294 10.2.3 通讯录程序数据设计 295 10.2.4 通讯录程序函数设计 296 10.2.5 函数编码及测试 297附录A C语言经典保留字 319附录B 常用C语言库函数 320附录C 常用ASCII码字符对照表 323附录D C语言的运算符 324附录E 习题(选择题)参考答案 326附录F 习题(编程题)参考程序 327参考文献 349??
??
??
??
C语言程序设计——理论、方法与实践(第2版)
目 录
前 言
序言
本书保持了第1版的应用性、实用性特色,并进行了以下改进。 ,增加综合程序设计,强化应用能力培养。增加了“第10章 综合程序设计”一章,该章以通讯录程序设计为实例,体现软件工程思想,针对C语言结构化程序设计的特点,详细介绍了C语言应用程序的设计方法与过程。 第二,充实习题解答,提供学习参考。增加了习题编程题目的简明解答,凡是适合以代码段形式参考的,均提供代码段,使题解起到提示、参考作用。个别习题提供完整代码。 第三,更新例题,优化程序代码。剔除或更新了不易讲解、不够经典的例题,充实了系列例题,更易于讲解;加强了例题的基础性与提高性的结合,适合不同层次、不同兴趣的学生学习;对原有部分例题的程序代码进行了优化,更简明易读。 第四,更新习题,利于课后练习。尤其对习题编程题目进行了较大幅度的更新,平均更新率达到20%,数组程序设计一章更新率达到了60%。经过更新之后,题目的新颖性、趣味性增强,题目吸引力提高,有利于布置课后作业和编程练习。 第五,讲练统一,有机结合。加强了实验内容与教学实例的衔接,结合例题做实验,使理论教学与实验教学有机统一,讲练一体化,有利于提高学习效率。 本书是C语言程序设计基础教材,集理论知识、实验指导、综合设计、习题解答于一体。内容组织注重基础,突出应用,兼顾提高。书中实例以“学生数据管理”系列例题为主体,贯穿教学主要内容,前后衔接,逐步扩展,运用比较教学法讲解,易教易学。 全书共有10章,分别是程序设计概述、简单程序设计、选择结构程序设计、循环结构程序设计、数组程序设计、函数程序设计、指针程序设计、结构体程序设计、文件程序设计以及综合程序设计等,前9章在每章之后均附有实验指导,并在书后附有简明习题解答。 本书配有PPT课件、例题及习题程序源代码,可以从清华大学出版社网站www.tup.com.cn下载 冯伟昌、黄忠义、王宗江、张元国、刘海慧、张莹、李竹健、王桂东、魏建国、王金才、张文、高永存、王涛、薛莹、徐英娟、马明祥、滕秀荣、彭玉忠、潘振昌、徐思杰等参与了本书的编写并做了大量素材整理、程序调试、文稿审校等工作,在此表示感谢! 清华大学出版社付弘宇编辑和她的同事们为本书的编辑、出版做了大量严谨细致的工作,在此一并致谢! 作者联系邮箱:[email protected]。
本书保持了第1版的应用性、实用性特色,并进行了以下改进。 ,增加综合程序设计,强化应用能力培养。增加了“第10章 综合程序设计”一章,该章以通讯录程序设计为实例,体现软件工程思想,针对C语言结构化程序设计的特点,详细介绍了C语言应用程序的设计方法与过程。 第二,充实习题解答,提供学习参考。增加了习题编程题目的简明解答,凡是适合以代码段形式参考的,均提供代码段,使题解起到提示、参考作用。个别习题提供完整代码。 第三,更新例题,优化程序代码。剔除或更新了不易讲解、不够经典的例题,充实了系列例题,更易于讲解;加强了例题的基础性与提高性的结合,适合不同层次、不同兴趣的学生学习;对原有部分例题的程序代码进行了优化,更简明易读。 第四,更新习题,利于课后练习。尤其对习题编程题目进行了较大幅度的更新,平均更新率达到20%,数组程序设计一章更新率达到了60%。经过更新之后,题目的新颖性、趣味性增强,题目吸引力提高,有利于布置课后作业和编程练习。 第五,讲练统一,有机结合。加强了实验内容与教学实例的衔接,结合例题做实验,使理论教学与实验教学有机统一,讲练一体化,有利于提高学习效率。 本书是C语言程序设计基础教材,集理论知识、实验指导、综合设计、习题解答于一体。内容组织注重基础,突出应用,兼顾提高。书中实例以“学生数据管理”系列例题为主体,贯穿教学主要内容,前后衔接,逐步扩展,运用比较教学法讲解,易教易学。 全书共有10章,分别是程序设计概述、简单程序设计、选择结构程序设计、循环结构程序设计、数组程序设计、函数程序设计、指针程序设计、结构体程序设计、文件程序设计以及综合程序设计等,前9章在每章之后均附有实验指导,并在书后附有简明习题解答。 本书配有PPT课件、例题及习题程序源代码,可以从清华大学出版社网站www.tup.com.cn下载 冯伟昌、黄忠义、王宗江、张元国、刘海慧、张莹、李竹健、王桂东、魏建国、王金才、张文、高永存、王涛、薛莹、徐英娟、马明祥、滕秀荣、彭玉忠、潘振昌、徐思杰等参与了本书的编写并做了大量素材整理、程序调试、文稿审校等工作,在此表示感谢! 清华大学出版社付弘宇编辑和她的同事们为本书的编辑、出版做了大量严谨细致的工作,在此一并致谢! 作者联系邮箱:[email protected]。
编 者
2016年11月
媒体评论
评论
在线试读
选择结构程序设计
选择结构是程序的三种逻辑结构之一,在C语言程序中,使用if命令和switch命令实现选择结构。本章系统介绍选择结构程序设计知识,主要内容包括:用于表示条件的关系表达式和逻辑表达式、if命令和switch命令的结构及执行过程、选择结构程序设计的基本方法等。 任何选择处理都是有条件的,合理、正确地表达和使用选择条件,是选择结构程序设计的重要内容。3.1 if选择结构 在第1章关于选择结构算法的知识中,讨论了判定“优等生”问题的选择结构算法(算法流程图见图1-5),其中分支选择的条件是ave≥90(ave表示平均成绩),该条件成立时,显示“优等生”,否则显示“加油!”。本节从此算法的实现程序开始,逐步介绍if选择结构的相关知识。3.1.1 if选择结构程序示例 【例3-1】 输入一个学生两门课程的成绩,若平均成绩不低于90,则显示“优等生”,否则显示“加油!”。程序如下: #include int main() { int s1,s2,ave; /* s1、s2为课程成绩,ave为平均成绩 */ printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩s1、s2 */ ave=(s1 s2)/2; /* 计算平均成绩ave */ if(ave>=90) /* 分支控制 */ printf(“优等生!n”); /* ave不低于90时,执行该语句 */ else printf(“加油!n”); /* ave不足90时,执行该语句 */ return 0; } 程序解析: 该程序中的if-else命令用于实现选择控制,选择条件是ave>=90。当ave>=90成立时,执行语句“printf(“优等生!n”);”,输出字符串“优等生!”;否则,执行语句“printf(“加油!n”);”,输出字符串“加油!”。本例中决定分支的条件ave>=90称为关系表达式。 以下是程序的执行实例,希望读者根据具体数据,分析程序的选择控制过程。 程序次执行结果: 输入两门课的成绩:88,96 (此时, 表达式ave>=90成立) 优等生! 程序第二次执行结果: 输入两门课的成绩:77,85(此时, 表达式ave>=90不成立) 加油!3.1.2 关系表达式 关系表达式是由关系运算符连接运算对象而构成的表达式。在选择结构中,进行分支选择的条件常使用关系表达式。例如,在上述示例程序中使用ave>=90作为选择控制条件,其中的>=符号称为关系运算符。 1.关系运算符 C语言有6种关系运算,分别表示两个对象进行大小比较的6种情况,即大于、大于等于、小于、小于等于、等于、不等于,其运算符及含义如表3-1所示。表3-1 关系运算符及其含义关系运算符含义实例 >大于ave>90 >=大于等于ave>=90 =90成立,则其值为1;第二次执行程序时,变量ave的值为81,关系表达式ave>=90不成立,则其值为0。 3.关系运算的优先级 (1)关系运算>、>=、b与(a<5)>b等价,若a=?2、b=2,则其值为0。3.1.3 逻辑表达式 逻辑表达式是由逻辑运算符连接运算对象而构成的表达式,它在程序中常用于表示复杂条件。例如,上述“优等生”问题,如果要求每门课程的成绩都不低于90时判定为“优等生”,那么程序中判断优等生的条件就要发生变化,满足优等生的条件是关系表达 式s1>=90与s2>=90都要成立。以下是该复杂条件的逻辑表达式,其中&&称为逻辑“与”运算。 s1>=90&&s2>=90 1.逻辑运算符 C语言的逻辑符有三个,分别为逻辑与运算符&&、逻辑或运算符||以及逻辑非运算 符“!”。 当两个条件为“并且”关系时,使用“与”运算&&表示,实例如上。 当两个条件为“或者”关系时,使用“或”运算||表示。例如,关于上述优等生问题,若任意一门课程的成绩不低于90,即判定为“优等生”,则判定“优等生”的逻辑表达式如下: s1>=90||s2>=90 当对某个条件进行否定时,使用“非”运算“!”表示。例如,表达式s1>=90可用如下“!”运算表示: !(s1<90) 2.逻辑表达式的值 逻辑表达式只有1和0两个取值。当逻辑表达式所表示的条件成立时(条件为“真”),其值为1;否则(条件为“假”),其值为0。设a、b为表示条件的表达式,则对应于a、b的各种取值时,逻辑表达式“!a”、a&&b和a||b的结果值如表3-2所示。该表称为逻辑运算真值表,它清楚地描述了逻辑运算&&、||、“!”的功能。表3-2 逻辑运算真值表ab!aa&&ba||b1(真)1(真)0(假)1(真)1(真)1(真)0(假)
0(假)1(真)0(假)1(真)1(真)0(假)1(真)0(假)0(假)
0(假)0(假) 【例3-2】 将数学关系式2020,并且x≤100,使用逻辑与运算&&可描述x的取值关系: x>20&&x<=100 (2)逻辑表达式求值 当x=50时,表达式x>20为1、表达式x<=100为1,则逻辑表达式x>20&&x<=100的值为1。 3.逻辑运算符的优先级和结合性 (1)优先级:!高于&& ,&&高于||。 (2)优先级:!高于算术运算符,&&、||低于关系运算符。 (3)结合性:&&、||是左结合的,!是右结合的。 4.逻辑运算的特点 (1)由与运算&&构成的逻辑表达式,自左至右求值,若运算符&&前端表达式的值为0时,则不再对其后端进行运算,整个与运算表达式的值为0。例如,逻辑表达式a&&b求值时,若a为0,则表达式的值为0,对b不再求值;若a非0,则需计算b的值。 (2)由或运算||构成的逻辑表达式,自左至右求值,若运算符||前端表达式的值为1时,则不再对其后端进行运算,整个或运算表达式的值为1。例如,逻辑表达式a||b求值时,若a为1,则表达式的值为1,对b不再求值;若a为0,则需计算b的值。3.1.4 if命令 if命令是基本的选择控制命令,在具体应用中有多种不同的使用形式。但不管何种形式,都要首先判断给定的条件,然后决定下一步要执行程序的哪些语句。 1.双分支if命令 双分支if命令的一般形式如下: if(表达式) {语句组1} else {语句组2} 其中,“表达式”是if命令进行分支处理的条件;“语句组”是若干个C语句,当它只有一个语句时,花括号{}可以省略。 双分支if命令的执行过程如下: 首先对“表达式”求值,然后进行判断分支:若“表达式”为非0值(即“真”),则执行{语句组1},然后执行紧接{语句组2}之后的语句;否则(即“假”),执行{语句组2},然后继续向下执行其他语句。分支控制过程的流程图如图3-1所示。 【例3-3】 计算下面分段函数的值(关系表达式作为选择条件)。
(1)算法设计 用流程图描述算法,如图3-2所示。
图3-1 双分支if命令流程图 图3-2 例3-2算法流程图 (2)实现程序 #include int main() { int x,y; printf(“X=”); scanf(“%d”,&x); /* 输入x的值 */ if(x>0) /* 判断x>0是否成立 */ y=x 25; /* x>0成立时 */ else y=x-25; /* x>0不成立时 */ printf(“Y=%dn”,y); /* 输出y的值 */ return 0; } 【例3-4】 输入一个学生两门课程的成绩,若每门课程的成绩都不低于90,则显示“优等生”,否则显示“加油!”(逻辑表达式作为选择条件)。 程序如下: #include int main() { int s1,s2; printf(“输入课程成绩:”); scanf(“%d,%d”,&s1,&s2); if(s1>=90&&s2>=90) printf(“优等生!n”); /* 每门课程成绩都不低于90 */ else printf(“加油!n”); /* 至少有一门课程成绩不足90 */ return 0; } 该程序中,逻辑表达式“s1>=90&&s2>=90”作为if命令的选择条件,只有该条件成立时,才会显示“优等生”。程序的算法流程图如图3-3所示。
图3-3 例3-4算法流程图 以下是程序的执行实例,希望读者根据具体数据,对if命令的分支控制过程进行分析。 次执行结果: 输入课程成绩:88,96 (此时,表达式s1>=90&&s2>=90不成立) 加油! 第二次执行结果: 输入课程成绩:95,90(此时,表达式s1>=90&&s2>=90成立) 优等生! 【例3-5】 从键盘输入一个字符,若其为大写英文字母,则在屏幕上输出它的小写形式;否则,原样输出该字符。 (1)问题分析 ① 输入字符后首先要判断它是否为大写字母。设输入量为ch,则下面的逻辑表达式成立(其值为1)时,ch为大写字母: ch>=’A’&&ch<=’Z’ ② 当ch为大写字母时,其对应的小写字母的ASCII码值为ch 32,以%c格式输出该表达式,即显示为小写字母。 (2)算法设计 ① 输入字符并存储到ch中。 ② 判断逻辑表达式ch>=’A’&&ch<=’Z’,若其成立,则以%c格式输出ch 32;否则,输出ch。 (3)实现程序 #include int main() { char ch; printf(“Input: “); ch=getchar(); /* 输入字符 */ printf(“Output: “); if(ch>=’A’&&ch<=’Z’) /* 判断ch是否为大写字母 */ printf(“%cn”,ch 32); /* ch为大写字母时,输出其小写形式 */ else printf(“%cn”,ch); /*ch不是大写字母时,原样输出 */ return 0; } 下面是程序两次运行的结果: Input: T Output: t Input: example Output: e (4)问题思考 在上面的运行结果中,当输入字符串“example”时,输出结果为e。为什么输入一个字符串时,只对其个字符进行输出处理? 2.单分支if命令 单分支if命令形式如下: if(表达式) ??{语句组} 执行过程:首先对“表达式”求值,若表达式的值非0(即真),则执行{语句组},然后继续向下执行其他语句;否则,不执行{语句组},而直接执行{语句组}之下的语句。简言之,该if命令的功能是根据条件表达式的值,决定是否执行{语句组},其控制过程的流程图如图3-4 所示。 【例3-6】 输入一个学生两门课程的成绩,若平均成绩不低于90,则显示“优等生”。 (1)算法设计 这是例3-1的一个简化问题,算法流程图如图3-5所示。 (2)程序实现 #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩s1、s2 */ ave=(s1 s2)/2; /* 计算平均成绩ave */ if(ave>=90) /* 判断ave>=90是否成立 */ printf(“优等生!n”); /* ave>=90成立时执行该语句 */ return 0; }
图3-4 单分支if命令流程图 图3-5 例3-6算法流程图 执行程序时,若输入的成绩数据满足优等生的条件,则显示“优等生”,否则,立即结束,不会显示任何信息。 3.if命令的嵌套结构 当一个if命令的{语句组}内又使用了if命令时,就形成了if命令的嵌套结构,这种结构用于多重条件判断的情况。图3-6是if命令嵌套结构示意图,该图只表示了嵌套的两种情况。
(a) (b)图3-6 if命令嵌套结构示意图 【例3-7】 输入一个学生两门课程的成绩,若平均成绩小于0,则显示“数据错误!”;否则,若平均成绩不低于90,则显示“优等生”,低于90则显示“加油!”。 (1)算法设计 根据平均成绩的计算结果,问题处理将有两个大的分支: 分支一:平均成绩小于0,显示“数据错误!”; 分支二:平均成绩不小于0,进一步进行小分支处理。 算法流程图如图3-7所示。对照流程图,先给出具体的实现程序,然后再对if命令的嵌套情况进行说明。也希望读者能够借助程序流程图,加深对if命令嵌套结构的认识。
图3-7 if命令的嵌套结构举例 (2)实现程序 #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); /* 输入两门课程的成绩 */ ave=(s1 s2)/2; /* 计算平均成绩,存储到变量ave中 */ ① if(ave<0) /* 外层if */ ② printf(“数据错误!n”); ③ else /* 与外层if配对 */ ④ if(ave>=90) /* 内层if */ ⑤ printf(“优等生!n”); ⑥ else /* 与内层if配对 */ ⑦ printf(“加油!n”); return 0; } 次执行结果: 输入两门课的成绩:70,?90 数据错误! 第二次执行结果: 输入两门课的成绩:90,95 优等生! 第三次执行结果: 输入两门课的成绩:70,65 加油! 为便于说明程序嵌套结构,部分语句加了编号,这些编号信息不属于源程序的内容。程序有两个if命令,①和③构成外层的if命令,②位于外层if命令的{语句组1}内,④、⑤、⑥、⑦位于外层if命令的{语句组2}内,④和⑥构成的if命令嵌套在外层if命令中。 使用嵌套的if命令,首先应避免出现嵌套混乱。C语言规定,在else语句无明确配对结构时,else与其前近的一个尚未配对的if配对。下面是两个程序段,可以进一步说明else和if的配对情况。 程序段一: if(x>20) { if(y>100) printf(“Good”); } else printf(“Bad”); 程序段二: if(x>20) if(y>100) printf(“Good”); else printf(“Bad”); 程序段一整体上是一个if-else的结构,else与个if配对。程序段二整体上是一个单分支if语句,else与第二个if配对,共同作为个if命令的语句体。关于这两个程序段的执行结果,希望读者分析并进行验证。 4. if-else if结构 if-else if结构属于if-else结构的嵌套形式,它的一般结构如下: if(表达式1) {语句组1} else if(表达式2) {语句组2} else if(表达式3) {语句组3} else if(表达式n) {语句组n} else {语句组n 1} 该结构中的每一个“表达式”都是一个“条件”,该结构的功能是根据表达式的值决定是否执行它所属的语句组。if-else if结构的具体执行过程为:从上到下逐个对条件进行判断,一旦条件满足就执行与它有关的语句组,其下的所有条件都不再判断,当然它们的语句组也不被执行;当任何一个条件都不满足时,执行{语句组n 1}。如图3-8所示为四层if结构的流程图。
图3-8 if-else if语句的逻辑结构 【例3-8】 用if-else if结构改写例3-7的程序。 程序如下: #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); ave=(s1 s2)/2; if(ave<0) printf(“数据错误!n”); /* ave<0 成立时 */ else if(ave>=90) printf(“优等生!n”); /* ave<0 不成立,而ave>=90成立时 */ else printf(“加油!n”); /* ave<0 不成立,ave>=90也不成立时 */ return 0; } 希望读者对照例3-7的程序,通过具体数据,分析该程序的执行过程。3.1.5 条件运算 条件运算是C语言的一个三目运算,运算符由“?”和“:”构成,它根据条件从两个表达式中选择一个进行计算取值。有些简单的if-else结构可通过条件运算实现。 1.条件运算表达式 由条件运算符构成的表达式称为条件运算表达式,其一般形式如下: 表达式1?表达式2:表达式3 例如: 5?19 6:21 条件运算表达式按以下过程求值: (1)计算“表达式1”的值; (2)当“表达式1”的值非0时,取“表达式2”的值为条件运算表达式的值;否则,取“表达式3”的值为条件运算表达式的值。 由此可以求得上面的条件运算表达式的值为25。 2.条件运算的优先级和结合性 条件运算的优先级高于赋值运算,而低于关系运算。 【例3-9】 用条件运算计算下面分段函数的值。
(1)问题分析 使用x>0作为计算y值的条件,即可得到计算y值的条件运算表达式。 y=(x>0)?(x 25):(x?25) 或者 y=x>0?x 25:x?25 当然,也可以使用x?0作为计算y值的条件,具体表达式由读者分析给出。 (2)算法设计 ① 输入x; ② 计算表达式(x>0)?(x 25):(x?25)的值,并存储在y变量中; ③ 输出y。 (3)实现程序 #include int main() { int x,y; printf(“X=”); scanf(“%d”,&x); /* 输入x */ y=(x>0)?(x 25):(x-25); /* 计算(x>0)?(x 25):(x-25),存储在y中 */ printf(“Y=%dn”,y); /* 输出y */ return 0; } 本节例3-3中,该分段函数的求值是通过if命令判断而实现的,希望读者注意比较这两个程序的异同。3.2 switch选择结构 switch选择结构是多分支选择的常见形式,由switch命令实现,具有结构清晰的特点。 switch命令的一般格式如下: switch(表达式) { case 常量1: 语句组1 case 常量2: 语句组2 case 常量n: 语句组n default: 语句组n 1 } switch命令的执行过程如下: 首先计算switch表达式的值,然后从第1个case行开始,由上至下依次扫描case行,比较case行中的常量值与switch表达式的值是否相同,一旦遇到相同的情况就停止扫描过程,并从该case行的语句组开始,依次向下执行各语句组,直至遇到强制中断命令break或执行完后一个语句组为止。当所有case都不符合要求时,执行default下的语句组。 在扫描case行时,case的语句组不起任何作用;开始执行语句后,其下的所有case行以及default行都被忽略掉,不再有任何作用。图3-9是switch命令执行过程的示意图。
图3-9 switch命令执行过程示意图 使用switch命令时,允许缺省“default:”及其语句组。 【例3-10】 switch执行过程示例程序。 #include int main() { int i; scanf(“%d”,&i); /* 为变量i输入数据 */ switch(i) { case 0: printf(“zero “); /* i为0时输出 */ case 1: printf(“one “); /* i为0或1时输出 */ break; /* 终止switch语句 */ case 2: printf(“two “); /* i为2时输出 */ case 3: printf(“three “); /* i为2或3时输出 */ case 4: printf(“four “); /* i为2或3或4时输出 */ break; /* 终止switch语句 */ default: printf(“other “); /* i不为0、1、2、3、4时输出 */ } printf(“n”); return 0; } 分别用0、1、3、6的值为i提供数据,执行4次程序,结果如下: i=0时,输出:zero one i=1时,输出:one i=3时,输出:three four i=6时,输出:other 程序中的“break”为中断命令,其功能是终止switch语句,使程序立即执行switch语句的后续语句,即“printf(“n”);”。 下面是关于switch语句的其他几点说明: (1)任何一个case的语句组允许为空。 【例3-11】 缺省case语句组的程序举例。 #include int main() { char result; scanf(“%c”,&result); /* 为变量result输入字符 */ switch(result) { case ‘A’: case ‘B’: case ‘C’: printf (“Good!n”); /* result为A或B或C时执行该语句*/ break; /* 终止switch语句 */ case ‘D’: case ‘E’: printf (“Bad!n”); /* result为D或E时执行该语句*/ break; /* 终止switch语句 */ default: printf (“Error!n”); /* result不是A、B、C、D、E时执行该语句 */ } return 0; } 该程序执行后,输入A或B或C时,显示“Good!”;输入D或E时显示“Bad!”;其他输入则显示Error!。 (2)switch表达式通常为整数型值或字符型值,case中常量的类型应与之相应。 (3)case中的“常量”位置允许是常数表达式,但不允许是变量表达式。 如下用法是正确的: case 5 8: case ‘a’ 6: 如下用法是错误的: case a 5: (4)switch命令允许嵌套,即在case的语句组中允许再使用switch命令。 3.3 选择结构程序举例 【例3-12】 编写一个程序,根据公历历法的闰年规律,判定某个年份是否为闰年。 1.问题分析与算法设计 闰年是为了弥补因人为历法造成的年度天数与地球实际公转周期的时间差而设立的,补上时间差的年份即为闰年。地球绕太阳运行周期约为365.24219天,即一回归年。公历的平年只有365天,比回归年短约0.24219?天,每四年累积约一天,把这一天加于2月末(2月29日),使当年延长为366天,这一年就为闰年。 按照每四年一个闰年计算,平均每年就要多算出0.0078天,经过四百年就会多出大约3天来,因此,每四百年中要减少三个闰年。所以规定公历年份是整百数的,必须是400的倍数才是闰年,不是400的倍数的就是平年。例如,1700年、1800年和1900年为平年,2000年为闰年。 简而言之,公历历法闰年的遵循规律为:四年一闰,百年不闰,四百年再闰。(1)设用变量year表示年份,写出满足闰年条件的逻辑表达式。 当year是400的整倍数时为闰年,条件表示为: year%400==0 当year是4的整倍数,但不是100的整倍数时为闰年, 条件表示为: year%4==0&&year%100!=0 对于年份year,满足上述任何一个条件均为闰年。因此,满足闰年条件的逻辑表达式如下: year%400==0||year%4==0&&year%100!=0 当上述表达式成立时,即为闰年。(2)输入year,根据上述逻辑表达式的值,即可得到year是否为闰年的结论。 其算法流程图如图3-10所示。
图3-10 闰年问题算法流程图2.实现程序 #include int main() { int year; /* 定义存储年份值的变量 */ printf(“Input year: “); scanf(“%d”,&year); /* 输入年份值 */ if(year%400==0||year%4==0&&year%100!=0) /* 判断闰年 */ printf(“%d is a leap year.n”,year); /* 是闰年时 */ else printf(“%d is not a leap year.n”,year); /* 不是闰年时 */ return 0; } 执行结果: Input year: 1995 1995 is not a leap year. 再次运行 Input year: 2000 2000 is a leap year. 该程序主要是学习在if语句中使用综合条件的方法,将多种条件组合成逻辑表达式,可以简化程序设计。 3. 问题思考 下面的程序也能对闰年年份进行判断,功能与上面的程序相同,但程序更简洁,它将printf()函数和条件运算结合起来,巧妙地解决了闰年判断问题。希望读者运行程序,并结合程序执行结果对程序进行解读分析。 #include int main() { int year; printf(“Year=”); scanf(“%d”,&year); printf(“%sn”,year%(year%100?4:400)?”NO”:”YES”); return 0; } 【例3-13】 设计求解一元二次方程(a≠0)的通用程序,并运行程序,对下面的两个方程求解。 方程一: 方程二: 1.问题分析与算法设计 (1)一元二次方程若有实根,则计算并输出实根,;否则,输出无实根信息。 (2)程序的输入量为方程的系数a、b、c。输入不同的系数,则求解不同的方程。 (3)程序中要使用数学函数sqrt(),因此,要注意打开math.h文件。 程序的算法流程图如图3-11所示。 2.实现程序 #include #include int main() { float a,b,c; /* 定义存储方程式系数的变量 */ float x1,x2,d; /* x1、x2存储方程根,d存储判别式的值 */ printf(“Input a,b,c: “); scanf(“%f,%f,%f”,&a,&b,&c); /* 输入方程式的系数值 */ d=b*b-4.0*a*c; /* 计算判别式的值 */ if(d>=0.0) /* 当方程有实根时,求方程的两个实根 */ { x1=(-b sqrt(d))/(2.0*a); /* 计算x1 */ x2=(-b-sqrt(d))/(2.0*a); /* 计算x2 */ printf(“x1=%f,x2=%fn”,x1,x2); /* 输出x1、x2 */ } else /* 当方程无实根时,输出无实根信息 */ printf(“no real root.n”); return 0; }
图3-11 求解一元二次方程的算法流程图 下面是求解方程一的执行结果: Input a,b,c: 3,9,-1 (输入方程一的系数) x1=0.107275,x2=-3.107175 下面是求解方程二的执行结果: Input a,b,c: 2,-4,3 (输入方程二的系数) no real root. 【例3-14】 学生成绩分等级显示。某班学生有两门课程,按百分制成绩(无小数位)进行考核。要求输入一个学生两门课程的成绩,然后按平均成绩分等级显示考核结果。考核结果的等级标准如下: 优秀(excellence):平均成绩?90; 良好(all right):80?平均成绩<90; 中等(middling):70?平均成绩<80; 及格(pass):60?平均成绩<70; 不及格(fail):平均成绩<60。 1.问题分析与算法设计 实现学生成绩分等级显示的基本处理过程,可以分成两个阶段。 (1)输入成绩并计算平均成绩。 (2)分等级显示。成绩分为5个等级,每个等级对应不同的条件。类似的多分支问题,通常使用if-else if结构或者switch结构进行逻辑控制。本例使用if-else if结构,算法流程图如图3-12所示。
图3-12 “学生成绩分等级显示”算法流程图 2.实现程序 #include int main() { int s1,s2,ave; /* s1、s2课程成绩、ave平均成绩*/ printf(“Score: “); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩 */ ave=(s1 s2)/2; /* 计算平均成绩 */ if(ave>=90) printf(“Result: excellencen”); /* 优秀 */ else if(ave>=80) printf(“Result: all rightn”); /* 良好 */ else if(ave>=70) printf(“Result: middlingn”); /* 中等 */ else if(ave>=60) printf(“Result: passn”); /* 及格 */ else printf(“Result: failn”); /* 不及格 */ return 0; } 程序执行结果: Score: 77,98(此时,ave为87) Result: all right Score: 89,92(此时,ave为90) Result: excellence 3. 问题思考 (1)对输入数据进行合法性检查,是算法评价的一项重要指标(算法的健壮性)。上面的程序未检查输入数据的合法性,即使输入了百分制之外的成绩值(如900、?90等),也会进行等级判定,这显然是不合理的。希望读者完善程序,使得只有输入数据合法时,才会进行等级判定,输出相应结果。 (2)“学生成绩分等级显示”是一个多分支处理问题,上面的程序使用if-else if结构实现分支控制。类似的多分支处理问题,使用switch结构也能方便地予以实现。希望读者使用switch结构改写上面的程序。小 结 本章介绍了程序中的分支结构知识,主要有if命令、switch命令、用于条件表达的关系表达式和逻辑表达式,以及分支结构程序的典型实例。 (1)if命令是基本的分支控制命令,它有多种形式,通常用关系表达式和逻辑表达式进行分支条件表达。任何一种if命令的语句体中都可以出现其他的if结构,这种结构称为if命令的嵌套结构。 (2)switch命令专门用于多路分支控制,适用于if -else if式的结构,而且更清晰。程序总是试图从满足条件的个case子句开始执行其后的所有语句,而不再对其后的case进行判断。因此,必要时使用break命令中断switch命令的运行。 (3)本章后,通过闰年问题、求解一元二次方程和学生成绩分等级显示等典型实例,详细介绍了分支结构程序设计的方法和过程。习 题 3 一、选择题 1.下面是由if构成的一个程序段: if(a B. C. D. 2.以下程序段的运行结果为________。 int x=2,y=-1,z=2; if(x /* 个if */ if(y<0)z=0; /* 第二个if */ else z =1; printf(“%dn”,z); A.3 B.2 C.1 D.0 3.有程序段如下: int a=1,b=2,c=3; if(a>b)c=a; a=b; b=c; 执行该程序段后,变量a、b、c的值是__________。 A.a=1,b=2,c=3 B.a=2,b=3,c=3 C.a=2,b=3,c=1 D.a=2,b=3,c=2 4.执行下面的程序段后,a和b的值分别为________。 int a=3,b=5,c; c=(a>–b)?a :b–; A.3,2 B.3,3 C.4,4 D.4,5 5.以下程序段的输出结果是________。 int x,y,temp; x=1,y=2; if(1) { if(x B.x=2,y=2 C.x=1,y=2 D.x=2,y=1 6.程序段如下: int x,y,z,max; x=1,y=2,z=3; max=x; if(z>y) { if(z>x) max=z; } else if(y>x) max=y; printf(“MAX=%dn”,max); 执行该段程序后,输出结果为________。 A.MAX=1 B.MAX=2 C.MAX=3 D.不确定 7.有变量定义如下: char ch=’A’; 则下列表达式的值是________。 Ch=(ch>’A’&& ch<=’Z’)?(ch 32):ch; A. A B.a C. Z D.z 8.有程序段如下: int year=2000; printf(“%sn”,year%(year%100?4:400)?”NO”:”YES”); 执行上面的printf()语句后,输出结果是________。 A.NO B.YES C.NO:YES D.不确定 9.有语句如下: int n; scanf(“%d”,&n); 要求当n是奇数时将其显示输出。以下语句中,符合要求的是________。 A.if(n%2==0)printf(“%dn”,n); B.if(n%2)printf(“%dn”,n); C.if(n%2=1)printf(“%dn”,n); D.if(n/2==1)printf(“%dn”,n); 10.有程序段如下: int flag; char ch; scanf(“%c”,&ch); flag=ch>=’0’&&ch<=’9′; if(flag) printf(“%cn”,ch); 以下关于程序段执行结果的叙述中正确的是________。 A.当输入一个字符时,立即将该字符输出 B.对输入的任何数值立即输出 C.若输入一个数字字符,则立即将其输出 D.若输入的字符是非数字字符时,则将其输出 二、编程题 1.按照如图3-13所示的流程图编写程序,并指出程序功能。 2.按照如图3-14所示的流程图编写程序,并指出程序功能。
图3-13 习题1算法流程图 图3-14 习题2算法流程图 3.计算邮费,邮件重量由键盘输入。邮件计费标准为:不超过100克时,每件10元;超过100克后,超出部分每克计费0.5元。 4.按照货物重量计算运费并输出结果。物流公司按照货物重量分段计费,标准如下: 货物重量不超过50吨时,运费为80元/吨;货物重量超过50吨,但不超过100吨时,超出部分运费为75元/吨;货物重量超过100吨时,超出部分运费为70元/吨。 5.求分段函数y的值,其中x的值由键盘输入。
6.输入三个整数,然后按由大到小的顺序输出这三个数。 7.由键盘输入一个整数,判断其能否既被3整除又被5整除。 8.编写程序,其功能是:输入1、2、3、4、5、6、7中的任一个数字,将对应显示Monday、Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday;输入其他数字,则显示No!。 9.编写完整求解一元二次方程的程序。 10.由键盘输入一个字符,判断是字母、数字还是其他符号。 11.输入一个不多于3位的正整数,编写程序,实现以下功能: (1)求出它是几位数。 (2)按逆序打印出各位数字,例如原数为321,应输出123。实验3 选择结构程序设计 一、实验目的 (1)学会使用关系表达式、逻辑表达式表示条件的方法。 (2)掌握if命令三种形式的用法。 (3)掌握switch命令的用法。 (4)学会具有嵌套的选择结构程序设计方法。 二、基本实验 1.if命令及简单条件(单一关系表达式表示条件)练习 按以下要求修改例3-1的程序: (1)学生的课程成绩可以是包括小数位的实数值。 (2)输出结果包括两类信息: ① 显示平均成绩; ② 若平均成绩不低于90分,则显示“优等生”;否则显示“加油!”。 以下为结果示例。 次执行程序: 输入两门课的成绩:95.5,81 Average: 83.3 加油! 第二次执行程序: 输入两门课的成绩:95.5,89 Average: 92.3 优等生! 2.if命令及复杂条件(逻辑表达式表示条件)练习 修改上面的程序,将判定优等生的条件改为:若任意一门课程的成绩不低于90,即判定为“优等生”。 3.单分支if命令练习 修改上面的程序,使其只有在优等生情况时,才显示相关信息。 4.if-else if命令练习 修改例3-8的程序,使程序执行后显示的结果与实验内容1的形式相同,即在原有显示信息之前,再增加平均成绩的信息。 5.switch选择结构练习 例3-14使用if-else if结构实现“学生成绩分等级显示”的程序,事实上使用switch结构也能方便地解决这一问题。试用switch分支结构改写例3-14的程序。 提示:为减少case数量,可先将分布在[0,100]范围的平均成绩ave(保留整数),通过表达式ave/10将其映射到[0,10]的较小范围内,如表3-3所示。在switch结构中,使用switch(ave/10)形式进行分支控制,算法流程图如图3-15所示。表3-3 “ave/10”与等级对应表ave(int型)的值ave/10的值对应等级10010优秀(excellence)小于100、不小于909优秀(excellence)小于90、不小于808良好(all right)小于80、不小于707中等(middling)小于70、不小于606及格(pass)小于605、4、3、2、1、0不及格(fail)
图3-15 使用switch结构的算法流程图 参考程序: #include int main(void) { int s1,s2,ave; /* s1、s2存储课程成绩,ave存储平均成绩*/ printf(“Score: “); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩 */ ave=(s1 s2)/2; /* 计算平均成绩 */ switch(ave/10) { case 10: /* ave为100 */ case 9: /* ave小于100、不小于90 */ printf(“Result: excellencen”); /* 优秀时,输出等级结果 */ break; case 8: /* ave小于90、不小于80 */ printf(“Result: all rightn”); /* 良好时,输出等级结果 */ break; case 7: /* ave小于80、不小于70 */ printf(“Result: middlingn”); /* 中等时,输出等级结果 */ break; case 6: /* ave小于70、不小于60 */ printf(“Result: passn”); /* 及格时,输出等级结果 */ break; default: /* ave小于60 */ printf(“Result: failn”); /* 不及格时,输出等级结果 */ } return 0; } 参考数据及结果: Score: 77,98(此时,ave为87,ave/10为8,与“case 8:”匹配 */ Result: all right Score: 89,92(此时,ave为90,ave/10为9,与“case 9:”匹配 */ Result: excellence 三、综合实验 编写学生成绩分等级程序。某学期有两门课程,每门课程都按百分制实行理论考核,按A、B两级实行实验考核。要求按照如下标准对学生的学习情况进行综合评价: (1)综合评价结论由理论考核成绩和实验考核成绩共同确定。 (2)理论考核按照平均成绩分为如下5个等级: 优秀(excellence):平均成绩?90; 良好(all right):80?平均成绩<90; 中等(middling):70?平均成绩<80; 及格(pass):60?平均成绩<70; 不及格(fail):平均成绩<60。 (3)当两门课的实验考核成绩均达到A级时,综合评定等级即为理论考核的等级,否则按照理论考核的等级降一级认定。若理论考核等级为“不及格”时,不管实验考核成绩如何,综合评定等级仍为“不及格”。 实验参考如下。 (1)编程分析 ① 本实验题目是前述学生成绩分等级显示问题的进一步扩展。理论成绩分等级的程序分析设计参考前述教学内容。本实验需要特别考虑的是,按照理论成绩分等后,要进一步对实验考核成绩进行判断,然后才能确定综合结论。可以考虑在switch语句中使用if语句处理。 ② 输入数据的方式也应是程序设计时认真考虑的问题,合理的数据输入形式会使输入数据时清晰,而且不容易出错。例如,可以将每门课的理论考核成绩和实验考核成绩合为一体输入。假若有如下成绩: a课程:理论考核为90,实验考核为A。 b课程:理论考核为80,实验考核为B。 则可以考虑使用如下方式输入数据: 90A,80B (2)参考程序 #include int main(void) { int a1,b1; /* a1,b1分别存储a、b两门课程的理论考核成绩 */ char a2,b2; /* a2,b2分别存储a、b两门课程的实验考核成绩 */ int ave; repeat: printf(“请输入考核成绩: “); scanf(“%d%c,%d%c”,&a1,&a2,&b1,&b2); if(a1<0||b1<0||a1>100||b1>100) goto repeat; /* 输入非法数据时,要求重新输入 */ ave=(a1 b1)/2; switch(ave/10) { case 10: case 9: if(a2==’A’&&b2==’A’) printf(“Result: excellencen”); /* 理论≥90,实验均为A等 */ else printf(“Result: all rightn”); /* 理论≥90,实验不为A等 */ break; case 8: if(a2==’A’&&b2==’A’) printf(“Result: all rightn”); /* 80≤理论<90,实验均为A等 */ else printf(“Result: middlingn”); /* 80≤理论<90,实验不为A等 */ break; case 7: if(a2==’A’&&b2==’A’) printf(“Result: middlingn”); /* 70≤理论<80,实验均为A等 */ else printf(“Result: passn”); /* 70≤理论<80,实验不为A等 */ break; case 6: if(a2==’A’&&b2==’A’) printf(“Result: passn”); /* 60≤理论<70,实验均为A等 */ else printf(“Result: failn”); /* 60≤理论<70,实验不为A等 */ break; default: printf(“Result: failn”); /* 理论<60 */ } return 0; } 关于参考程序的说明: (1)该程序对数据输入的合法性进行了一定检验,能够确保理论考核的输入数据在 0~100范围内,但对实验考核输入数据的合法性未作检验。程序中体现的实验考核成绩只有A和非A两种情况。 (2)若实验考核成绩为A级时,必须输入大写A,否则将处理为非A级。当然,可以通过修改程序,无论输入A或a时,都认定为A级。 ??
??
??
??
C语言程序设计——理论、方法与实践(第2版)
0(假)1(真)0(假)1(真)1(真)0(假)1(真)0(假)0(假)
0(假)0(假) 【例3-2】 将数学关系式2020,并且x≤100,使用逻辑与运算&&可描述x的取值关系: x>20&&x<=100 (2)逻辑表达式求值 当x=50时,表达式x>20为1、表达式x<=100为1,则逻辑表达式x>20&&x<=100的值为1。 3.逻辑运算符的优先级和结合性 (1)优先级:!高于&& ,&&高于||。 (2)优先级:!高于算术运算符,&&、||低于关系运算符。 (3)结合性:&&、||是左结合的,!是右结合的。 4.逻辑运算的特点 (1)由与运算&&构成的逻辑表达式,自左至右求值,若运算符&&前端表达式的值为0时,则不再对其后端进行运算,整个与运算表达式的值为0。例如,逻辑表达式a&&b求值时,若a为0,则表达式的值为0,对b不再求值;若a非0,则需计算b的值。 (2)由或运算||构成的逻辑表达式,自左至右求值,若运算符||前端表达式的值为1时,则不再对其后端进行运算,整个或运算表达式的值为1。例如,逻辑表达式a||b求值时,若a为1,则表达式的值为1,对b不再求值;若a为0,则需计算b的值。3.1.4 if命令 if命令是基本的选择控制命令,在具体应用中有多种不同的使用形式。但不管何种形式,都要首先判断给定的条件,然后决定下一步要执行程序的哪些语句。 1.双分支if命令 双分支if命令的一般形式如下: if(表达式) {语句组1} else {语句组2} 其中,“表达式”是if命令进行分支处理的条件;“语句组”是若干个C语句,当它只有一个语句时,花括号{}可以省略。 双分支if命令的执行过程如下: 首先对“表达式”求值,然后进行判断分支:若“表达式”为非0值(即“真”),则执行{语句组1},然后执行紧接{语句组2}之后的语句;否则(即“假”),执行{语句组2},然后继续向下执行其他语句。分支控制过程的流程图如图3-1所示。 【例3-3】 计算下面分段函数的值(关系表达式作为选择条件)。
(1)算法设计 用流程图描述算法,如图3-2所示。
图3-1 双分支if命令流程图 图3-2 例3-2算法流程图 (2)实现程序 #include int main() { int x,y; printf(“X=”); scanf(“%d”,&x); /* 输入x的值 */ if(x>0) /* 判断x>0是否成立 */ y=x 25; /* x>0成立时 */ else y=x-25; /* x>0不成立时 */ printf(“Y=%dn”,y); /* 输出y的值 */ return 0; } 【例3-4】 输入一个学生两门课程的成绩,若每门课程的成绩都不低于90,则显示“优等生”,否则显示“加油!”(逻辑表达式作为选择条件)。 程序如下: #include int main() { int s1,s2; printf(“输入课程成绩:”); scanf(“%d,%d”,&s1,&s2); if(s1>=90&&s2>=90) printf(“优等生!n”); /* 每门课程成绩都不低于90 */ else printf(“加油!n”); /* 至少有一门课程成绩不足90 */ return 0; } 该程序中,逻辑表达式“s1>=90&&s2>=90”作为if命令的选择条件,只有该条件成立时,才会显示“优等生”。程序的算法流程图如图3-3所示。
图3-3 例3-4算法流程图 以下是程序的执行实例,希望读者根据具体数据,对if命令的分支控制过程进行分析。 次执行结果: 输入课程成绩:88,96 (此时,表达式s1>=90&&s2>=90不成立) 加油! 第二次执行结果: 输入课程成绩:95,90(此时,表达式s1>=90&&s2>=90成立) 优等生! 【例3-5】 从键盘输入一个字符,若其为大写英文字母,则在屏幕上输出它的小写形式;否则,原样输出该字符。 (1)问题分析 ① 输入字符后首先要判断它是否为大写字母。设输入量为ch,则下面的逻辑表达式成立(其值为1)时,ch为大写字母: ch>=’A’&&ch<=’Z’ ② 当ch为大写字母时,其对应的小写字母的ASCII码值为ch 32,以%c格式输出该表达式,即显示为小写字母。 (2)算法设计 ① 输入字符并存储到ch中。 ② 判断逻辑表达式ch>=’A’&&ch<=’Z’,若其成立,则以%c格式输出ch 32;否则,输出ch。 (3)实现程序 #include int main() { char ch; printf(“Input: “); ch=getchar(); /* 输入字符 */ printf(“Output: “); if(ch>=’A’&&ch<=’Z’) /* 判断ch是否为大写字母 */ printf(“%cn”,ch 32); /* ch为大写字母时,输出其小写形式 */ else printf(“%cn”,ch); /*ch不是大写字母时,原样输出 */ return 0; } 下面是程序两次运行的结果: Input: T Output: t Input: example Output: e (4)问题思考 在上面的运行结果中,当输入字符串“example”时,输出结果为e。为什么输入一个字符串时,只对其个字符进行输出处理? 2.单分支if命令 单分支if命令形式如下: if(表达式) ??{语句组} 执行过程:首先对“表达式”求值,若表达式的值非0(即真),则执行{语句组},然后继续向下执行其他语句;否则,不执行{语句组},而直接执行{语句组}之下的语句。简言之,该if命令的功能是根据条件表达式的值,决定是否执行{语句组},其控制过程的流程图如图3-4 所示。 【例3-6】 输入一个学生两门课程的成绩,若平均成绩不低于90,则显示“优等生”。 (1)算法设计 这是例3-1的一个简化问题,算法流程图如图3-5所示。 (2)程序实现 #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩s1、s2 */ ave=(s1 s2)/2; /* 计算平均成绩ave */ if(ave>=90) /* 判断ave>=90是否成立 */ printf(“优等生!n”); /* ave>=90成立时执行该语句 */ return 0; }
图3-4 单分支if命令流程图 图3-5 例3-6算法流程图 执行程序时,若输入的成绩数据满足优等生的条件,则显示“优等生”,否则,立即结束,不会显示任何信息。 3.if命令的嵌套结构 当一个if命令的{语句组}内又使用了if命令时,就形成了if命令的嵌套结构,这种结构用于多重条件判断的情况。图3-6是if命令嵌套结构示意图,该图只表示了嵌套的两种情况。
(a) (b)图3-6 if命令嵌套结构示意图 【例3-7】 输入一个学生两门课程的成绩,若平均成绩小于0,则显示“数据错误!”;否则,若平均成绩不低于90,则显示“优等生”,低于90则显示“加油!”。 (1)算法设计 根据平均成绩的计算结果,问题处理将有两个大的分支: 分支一:平均成绩小于0,显示“数据错误!”; 分支二:平均成绩不小于0,进一步进行小分支处理。 算法流程图如图3-7所示。对照流程图,先给出具体的实现程序,然后再对if命令的嵌套情况进行说明。也希望读者能够借助程序流程图,加深对if命令嵌套结构的认识。
图3-7 if命令的嵌套结构举例 (2)实现程序 #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); /* 输入两门课程的成绩 */ ave=(s1 s2)/2; /* 计算平均成绩,存储到变量ave中 */ ① if(ave<0) /* 外层if */ ② printf(“数据错误!n”); ③ else /* 与外层if配对 */ ④ if(ave>=90) /* 内层if */ ⑤ printf(“优等生!n”); ⑥ else /* 与内层if配对 */ ⑦ printf(“加油!n”); return 0; } 次执行结果: 输入两门课的成绩:70,?90 数据错误! 第二次执行结果: 输入两门课的成绩:90,95 优等生! 第三次执行结果: 输入两门课的成绩:70,65 加油! 为便于说明程序嵌套结构,部分语句加了编号,这些编号信息不属于源程序的内容。程序有两个if命令,①和③构成外层的if命令,②位于外层if命令的{语句组1}内,④、⑤、⑥、⑦位于外层if命令的{语句组2}内,④和⑥构成的if命令嵌套在外层if命令中。 使用嵌套的if命令,首先应避免出现嵌套混乱。C语言规定,在else语句无明确配对结构时,else与其前近的一个尚未配对的if配对。下面是两个程序段,可以进一步说明else和if的配对情况。 程序段一: if(x>20) { if(y>100) printf(“Good”); } else printf(“Bad”); 程序段二: if(x>20) if(y>100) printf(“Good”); else printf(“Bad”); 程序段一整体上是一个if-else的结构,else与个if配对。程序段二整体上是一个单分支if语句,else与第二个if配对,共同作为个if命令的语句体。关于这两个程序段的执行结果,希望读者分析并进行验证。 4. if-else if结构 if-else if结构属于if-else结构的嵌套形式,它的一般结构如下: if(表达式1) {语句组1} else if(表达式2) {语句组2} else if(表达式3) {语句组3} else if(表达式n) {语句组n} else {语句组n 1} 该结构中的每一个“表达式”都是一个“条件”,该结构的功能是根据表达式的值决定是否执行它所属的语句组。if-else if结构的具体执行过程为:从上到下逐个对条件进行判断,一旦条件满足就执行与它有关的语句组,其下的所有条件都不再判断,当然它们的语句组也不被执行;当任何一个条件都不满足时,执行{语句组n 1}。如图3-8所示为四层if结构的流程图。
图3-8 if-else if语句的逻辑结构 【例3-8】 用if-else if结构改写例3-7的程序。 程序如下: #include int main() { int s1,s2,ave; printf(“输入两门课的成绩:”); scanf(“%d,%d”,&s1,&s2); ave=(s1 s2)/2; if(ave<0) printf(“数据错误!n”); /* ave<0 成立时 */ else if(ave>=90) printf(“优等生!n”); /* ave<0 不成立,而ave>=90成立时 */ else printf(“加油!n”); /* ave<0 不成立,ave>=90也不成立时 */ return 0; } 希望读者对照例3-7的程序,通过具体数据,分析该程序的执行过程。3.1.5 条件运算 条件运算是C语言的一个三目运算,运算符由“?”和“:”构成,它根据条件从两个表达式中选择一个进行计算取值。有些简单的if-else结构可通过条件运算实现。 1.条件运算表达式 由条件运算符构成的表达式称为条件运算表达式,其一般形式如下: 表达式1?表达式2:表达式3 例如: 5?19 6:21 条件运算表达式按以下过程求值: (1)计算“表达式1”的值; (2)当“表达式1”的值非0时,取“表达式2”的值为条件运算表达式的值;否则,取“表达式3”的值为条件运算表达式的值。 由此可以求得上面的条件运算表达式的值为25。 2.条件运算的优先级和结合性 条件运算的优先级高于赋值运算,而低于关系运算。 【例3-9】 用条件运算计算下面分段函数的值。
(1)问题分析 使用x>0作为计算y值的条件,即可得到计算y值的条件运算表达式。 y=(x>0)?(x 25):(x?25) 或者 y=x>0?x 25:x?25 当然,也可以使用x?0作为计算y值的条件,具体表达式由读者分析给出。 (2)算法设计 ① 输入x; ② 计算表达式(x>0)?(x 25):(x?25)的值,并存储在y变量中; ③ 输出y。 (3)实现程序 #include int main() { int x,y; printf(“X=”); scanf(“%d”,&x); /* 输入x */ y=(x>0)?(x 25):(x-25); /* 计算(x>0)?(x 25):(x-25),存储在y中 */ printf(“Y=%dn”,y); /* 输出y */ return 0; } 本节例3-3中,该分段函数的求值是通过if命令判断而实现的,希望读者注意比较这两个程序的异同。3.2 switch选择结构 switch选择结构是多分支选择的常见形式,由switch命令实现,具有结构清晰的特点。 switch命令的一般格式如下: switch(表达式) { case 常量1: 语句组1 case 常量2: 语句组2 case 常量n: 语句组n default: 语句组n 1 } switch命令的执行过程如下: 首先计算switch表达式的值,然后从第1个case行开始,由上至下依次扫描case行,比较case行中的常量值与switch表达式的值是否相同,一旦遇到相同的情况就停止扫描过程,并从该case行的语句组开始,依次向下执行各语句组,直至遇到强制中断命令break或执行完后一个语句组为止。当所有case都不符合要求时,执行default下的语句组。 在扫描case行时,case的语句组不起任何作用;开始执行语句后,其下的所有case行以及default行都被忽略掉,不再有任何作用。图3-9是switch命令执行过程的示意图。
图3-9 switch命令执行过程示意图 使用switch命令时,允许缺省“default:”及其语句组。 【例3-10】 switch执行过程示例程序。 #include int main() { int i; scanf(“%d”,&i); /* 为变量i输入数据 */ switch(i) { case 0: printf(“zero “); /* i为0时输出 */ case 1: printf(“one “); /* i为0或1时输出 */ break; /* 终止switch语句 */ case 2: printf(“two “); /* i为2时输出 */ case 3: printf(“three “); /* i为2或3时输出 */ case 4: printf(“four “); /* i为2或3或4时输出 */ break; /* 终止switch语句 */ default: printf(“other “); /* i不为0、1、2、3、4时输出 */ } printf(“n”); return 0; } 分别用0、1、3、6的值为i提供数据,执行4次程序,结果如下: i=0时,输出:zero one i=1时,输出:one i=3时,输出:three four i=6时,输出:other 程序中的“break”为中断命令,其功能是终止switch语句,使程序立即执行switch语句的后续语句,即“printf(“n”);”。 下面是关于switch语句的其他几点说明: (1)任何一个case的语句组允许为空。 【例3-11】 缺省case语句组的程序举例。 #include int main() { char result; scanf(“%c”,&result); /* 为变量result输入字符 */ switch(result) { case ‘A’: case ‘B’: case ‘C’: printf (“Good!n”); /* result为A或B或C时执行该语句*/ break; /* 终止switch语句 */ case ‘D’: case ‘E’: printf (“Bad!n”); /* result为D或E时执行该语句*/ break; /* 终止switch语句 */ default: printf (“Error!n”); /* result不是A、B、C、D、E时执行该语句 */ } return 0; } 该程序执行后,输入A或B或C时,显示“Good!”;输入D或E时显示“Bad!”;其他输入则显示Error!。 (2)switch表达式通常为整数型值或字符型值,case中常量的类型应与之相应。 (3)case中的“常量”位置允许是常数表达式,但不允许是变量表达式。 如下用法是正确的: case 5 8: case ‘a’ 6: 如下用法是错误的: case a 5: (4)switch命令允许嵌套,即在case的语句组中允许再使用switch命令。 3.3 选择结构程序举例 【例3-12】 编写一个程序,根据公历历法的闰年规律,判定某个年份是否为闰年。 1.问题分析与算法设计 闰年是为了弥补因人为历法造成的年度天数与地球实际公转周期的时间差而设立的,补上时间差的年份即为闰年。地球绕太阳运行周期约为365.24219天,即一回归年。公历的平年只有365天,比回归年短约0.24219?天,每四年累积约一天,把这一天加于2月末(2月29日),使当年延长为366天,这一年就为闰年。 按照每四年一个闰年计算,平均每年就要多算出0.0078天,经过四百年就会多出大约3天来,因此,每四百年中要减少三个闰年。所以规定公历年份是整百数的,必须是400的倍数才是闰年,不是400的倍数的就是平年。例如,1700年、1800年和1900年为平年,2000年为闰年。 简而言之,公历历法闰年的遵循规律为:四年一闰,百年不闰,四百年再闰。(1)设用变量year表示年份,写出满足闰年条件的逻辑表达式。 当year是400的整倍数时为闰年,条件表示为: year%400==0 当year是4的整倍数,但不是100的整倍数时为闰年, 条件表示为: year%4==0&&year%100!=0 对于年份year,满足上述任何一个条件均为闰年。因此,满足闰年条件的逻辑表达式如下: year%400==0||year%4==0&&year%100!=0 当上述表达式成立时,即为闰年。(2)输入year,根据上述逻辑表达式的值,即可得到year是否为闰年的结论。 其算法流程图如图3-10所示。
图3-10 闰年问题算法流程图2.实现程序 #include int main() { int year; /* 定义存储年份值的变量 */ printf(“Input year: “); scanf(“%d”,&year); /* 输入年份值 */ if(year%400==0||year%4==0&&year%100!=0) /* 判断闰年 */ printf(“%d is a leap year.n”,year); /* 是闰年时 */ else printf(“%d is not a leap year.n”,year); /* 不是闰年时 */ return 0; } 执行结果: Input year: 1995 1995 is not a leap year. 再次运行 Input year: 2000 2000 is a leap year. 该程序主要是学习在if语句中使用综合条件的方法,将多种条件组合成逻辑表达式,可以简化程序设计。 3. 问题思考 下面的程序也能对闰年年份进行判断,功能与上面的程序相同,但程序更简洁,它将printf()函数和条件运算结合起来,巧妙地解决了闰年判断问题。希望读者运行程序,并结合程序执行结果对程序进行解读分析。 #include int main() { int year; printf(“Year=”); scanf(“%d”,&year); printf(“%sn”,year%(year%100?4:400)?”NO”:”YES”); return 0; } 【例3-13】 设计求解一元二次方程(a≠0)的通用程序,并运行程序,对下面的两个方程求解。 方程一: 方程二: 1.问题分析与算法设计 (1)一元二次方程若有实根,则计算并输出实根,;否则,输出无实根信息。 (2)程序的输入量为方程的系数a、b、c。输入不同的系数,则求解不同的方程。 (3)程序中要使用数学函数sqrt(),因此,要注意打开math.h文件。 程序的算法流程图如图3-11所示。 2.实现程序 #include #include int main() { float a,b,c; /* 定义存储方程式系数的变量 */ float x1,x2,d; /* x1、x2存储方程根,d存储判别式的值 */ printf(“Input a,b,c: “); scanf(“%f,%f,%f”,&a,&b,&c); /* 输入方程式的系数值 */ d=b*b-4.0*a*c; /* 计算判别式的值 */ if(d>=0.0) /* 当方程有实根时,求方程的两个实根 */ { x1=(-b sqrt(d))/(2.0*a); /* 计算x1 */ x2=(-b-sqrt(d))/(2.0*a); /* 计算x2 */ printf(“x1=%f,x2=%fn”,x1,x2); /* 输出x1、x2 */ } else /* 当方程无实根时,输出无实根信息 */ printf(“no real root.n”); return 0; }
图3-11 求解一元二次方程的算法流程图 下面是求解方程一的执行结果: Input a,b,c: 3,9,-1 (输入方程一的系数) x1=0.107275,x2=-3.107175 下面是求解方程二的执行结果: Input a,b,c: 2,-4,3 (输入方程二的系数) no real root. 【例3-14】 学生成绩分等级显示。某班学生有两门课程,按百分制成绩(无小数位)进行考核。要求输入一个学生两门课程的成绩,然后按平均成绩分等级显示考核结果。考核结果的等级标准如下: 优秀(excellence):平均成绩?90; 良好(all right):80?平均成绩<90; 中等(middling):70?平均成绩<80; 及格(pass):60?平均成绩<70; 不及格(fail):平均成绩<60。 1.问题分析与算法设计 实现学生成绩分等级显示的基本处理过程,可以分成两个阶段。 (1)输入成绩并计算平均成绩。 (2)分等级显示。成绩分为5个等级,每个等级对应不同的条件。类似的多分支问题,通常使用if-else if结构或者switch结构进行逻辑控制。本例使用if-else if结构,算法流程图如图3-12所示。
图3-12 “学生成绩分等级显示”算法流程图 2.实现程序 #include int main() { int s1,s2,ave; /* s1、s2课程成绩、ave平均成绩*/ printf(“Score: “); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩 */ ave=(s1 s2)/2; /* 计算平均成绩 */ if(ave>=90) printf(“Result: excellencen”); /* 优秀 */ else if(ave>=80) printf(“Result: all rightn”); /* 良好 */ else if(ave>=70) printf(“Result: middlingn”); /* 中等 */ else if(ave>=60) printf(“Result: passn”); /* 及格 */ else printf(“Result: failn”); /* 不及格 */ return 0; } 程序执行结果: Score: 77,98(此时,ave为87) Result: all right Score: 89,92(此时,ave为90) Result: excellence 3. 问题思考 (1)对输入数据进行合法性检查,是算法评价的一项重要指标(算法的健壮性)。上面的程序未检查输入数据的合法性,即使输入了百分制之外的成绩值(如900、?90等),也会进行等级判定,这显然是不合理的。希望读者完善程序,使得只有输入数据合法时,才会进行等级判定,输出相应结果。 (2)“学生成绩分等级显示”是一个多分支处理问题,上面的程序使用if-else if结构实现分支控制。类似的多分支处理问题,使用switch结构也能方便地予以实现。希望读者使用switch结构改写上面的程序。小 结 本章介绍了程序中的分支结构知识,主要有if命令、switch命令、用于条件表达的关系表达式和逻辑表达式,以及分支结构程序的典型实例。 (1)if命令是基本的分支控制命令,它有多种形式,通常用关系表达式和逻辑表达式进行分支条件表达。任何一种if命令的语句体中都可以出现其他的if结构,这种结构称为if命令的嵌套结构。 (2)switch命令专门用于多路分支控制,适用于if -else if式的结构,而且更清晰。程序总是试图从满足条件的个case子句开始执行其后的所有语句,而不再对其后的case进行判断。因此,必要时使用break命令中断switch命令的运行。 (3)本章后,通过闰年问题、求解一元二次方程和学生成绩分等级显示等典型实例,详细介绍了分支结构程序设计的方法和过程。习 题 3 一、选择题 1.下面是由if构成的一个程序段: if(a B. C. D. 2.以下程序段的运行结果为________。 int x=2,y=-1,z=2; if(x /* 个if */ if(y<0)z=0; /* 第二个if */ else z =1; printf(“%dn”,z); A.3 B.2 C.1 D.0 3.有程序段如下: int a=1,b=2,c=3; if(a>b)c=a; a=b; b=c; 执行该程序段后,变量a、b、c的值是__________。 A.a=1,b=2,c=3 B.a=2,b=3,c=3 C.a=2,b=3,c=1 D.a=2,b=3,c=2 4.执行下面的程序段后,a和b的值分别为________。 int a=3,b=5,c; c=(a>–b)?a :b–; A.3,2 B.3,3 C.4,4 D.4,5 5.以下程序段的输出结果是________。 int x,y,temp; x=1,y=2; if(1) { if(x B.x=2,y=2 C.x=1,y=2 D.x=2,y=1 6.程序段如下: int x,y,z,max; x=1,y=2,z=3; max=x; if(z>y) { if(z>x) max=z; } else if(y>x) max=y; printf(“MAX=%dn”,max); 执行该段程序后,输出结果为________。 A.MAX=1 B.MAX=2 C.MAX=3 D.不确定 7.有变量定义如下: char ch=’A’; 则下列表达式的值是________。 Ch=(ch>’A’&& ch<=’Z’)?(ch 32):ch; A. A B.a C. Z D.z 8.有程序段如下: int year=2000; printf(“%sn”,year%(year%100?4:400)?”NO”:”YES”); 执行上面的printf()语句后,输出结果是________。 A.NO B.YES C.NO:YES D.不确定 9.有语句如下: int n; scanf(“%d”,&n); 要求当n是奇数时将其显示输出。以下语句中,符合要求的是________。 A.if(n%2==0)printf(“%dn”,n); B.if(n%2)printf(“%dn”,n); C.if(n%2=1)printf(“%dn”,n); D.if(n/2==1)printf(“%dn”,n); 10.有程序段如下: int flag; char ch; scanf(“%c”,&ch); flag=ch>=’0’&&ch<=’9′; if(flag) printf(“%cn”,ch); 以下关于程序段执行结果的叙述中正确的是________。 A.当输入一个字符时,立即将该字符输出 B.对输入的任何数值立即输出 C.若输入一个数字字符,则立即将其输出 D.若输入的字符是非数字字符时,则将其输出 二、编程题 1.按照如图3-13所示的流程图编写程序,并指出程序功能。 2.按照如图3-14所示的流程图编写程序,并指出程序功能。
图3-13 习题1算法流程图 图3-14 习题2算法流程图 3.计算邮费,邮件重量由键盘输入。邮件计费标准为:不超过100克时,每件10元;超过100克后,超出部分每克计费0.5元。 4.按照货物重量计算运费并输出结果。物流公司按照货物重量分段计费,标准如下: 货物重量不超过50吨时,运费为80元/吨;货物重量超过50吨,但不超过100吨时,超出部分运费为75元/吨;货物重量超过100吨时,超出部分运费为70元/吨。 5.求分段函数y的值,其中x的值由键盘输入。
6.输入三个整数,然后按由大到小的顺序输出这三个数。 7.由键盘输入一个整数,判断其能否既被3整除又被5整除。 8.编写程序,其功能是:输入1、2、3、4、5、6、7中的任一个数字,将对应显示Monday、Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday;输入其他数字,则显示No!。 9.编写完整求解一元二次方程的程序。 10.由键盘输入一个字符,判断是字母、数字还是其他符号。 11.输入一个不多于3位的正整数,编写程序,实现以下功能: (1)求出它是几位数。 (2)按逆序打印出各位数字,例如原数为321,应输出123。实验3 选择结构程序设计 一、实验目的 (1)学会使用关系表达式、逻辑表达式表示条件的方法。 (2)掌握if命令三种形式的用法。 (3)掌握switch命令的用法。 (4)学会具有嵌套的选择结构程序设计方法。 二、基本实验 1.if命令及简单条件(单一关系表达式表示条件)练习 按以下要求修改例3-1的程序: (1)学生的课程成绩可以是包括小数位的实数值。 (2)输出结果包括两类信息: ① 显示平均成绩; ② 若平均成绩不低于90分,则显示“优等生”;否则显示“加油!”。 以下为结果示例。 次执行程序: 输入两门课的成绩:95.5,81 Average: 83.3 加油! 第二次执行程序: 输入两门课的成绩:95.5,89 Average: 92.3 优等生! 2.if命令及复杂条件(逻辑表达式表示条件)练习 修改上面的程序,将判定优等生的条件改为:若任意一门课程的成绩不低于90,即判定为“优等生”。 3.单分支if命令练习 修改上面的程序,使其只有在优等生情况时,才显示相关信息。 4.if-else if命令练习 修改例3-8的程序,使程序执行后显示的结果与实验内容1的形式相同,即在原有显示信息之前,再增加平均成绩的信息。 5.switch选择结构练习 例3-14使用if-else if结构实现“学生成绩分等级显示”的程序,事实上使用switch结构也能方便地解决这一问题。试用switch分支结构改写例3-14的程序。 提示:为减少case数量,可先将分布在[0,100]范围的平均成绩ave(保留整数),通过表达式ave/10将其映射到[0,10]的较小范围内,如表3-3所示。在switch结构中,使用switch(ave/10)形式进行分支控制,算法流程图如图3-15所示。表3-3 “ave/10”与等级对应表ave(int型)的值ave/10的值对应等级10010优秀(excellence)小于100、不小于909优秀(excellence)小于90、不小于808良好(all right)小于80、不小于707中等(middling)小于70、不小于606及格(pass)小于605、4、3、2、1、0不及格(fail)
图3-15 使用switch结构的算法流程图 参考程序: #include int main(void) { int s1,s2,ave; /* s1、s2存储课程成绩,ave存储平均成绩*/ printf(“Score: “); scanf(“%d,%d”,&s1,&s2); /* 输入课程成绩 */ ave=(s1 s2)/2; /* 计算平均成绩 */ switch(ave/10) { case 10: /* ave为100 */ case 9: /* ave小于100、不小于90 */ printf(“Result: excellencen”); /* 优秀时,输出等级结果 */ break; case 8: /* ave小于90、不小于80 */ printf(“Result: all rightn”); /* 良好时,输出等级结果 */ break; case 7: /* ave小于80、不小于70 */ printf(“Result: middlingn”); /* 中等时,输出等级结果 */ break; case 6: /* ave小于70、不小于60 */ printf(“Result: passn”); /* 及格时,输出等级结果 */ break; default: /* ave小于60 */ printf(“Result: failn”); /* 不及格时,输出等级结果 */ } return 0; } 参考数据及结果: Score: 77,98(此时,ave为87,ave/10为8,与“case 8:”匹配 */ Result: all right Score: 89,92(此时,ave为90,ave/10为9,与“case 9:”匹配 */ Result: excellence 三、综合实验 编写学生成绩分等级程序。某学期有两门课程,每门课程都按百分制实行理论考核,按A、B两级实行实验考核。要求按照如下标准对学生的学习情况进行综合评价: (1)综合评价结论由理论考核成绩和实验考核成绩共同确定。 (2)理论考核按照平均成绩分为如下5个等级: 优秀(excellence):平均成绩?90; 良好(all right):80?平均成绩<90; 中等(middling):70?平均成绩<80; 及格(pass):60?平均成绩<70; 不及格(fail):平均成绩<60。 (3)当两门课的实验考核成绩均达到A级时,综合评定等级即为理论考核的等级,否则按照理论考核的等级降一级认定。若理论考核等级为“不及格”时,不管实验考核成绩如何,综合评定等级仍为“不及格”。 实验参考如下。 (1)编程分析 ① 本实验题目是前述学生成绩分等级显示问题的进一步扩展。理论成绩分等级的程序分析设计参考前述教学内容。本实验需要特别考虑的是,按照理论成绩分等后,要进一步对实验考核成绩进行判断,然后才能确定综合结论。可以考虑在switch语句中使用if语句处理。 ② 输入数据的方式也应是程序设计时认真考虑的问题,合理的数据输入形式会使输入数据时清晰,而且不容易出错。例如,可以将每门课的理论考核成绩和实验考核成绩合为一体输入。假若有如下成绩: a课程:理论考核为90,实验考核为A。 b课程:理论考核为80,实验考核为B。 则可以考虑使用如下方式输入数据: 90A,80B (2)参考程序 #include int main(void) { int a1,b1; /* a1,b1分别存储a、b两门课程的理论考核成绩 */ char a2,b2; /* a2,b2分别存储a、b两门课程的实验考核成绩 */ int ave; repeat: printf(“请输入考核成绩: “); scanf(“%d%c,%d%c”,&a1,&a2,&b1,&b2); if(a1<0||b1<0||a1>100||b1>100) goto repeat; /* 输入非法数据时,要求重新输入 */ ave=(a1 b1)/2; switch(ave/10) { case 10: case 9: if(a2==’A’&&b2==’A’) printf(“Result: excellencen”); /* 理论≥90,实验均为A等 */ else printf(“Result: all rightn”); /* 理论≥90,实验不为A等 */ break; case 8: if(a2==’A’&&b2==’A’) printf(“Result: all rightn”); /* 80≤理论<90,实验均为A等 */ else printf(“Result: middlingn”); /* 80≤理论<90,实验不为A等 */ break; case 7: if(a2==’A’&&b2==’A’) printf(“Result: middlingn”); /* 70≤理论<80,实验均为A等 */ else printf(“Result: passn”); /* 70≤理论<80,实验不为A等 */ break; case 6: if(a2==’A’&&b2==’A’) printf(“Result: passn”); /* 60≤理论<70,实验均为A等 */ else printf(“Result: failn”); /* 60≤理论<70,实验不为A等 */ break; default: printf(“Result: failn”); /* 理论<60 */ } return 0; } 关于参考程序的说明: (1)该程序对数据输入的合法性进行了一定检验,能够确保理论考核的输入数据在 0~100范围内,但对实验考核输入数据的合法性未作检验。程序中体现的实验考核成绩只有A和非A两种情况。 (2)若实验考核成绩为A级时,必须输入大写A,否则将处理为非A级。当然,可以通过修改程序,无论输入A或a时,都认定为A级。 ??
??
??
??
C语言程序设计——理论、方法与实践(第2版)
科 选择结构程序设计
书摘插画
评论
还没有评论。