C语言程序设计基础(通识版 慕课版) 课件全套 第1-10章 程序设计的计算机基础 -文件读写和综合应用_第1页
C语言程序设计基础(通识版 慕课版) 课件全套 第1-10章 程序设计的计算机基础 -文件读写和综合应用_第2页
C语言程序设计基础(通识版 慕课版) 课件全套 第1-10章 程序设计的计算机基础 -文件读写和综合应用_第3页
C语言程序设计基础(通识版 慕课版) 课件全套 第1-10章 程序设计的计算机基础 -文件读写和综合应用_第4页
C语言程序设计基础(通识版 慕课版) 课件全套 第1-10章 程序设计的计算机基础 -文件读写和综合应用_第5页
已阅读5页,还剩440页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

哈尔滨工业大学第1章程序设计的计算机基础计算机与人工智能他是少年天才,曾享受与爱因斯坦同等的待遇(不须上课),是计算机史上著名的“101页报告”的作者之一,被誉为“现代计算机之父”他是改变世界的第三个苹果的缔造者,是电脑业界与娱乐业界的标志性人物,他为我们留下众多传世之作!他是个人PC时代当之无愧的领军人物,他的软件产品遍布世界每一个角落,而他也当仁不让地长期霸占世界首富的桂冠!他曾协助军方破解德国的著名密码系统Enigma,他提出的著名模型为现代计算机的逻辑工作方式奠定了基础,被誉为“计算机科学之父”2计算机与人工智能3CanMachinesThink?计算机与人工智能人工智能(ArtificialIntelligence,简称AI)让计算机具有执行某些与人类智能活动有关的复杂功能(如判断、推理、识别、理解、学习、规划和问题求解等)的能力《变形金刚》《人工智能》《终结者》系列《黑客帝国》三部曲4人机大战计算机与人工智能5IBM的”思考”成为第一台能同人下棋的计算机19581988“深思”击败丹麦特级大师拉尔森1989“深思”在与世界棋王卡斯帕罗夫进行的对阵中以0比2败北1996“深蓝”诞生,在与卡斯帕罗夫的挑战赛中”深蓝”以2比4失利1997“更深的蓝”以3比2击败了卡斯帕罗夫2001“更弗里茨”击败了卡斯帕罗夫、阿南德以及除了克拉姆尼克之外的所有排名世界前十位的棋手2002“更弗里茨”与克拉姆尼克以4比4战平2014年6月7日,聊天程序“尤金·古斯特曼”在英国皇家学会举行的2014图灵测试大会上冒充一个13岁乌克兰男孩而骗过了33%的评委,从而“通过”了图灵测试2012年6月底,在英国著名的布莱切利庄园举行了一场国际人工智能机器测试竞赛。由俄罗斯专家设计的“叶甫根尼”电脑程序脱颖而出,其29.2%的回答均成功“骗过”了测试者计算机与人工智能计算机很强大?2011年,IBM公司研制的可以参加智力问答比赛的“沃森(Watson)”软件系统能以每秒翻100万本书的速度从其存储的2亿页百科全书、字典、文学作品中搜索答案,这种人类望尘莫及的事情计算机很笨?计算机去理解一个儿童故事这种连5岁小孩子都能做到的事情,却困难重重6计算机系统计算机系统(ComputerSystem)一种能按照事先存储的程序自动、高效地对数据进行输入、处理、存储和输出的系统由硬件(Hardware)和软件(Software)两部分组成7计算机系统硬件系统:计算机的躯壳8存储器输入设备输出设备控制器运算器CPU计算机系统硬件系统:计算机的躯壳9软件系统:计算机的灵魂计算机系统10操作系统应用软件支撑软件人与计算机是如何通讯的站起来坐下跳舞启动跑步1000100111110000自然语言机器语言机器语言机器语言(MachineLanguage)计算机能直接读懂和执行的语言机器代码(MachineCode)用机器语言编写的一组机器指令的集合12机器语言与高级语言100001100000011110001011000010101001011100000111MOVA,7ADDA,10MOV(7),AHLTResult=7+10Return编码机器语言二进制和编码方式汇编语言用助记符号编写程序高级语言用类似自然语言的语句编写程序13高级语言的分类

语言典型代表特点过程式语言(Procedural)C命令驱动,面向动作(语句),即将计算看作是动作(语句)的序列,程序由一系列的语句组成函数式语言(Functional)LISP注重程序实现的功能,程序的编写过程是从已有函数出发构造出更复杂的函数,应用这些函数直至计算求得最终结果面向对象语言(Object-Oriented)SmallTalk、C++、Java程序的编写过程是直接从问题本身出发分析问题,并把数据和操作封装在一起构成对象,用数据描述对象属性,用对数据的操作描述对象行为逻辑式语言(Logical)PROLOG基于规则的具有推理功能的语言10大流行语言的流行趋势和受欢迎程度C语言的设计者KenThompson江湖人称kenDennisM.Ritchie江湖人称dmr两个骨灰级游戏玩家Ritchie漫画像C语言的诞生始末1969年,ken梦想能遨游宇宙,设计了一款模拟在太阳系航行的电子游戏——“SpaceTravel”,1971年dmr加入游戏在PDP-7小型机上开发,因为这台机器免费,但免费的机器没有操作系统玩游戏前,先给PDP-7做个操作系统,命名为UNIX20世纪60年代,Ritchie和Thompson在贝尔实验室开发UNIX操作系统C语言的诞生始末汇编编写UNIX太慢,而一般的高级语言难以实现汇编语言的某些功能,怎么办?dmr改造B语言,设计了一种新的高级语言,命名为“C语言”,把UNIX的90%以上代码用C改写1983年,因为UNIX和C语言的巨大成功,ken和dmr共同获得当年度的计算机界最高奖——图灵奖1999年接受美国国家技术勋章C语言标准1978年,DennisM.Richie和BrianW.Kernighan合著影响深远的名著《TheCProgrammingLanguage》1982年,美国国家标准化协会(AmericanNationalStandardsInstitute,ANSI)成立C标准委员会1989年,发布第一个完整的C语言标准,简称C89习惯上也称为ANSIC(标准C)1990年被国际标准化组织ISO采纳,也称为C901999年修正和完善之后,ISO发布了C9919/37冯.诺依曼机运算器控制器存储器输入输出存储器输入设备输出设备控制器运算器CPU计算机的基本工作原理C语言编程的基本步骤源文件目标文件库文件可执行文件怎么学“编程”汉语和英语是人与人交流的工具,而程序设计语言是人与计算机交流的工具有着天生自学(汉语)的和后天训练(英语)的“语言学习”能力字母单词词性时态语态短语语气句子成分句型结构标识符数据类型常量函数控制结构变量数组字母指针AI辅助编程及其工具

AI编程工具是一种AI大语言模型驱动的工具,通过将其集成到现有的开发环境中提供代码生成、智能补全、错误检测、代码优化、代码解释、注释生成等功能。

Cursor、GitHub‌Copilot‌国外主流的AI编程工具由阿里基于通义大模型研发的通义灵码‌(TONGYILingma)由文心大模型提供技术支持的文心快码(Baidu‌Comate‌)字节跳动基于豆包大模型研发的豆包MarsCode腾讯云推出的腾讯云AI代码助手……国内主流的AI编程工具Thankyouforyourattention!Q&A24/37第2章基本IO和基本运算哈尔滨工业大学2.1认识C语言程序从HelloWorld开始【例2.1】向屏幕输出"Helloworld!"分两行输出“Helloworld!”呢?#include<stdio.h>intmain(void){printf("Helloworld\n");

return0;}以#开头,编译预处理指令EveryCprogrammusthaveamainfunctionTheexecutionofCprogramstartsfrommain()function头文件2.2变量及其数据类型常量(Constant)在程序中不能改变其值的量变量(Variable)其值在程序执行过程中是可以改变的2.2.1变量的类型和变量的定义(1)声明变量的同时为变量赋值(Assignment)

——变量的初始化(Initialize)未被初始化的变量的值会是什么?其值为随机数(乱码)

变量的声明(VariableDeclaration)

类型关键字变量名;2.2.1变量的类型和变量的定义使用变量的基本原则变量必须先声明,后使用一条声明语句可声明若干个同类型的变量inta,b,c;声明的顺序无关紧要占用内存空间的大小数据的存储形式合法的表数范围可参与的运算种类2.2.2变量的类型决定了什么?(1)不同数据类型可参与的运算不同整型加、减、乘、除、求余实型加、减、乘、除字符型加、减(整数)对ASCII码值的运算指针类型加、减(整数)和比较运算(2)不同类型数据占用的内存大小不同如何计算变量或类型占内存的大小计算变量占内存空间的大小用sizeof运算符一元运算符用sizeof运算符计算变量占内存空间的大小的好处增加程序的可移植性编译时执行的运算符,不会导致额外的运行时间开销语法形式运算结果sizeof(类型)类型占用的内存字节数

sizeof(变量或表达式)变量或表达式所属类型占的内存字节数整型数一个多字节的数据是如何存放到存储单元中的呢?小端次序便于计算机从低位字节向高位字节运算大端次序与人们从左到右的书写顺序相同,便于处理字符串(3)不同类型数据的存储形式不同高位字节低位字节……低位字节高位字节小端次序(Little-endian)……高位字节低位字节大端次序(Big-endian)如何存储实型数呢?关键:确定小数点的位置问题:如何表示实型数?小数形式指数形式——科学计数法(3)不同类型数据的存储形式不同整数部分小数部分定点数(FixedPoint)小数点的位置固定定点整数定点小数定点数定点小数(纯小数)——小数点位于符号位和最高数值位之间定点整数——小数点位于数值位的最低位

(3)不同类型数据的存储形式不同...符号位固定小数点数值部分...符号位固定小数点数值部分问题:如何表示实型数?小数形式指数形式——科学计数法(3)不同类型数据的存储形式不同整数部分小数部分指数部分小数部分定点数(FixedPoint)小数点的位置固定浮点数(Floating-Point)小数点的位置不固定浮点数实现小数点位置可浮动的主要原因将实数拆分成了阶码(Exponent)和尾数(Mantissa)分别存储对于同样的尾数,阶码的值越大,则浮点数所表示的数值的绝对值就越大(3)不同类型数据的存储形式不同阶码E(指数部分)尾数M(小数部分)N=rE

M

r为基数通常取2决定实数的表数精度决定实数的表数范围同样是4个字节(32位)定点数表数范围受其二进制位数的限制——值域都是有限的在计算机中通常是用定点数来表示整数和纯小数用浮点数表示既有整数部分、又有小数部分的实数(3)不同类型数据的存储形式不同定点数-231~231-1单精度浮点数-3.402823466×1038~3.402823466×1038字符型数据(英文字母、数字、控制字符)以二进制编码方式存储,一个字节保存一个字符字符编码方式取决于计算机系统所使用的字符集ASCII(美国标准信息交换码)字符集每个字符有一个编码值(查ASCII码表)字符常数就是一个普通整数(3)不同类型数据的存储形式不同01001000‘H’72(4)不同数据类型的表数范围不同(2)不同数据类型的表数范围不同以2字节(16位)短整型为例有符号整数的最高位是符号位,使其数据位比无符号整数的数据位少了1位2.2.3标识符的命名规则(1)标识符由英文字母、数字和下画线组成,且必须以英文字母或下画线开头。(2)不允许使用关键字作为标识符,同时标识符也不应与系统预定义的库函数重名。(3)C语言的标识符可以是任意长度。一般也会有最大长度(与编译器相关)限制。(4)标识符应直观、易于拼读、易于记忆,即做到“见名知意”,最好使用英文单词及其组合,切忌使用汉语拼音。2.2.3标识符的命名规则(5)标识符应尽量与所采用的操作系统或开发工具的风格保持一致。例如,Windows应用程序的标识符通常采用“大小写混排”方式,如MaxValue,而UNIX应用程序的标识符通常采用“小写加下画线”方式,如max_value。不要将两类风格混在一起使用。(6)C语言的标识符是区分大小写(对大小写敏感)的。在程序中不能改变其值的量包括:整型(如0,67,2,

123L,123u,

022,0x12)默认为基本整型int实型(如2.3,1.2e-5,2.73F,2.73L)默认为双精度实型double字符型(如'z','3','$’)字符串(如"UKM","1","5a”)枚举型2.3常量长整型无符号整型八进制十六进制单精度实型长双精度实型十进制小数指数形式十进制2.2.1常量的表示2.2.1常量的表示48/532.3.2宏常量和const变量在程序中直接使用的常数,称为幻数(MagicNumber)

问题:使用幻数存在什么问题?程序的可读性变差容易发生书写错误,产生不一致性当常数需要改变时,要修改所有引用它的代码,繁琐,还可能有遗漏良好的程序设计风格建议把幻数定义为宏常量const常量优点减少重复书写常数的工作量提高程序的可读性和可维护性宏常量(MacroConstant)用一个标识符号来表示的常量宏定义

#define

标识符字符串

编译预处理命令:在源程序编译之前,先对程序中的编译预处理命令进行处理然后将处理的结果和源程序一起进行编译,以得到目标代码2.3.2宏常量和const变量宏常量(MacroConstant)宏定义

#define

标识符字符串

#definePI3.14159

符号常量(SymbolicConstant)宏名(MacroName),一般全大写不区分数据类型2.3.2宏常量和const变量宏常量存在的问题是什么?没有数据类型,编译器在宏替换时不进行类型检查只进行简单的字符串替换,极易产生意想不到的错误2.3.2宏常量和const变量constdoublepi=3.14159;const常量与宏常量相比的优点是什么?const常量有数据类型,编译器能对其进行类型检查某些集成化调试工具可以对const常量进行调试2.4键盘输入和屏幕输出2.4.1单个字符的输入输出函数2.4.2格式化输入输出函数2.4.1单个字符的输入输出字符输出函数putchar()putchar(ch)向屏幕输出一个字符,字符型变量ch的值字符输入函数getchar()ch=getchar()从键盘接收的字符作为getchar()的函数值无参数【例2.2】小写英文字母转换成大写英文字母B↙b#include<stdio.h>intmain(void){ charch; ch=getchar();//从键盘输入一个字符,按回车键结束输入

ch=ch–('a'-'A');//将大写字母转换为小写字母 putchar(ch);//在屏幕上显示变量ch中的字符 putchar('\n');//输出一个回车换行控制符

return0;}2.4.2数据的格式化屏幕输出按指定格式和类型输出变量的值,或者输出一行字符串printf(格式控制字符串,输出值参数表);printf("a=%db=%f",a,b);输出值参数类型应与格式转换说明符相匹配可输出多个任意类型的数据可变长度的输出参数表与格式说明符一一对应普通字符转换说明指定输出数据格式%ddecimal

输出十进制有符号int型%uunsigned

输出十进制无符号int型%ffloat

以小数形式(6位小数)输出float,double型%eexponent以标准指数形式输出float,double型inta=10;printf("%d",a);10doubleb=10.3;printf("%f",b);10.300000floatb=10.3;printf("%e",b);1.030000e+0012.4.2数据的格式化屏幕输出%ccharacter以字符形式输出单个字符charc=‘A’;printf("%c",c);Acharc=‘A’;printf("%d",c);652.4.2数据的格式化屏幕输出2.4.3数据的格式化键盘输入

转换说明可变长度输入地址参数表格式

scanf(格式控制字符串,输入地址表);

scanf("%d%f",&a,&b);

&是取地址运算符格式

scanf(格式控制字符串,输入地址表);

scanf("%d%f",&a,&b);如何分隔多个输入数据?1)空格、Tab或回车2)达到输入位宽3)遇非法字符遇以上情况都认为一个数据输入结束:2.4.3数据的格式化键盘输入%d 输入十进制int型%f,%e 输入float型(不能指定输入数据的精度)%c 输入一个字符(包括空白字符)常见错误scanf("%7.2f",&a);scanf("%f",

a);scanf("%f\n",

&a);2.4.3数据的格式化键盘输入scanf()的格式修饰符m 输入数据的位宽l 加d、u前输入long型 加f、e前输入double型L 加f、e前输入longdouble型h 加d前输入short型%ld 输入longint型%hd 输入shortint型%f 输入float型%lf

输入double型m 输入数据的位宽l 加d、u前输入long型 加f、e前输入double型L 加f、e前输入longdouble型h 加d前输入short型* 输入项在读入后不赋给相应的变量2.4.3数据的格式化键盘输入2.5算术运算算术表达式除法(Division)

a/b浮点数除法(FloatingDivision)aorborbotharefloats整数除法(IntegerDivision)aandbareintegers11/5=211.0/5=2.22.5算术运算操作数必须是整数,返回a与b相除之后的余数(Remainder)(1)提取数字的最低位。例如,123%10即可得到123的最低位3。(2)判断一个数能否被另一个数整除。例如,若m%n的结果为0,则m能被n整除。(3)判断一个数是否为偶数。例如,若m%2的结果为0,则m为偶数。(4)生成一个指定范围内的随机数。求余(Modulus)——也称a对b取模

a%b2.5算术运算问题:输出一个三位整数的个位、十位和百位数字关键:如何分离个位、十位、百位数字?153%10

=3153/100=1153-1*100=53

53/10=5153-1*100-5*10=3153%100

=53

53/10=5153/10

=

15

15%10=52.5算术运算对p求模取余:H(k)=k%p将一个大范围的自然数集合映射到一个只有p个元素的小集合上随机函数rand()生成一个在0~32767之间的随机数问题:如何生成一个指定范围(如1~100)内的随机数?magic=rand()%100;//0~99magic=rand()%100+1;//1~1002.5算术运算常用的标准数学函数#include<math.h>函数名功能exp(x)ex函数名功能exp(x)expow(x,y)xy函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)fabs(x)|x|函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)fabs(x)|x|log(x)lnx,(x>0)函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)fabs(x)|x|log(x)lnx,(x>0)log10(x)lgx,(x>0)函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)fabs(x)|x|log(x)lnx,(x>0)log10(x)lgx,(x>0)sin(x)sinx,x为弧度值函数名功能exp(x)expow(x,y)xysqrt(x)x的平方根,(x>=0)fabs(x)|x|log(x)lnx,(x>0)log10(x)lgx,(x>0)sin(x)sinx,x为弧度值cos(x)cosx,x为弧度值2.5算术运算2.6赋值运算赋值运算符和数学中的等号有何区别?有方向性左值和右值类型应一致

(1)赋值表达式语句(

ExpressionStatement

变量

=

表达式

;

(2)定义变量的同时为变量赋值——初始化(Initialize)

类型变量=表达式;

2.6赋值运算赋值运算符的结合性?

(2)多重赋值(MultipleAssignment)

变量1=变量2=

表达式

赋值运算符的优先级?

(1)简单赋值(SimpleAssignment)

变量=

表达式

一种简写的且执行效率更高的赋值

(3)复合的赋值(CombinedAssignment)

变量1运算符op=表达式

2.6赋值运算增1运算符(Increment)++使变量的值增加1个单位减1运算符(Decrement)--使变量的值减少1个单位操作数只能是变量,不能是表达式,自增自减运算一元运算符前缀(prefix)++n--n后缀(postfix)n++n--

n=n+1

n=n–1

n=n+1

n=n–1作为前缀(prefix)运算符时++n,--n先对n增1/减1,然后再使用n的值m=++n;n=n+1;

m=n;printf("%d",++n);n=n+1;

printf("%d",n);用增1和减1运算生成的代码运行速度更快2.6赋值运算作为后缀(postfix)运算符时n++,n--先使用n的值,然后再对n增1/减1m=

n++;m=n;n=n+1;

printf("%d",n++);n=n+1;

printf("%d",n);2.7增1和减1运算符i5j??46前缀与后缀对变量和表达式的影响mnm=++n-2;n=n+1;

m=n-2;m=

n++-2;m=n-2;n=n+1;

n5m??36操作数的值是相同的但表达式的值是不同的2.7增1和减1运算符优点增1和减1运算生成的代码效率更高一些问题:过多的增1和减1运算混合会产生什么结果?可读性差,例如(++n)+(++n),(n++)+(n++)不同编译器产生的运行结果不同良好的程序设计风格提倡在一行语句中,一个变量只出现一次增1或减1运算2.7增1和减1运算符2.8.1自动类型转换2.8.2强制类型转换2.8混合数据类型运算中的类型转换算术表达式中问题:相同类型数据的运算结果的类型是什么?还是该类型例如,整数除法2.8.1自动类型转换11/5=2根据参与运算的操作数类型从低级别向高级别自动转换算术表达式中问题:不同类型数据的运算结果的类型是什么?取值范围较大的那种类型例如,浮点数除法C编译器将所有操作数都转换成取值范围较大的操作数的类型——类型提升(TypePromotion)11.0/5=11.0/5.0=2.22.8.1自动类型转换Example:

inttotal,number; floataver; … aver=total/number;

15/2

7total15number2aver??7.000000整数除法2.8.2强制类型转换不同类型的数据的运算结果的类型?

intnumber;

floattotal,aver; … aver=total/number;

15.000000/2

7.500000total15number2aver??7.500000浮点数除法2.8.2强制类型转换不同类型的数据的运算结果的类型?

intnumber;

floattotal,aver; … aver=total/number;

15.000000/2

7.500000total15number2aver??7.500000如何避免这种隐式的自动类型转换,以显式地表明程序员的意图?2.8.2强制类型转换Example:

inttotal,number; floataver; … aver=(float)total/number; total15number2aver??将一个表达式的类型强制转换为用户指定的类型

15.000000/2

7.5000007.500000(类型)表达式——一元运算符2.8.2强制类型转换Example:

inttotal,number; floataver; … aver=(float)total/number;

15.000000/2

7.500000total15number2aver??7.500000不改变total的类型和值2.8.2强制类型转换Example:

inttotal,number; floataver; … aver=(float)total/number;

15/2=7

7.000000total15number2aver??7.000000(float)(total/number)结果如何? 2.8.2强制类型转换1.明确需求2.撰写指令3.生成代码4.采纳并运行分析和梳理清楚你想要实现的项目需求用自然语言书写Prompt:背景,角色和任务,要求或示例,输出格式AI根据你的指令生成代码建议理解、评判、采纳并运行代码,确认是否符合需求2.9AI编程的基本流程本章思维导图85/53Thankyouforyourattention!Q&A86/50第3章基本控制结构哈尔滨工业大学3.1算法的概念和描述方法3.1.1算法的概念3.1.2算法的描述方法3.1.1算法的概念算法(Algorithm)为解决一个具体问题而采取的确定的有限的操作步骤,仅指计算机能执行的算法计算机中的问题求解计划通过程序员按照某种算法编写的计算机程序(ComputerProgram)来实现的设计出正确的算法是编写正确的计算机程序的前提条件程序设计是一门艺术,主要体现在算法设计结构设计揭示面向过程的程序本质的公式算法+数据结构=程序N.Wirth(图灵奖1984)Pascal创始人定义待操作的数据在计算机内存中是如何存储和组织的,选择恰当的数据结构可以提高程序的运行或存储效率对在数据上的操作的描述,不同的算法可能有不同的时间或空间效率3.1.1算法的概念算法的特性有穷性(Finiteness)在合理的时间内完成确定性(Definiteness)无歧义,能有效执行,且能得到确定的结果有效性(Effectiveness)允许没有输入或有多个输入(Input)必须有一个或多个输出(Output)3.1.1算法的概念常用的算法描述方法自然语言(NaturalLanguage)伪码(Pseudocode)表示传统的流程图(Flowchart)N-S结构化流程图3.1.2算法的描述方法3.1.2算法的描述方法以买苹果为例,已知单价每斤y元,问买x斤苹果,需多少钱?step1:输入x和y;step2:根据公式t=x*y计算总价;step3:输出总价t。BeginInputx,yt=x*yOutputtEnd

自然语言描述伪码描述通俗易懂,符合人的日常思维习惯,但不易直接转化为程序书写无固定格式和规范,灵活,介于自然语言和计算机语言之间,易于转换为计算机程序3.1.2算法的描述方法3.2顺序结构顺序结构:最简单、最常用的程序结构复合语句:以两数交换为例3.3选择结构3.3.1选择结构的控制方式3.3.2条件语句3.3.3开关语句3.3.1选择结构的控制方式选择结构根据给定的判定条件,判断结果,并根据判断的结果来控制程序的流程选择结构(分支结构)单分支选择结构(SingleSelection)双分支选择结构(DoubleSelection)多分支选择结构(MultipleSelection)单分支选择结构(SingleSelection)面临的选择是:要么执行一个操作,要么跳过它3.3.1选择结构的控制方式双分支选择结构(DoubleSelection)面临的选择是:在两个不同的操作中选择其中的一个来执行多分支选择结构(MultipleSelection)3.3.1选择结构的控制方式if-else单分支双分支多分支ifelse-if3.3.2条件语句【例3.1】计算最大值。从键盘输入两个整型数,编程计算并输出其最大值确定问题的输入和输出建立问题的数学模型算法描述3.3.2条件语句【例3.1】3.3.2条件语句#include<stdio.h>intmain(void){ inta,b,max; scanf("%d,%d",&a,&b); if(a>=b) { max=a; } else { max=b; } printf("max=%d\n",max);return0;}#include<stdio.h>intmain(void){ inta,b; scanf("%d,%d",&a,&b); if(a>=b) { printf("max=%d\n",a); } else { printf("max=%d\n",b); }return0;}【例3.1】3.3.2条件语句#include<stdio.h>intmain(void){ inta,b,max; scanf("%d,%d",&a,&b); max=a>=b?a:b;

printf("max=%d\n",max);return0;}#include<stdio.h>intmain(void){ inta,b; scanf("%d,%d",&a,&b); printf("max=%d\n",a>=b?a:b);//直接打印条件表达式的值

return0;}3.3.2条件语句如何表示真假值?真

1假

0如何判断真假值?非0

真0

假3.3.2条件语句3.3.2条件语句逻辑非

算术

关系

逻辑与

逻辑或

赋值圆括号优先级最高【例3.2】从键盘任意输入一个年份year,编程判断其是否为闰年,如果是闰年,则输出“Yes!”,否则输出“No!”。闰年需要满足下列两个条件中的任意一个。(1)能被4整除,但不能被100整除。(2)能被400整除。3.3.2条件语句#include<stdio.h>intmain(void){ intyear,leap; scanf("%d",&year); leap=((year%4==0)&&(year%100!=0))||(year%400==0); if(leap)//若leap的值为非0,即为真

{

printf("Yes!\n"); } else { printf("No!\n"); }return0;}【例3.2】从键盘任意输入一个年份year,编程判断其是否为闰年,如果是闰年,则输出“Yes!”,否则输出“No!”。3.3.2条件语句#include<stdio.h>intmain(void){ intyear; scanf("%d",&year); if(((year%4==0)&&(year%100!=0))||(year%400==0)) { printf("Yes!\n"); } else { printf("No!\n"); }return0;}【例3.3】简单的计算器。要求用户按如下格式从键盘输入算式:操作数1运算符op操作数2编程输出其计算结果值,算术运算符包括:加(+)、减(-)、乘(*)、除(/)。3.3.3开关语句3.3.3开关语句#include<stdio.h>intmain(void){ intdata1,data2; charop; scanf("%d%c%d",&data1,&op,&data2);//输入算式,运算符两侧不加空格

if(op=='+') //加法运算

{

printf("%d+%d=%d\n",data1,data2,data1+data2); } elseif(op=='-') //减法运算

{

printf("%d-%d=%d\n",data1,data2,data1-data2); } elseif(op=='*') //乘法运算

{

printf("%d*%d=%d\n",data1,data2,data1*data2); } elseif(op=='/') //除法运算

{

if(data2==0)//为避免除0错误,检验除数是否为0 {

printf("Divisionbyzero!\n"); } else { printf("%d/%d=%d\n",data1,data2,data1/data2); } } else { printf("Invalidoperator!\n"); } return0;}3.3.3开关语句1.每个case后的常量的类型应与switch后括号内表达式的类型一致,并且switch后括号内表达式的值只能为整型、字符型或枚举类型的常量。2.switch语句与break语句配合使用,才能形成真正意义上的多分支3.改变case标号出现的次序,不会影响程序的运行结果3.3.3开关语句#include<stdio.h>intmain(void){ intdata1,data2; charop; scanf("%d%c%d",&data1,&op,&data2);//输入算式,运算符两侧不加空格

switch(op) //根据输入的运算符确定执行的运算

{

case'+'://加法运算

printf("%d+%d=%d\n",data1,data2,data1+data2); break; case'-'://减法运算

printf("%d-%d=%d\n",data1,data2,data1-data2); break; case'*'://乘法运算

printf("%d*%d=%d\n",data1,data2,data1*data2); break; case'/'://除法运算

if(data2==0)//为避免除0错误,检验除数是否为0{

printf("Divisionbyzero!\n"); } else { printf("%d/%d=%d\n",data1,data2,data1/data2); } break; default://处理非法运算符

printf("Invalidoperator!\n"); } return0;}3.4循环结构3.4.1循环控制方式3.4.2计数控制的循环和for语句3.4.3条件控制的循环以及while和do-while语句3.4.4嵌套循环3.4.1循环的控制方式当型循环是先测试循环条件,后执行循环体直到型循环是先执行循环体,然后测试循环条件3.4.2计数控制的循环实现计数控制的for语句

3.4.2计数控制的循环#include<stdio.h>intmain(void){intn;intsum=0;//累加和变量初始化为0

scanf("%d",&n);for(inti=1;i<=n;i++){sum=sum+i;//做累加运算

}

printf("sum=%d\n",sum);return0;}【例3.4】从键盘输入整型变量n的值,然后计算并输出1+2+3+…+n的值。3.4.2计数控制的循环#include<stdio.h>intmain(void){ intn; scanf("%d",&n); intsum=(n%2==0)?0:(n+1)/2; for(inti=1,j=n;i<j;i++,j--) { sum=sum+i+j; } printf("%d\n",sum); return0;}【例3.5】累加求和计算的加速。4.5.2计数控制的循环#include<stdio.h>intmain(void){intn;longp=1;//因是累乘计算,故初始化为1

scanf("%d",&n);for(inti=1;i<=n;i++){p=p*i;//做累乘运算

}

printf("%d!=%ld\n",n,p);

return0;}【例3.6】从键盘输入整型变量n的值,然后计算并输出1×2×3×…×n(即n!)的值。4.5.2计数控制的循环#include<stdio.h>intmain(void){intn;longsum=0;//累加求和变量初始化为0

longp=1;//累乘求积变量初始化为1

scanf("%d",&n);for(inti=1;i<=n;i++){p=p*i;//计算累加项(即通项)

sum=sum+p;//将累乘后p的值即i!进行累加求和

}

printf("sum=%ld\n",n,p);

return0;}【例3.7】编程从键盘输入整型变量n的值,然后计算并输出1~n所有数的阶乘值(1!,2!,3!,…,n!)的累加和,即1!+2!+3!+…+n!。4.5.2计数控制的循环【例3.7】编程从键盘输入整型变量n的值,然后计算并输出1~n所有数的阶乘值(1!,2!,3!,…,n!)的累加和,即1!+2!+3!+…+n!。3.3.3条件控制的循环循环次数未知、由条件或标记值控制的循环结构,通常用while语句或do-while语句来实现。自底向上的程序设计——只猜一次intmain(void){intmagic;

intguess;

srand(time(NULL));

magic=rand()%100+1;

printf("Guessanumber:");scanf("%d",&guess);

if(guess>magic)

{printf("Wrong!Toobig!\n");}elseif(guess<magic){printf("Wrong!Toosmall!\n");}else

{printf("Right!\n");}return0;}【例3.8】猜数游戏V1.0:先由计算机“想”一个数,然后请用户猜,若用户猜对了,则计算机给出提示“正确!”,否则提示“错误!”,并告诉用户所猜的数是大还是小。自底向上的程序设计——只猜一次intmain(void){...

scanf("%d",&guess);

if(guess>magic) {printf("Wrong!Toobig!\n");}elseif(guess<magic){printf("Wrong!Toosmall!\n");}else { printf("Right!\n");}

return0;}do{

}while(guess!=magic);

counter++;printf("counter=%d\n",counter);intcounter=0;

printf("Try%d:",counter+1);【例3.9】猜数游戏V2.0:在例3.7的基础上,将游戏升级为:直到猜对为止,同时记录用户猜的次数,以此来反映用户“猜”数的水平。自底向上的程序设计——只猜一次intmain(void){...

scanf("%d",&guess);

if(guess>magic) {printf("Wrong!Toobig!\n");}elseif(guess<magic){printf("Wrong!Toosmall!\n");}else { printf("Right!\n");}

return0;}do{

}while(guess!=magic);

counter++;printf("counter=%d\n",counter);intcounter=0;

printf("Try%d:",counter+1);&&counter<10);

【例3.10】猜数游戏3.0:在例3.8的基础上,将游戏升级为:每次猜数只允许用户最多猜10次,即用户猜对了或者猜了10次仍未猜对,都结束游戏。自底向上的程序设计——只猜一次intmain(void){……intcounter=0;

return0;}【例3.11】猜数游戏V4.0:猜多个数charreply;do{

counter=0;magic=rand()%100+1;...//输出magic和counterprintf("Doyouwanttocontinue(Y/Nory/n)?");scanf("%c",&reply);}while(reply=='Y'||reply=='y');3.4.4嵌套循环4.5.2计数控制的循环【例4.8】利用单独计算累加通项的方法,编程计算1!+2!+3!+…+n!。#include<stdio.h>intmain(void){intn;longsum=0;//累加求和变量初始化为0

longp=1;scanf("%d",&n);for(inti=1;i<=n;i++)//外层循环

{

p=1;//每次循环之前都要将累乘求积变量p重新初始化为1

for(intj=1;j<=i;j++)//内层循环

{

p=p*j;//累乘求积

}

sum=sum+p;//将累乘后p的值即i!进行累加求和

}

printf("sum=%ld\n",sum); //以长整型格式输出n的阶乘值

return0;}3.5结构化程序设计与流程转移控制一个比较流行的定义是:结构化程序设计(StructuredProgramming)是一种程序设计的原则和方法它限制和避免使用goto语句,采用“自顶向下、逐步求精”方法进行程序设计按照这种原则和方法设计出的程序的特点为:结构清晰容易阅读容易修改容易验证按照结构化程序设计的要求设计出的语言——结构化程序设计语言按照结构化程序设计语言(或结构化程序设计思想)设计的程序——结构化程序结构化程序设计的目标为了得到一个好结构的程序有无goto语句,并不是程序结构好坏的标志3.5结构化程序设计与流程转移控制结构化程序设计StructuredProgrammingD.E.Knuth(图灵奖1974)12限制和避免使用goto语句采用“自顶向下逐步求精”方法进行程序设计采用顺序、选择和循环三种基本控制结构作为程序设计的基本单元34严格遵循“单入口单出口”的原则,无死循环,无死语句结构清晰容易阅读容易修改容易验证原则方法特点3.5结构化程序设计与流程转移控制1.goto语句的利与弊尽量避免使用goto语句,尤其是不要使用过多的goto语句标号(最多1个),因为过多的goto语句标号会破坏程序的“单入口、单出口”结构。为避免使用过多goto语句标号导致的程序结构混乱,一般只允许在一个“单入口、单出口”的模块内部使用goto语句向下跳转,不允许回跳,尤其不允许交叉使用goto语句通常,仅如下两种情形可以使用goto语句:(1)跳出多重循环。goto语句是快速跳出多重循环的一条捷径。(2)跳向共同的出口位置,进行退出前的错误处理工作。这样,将所有错误都指向同一个标号处的语句来处理,可以使程序结构更清晰,且代码更集中。3.5结构化程序设计与流程转移控制2.break语句的利与弊break语句只对包含它的最内层循环语句起作用,不能跳出多重循环。3.5结构化程序设计与流程转移控制3.continue语句的利与弊3.5结构化程序设计与流程转移控制3.continue语句的利与弊在大多数情况下,for循环和while循环可进行语义等价的相互转换,但当循环体中存在continue语句时,将for循环转换为while循环,二者有可能不等价。3.5结构化程序设计与流程转移控制3.6学习AI编程的首要任务——清晰地表达需求学习AI编程首先要学会清晰准确地表达问题和需求。这个过程就像点外卖一样,不能只是简单地说:“我要点一个宫保鸡丁,请送到xx学校门口”,这样说就很模糊以计算你的课程平均分为例,可以将需求梳理成如下三个步骤:(1)输入:从键盘输入你的各门课程的成绩。(2)处理:先计算总分,然后除以课程门数,得到平均分。(3)输出:将计算出的平均分输出到屏幕上。本章思维导图Thankyouforyourattention!Q&A第4章函数与模块化程序设计哈尔滨工业大学4.1模块化程序设计CBCCAB自底向上(Down-top)ABCCABA1A2B1B2C1C2自顶向下(Top-down)先写出结构简单、清晰的主程序来表达整个问题在此问题中包含的复杂子问题用子程序或函数来实现若子问题中还包含复杂的子问题,再用子程序或函数实现直到每个细节都可用高级语言表达为止上:比较抽象的层面下:更具体的层面接近程序设计语言规模增大问题简单规模较小构造分解4.1模块化程序设计逐步求精(StepwiseRefinement)对问题的全局做出决策,设计出对问题本身较为自然的、很可能是用自然语言表达的抽象算法由一些抽象数据及其上的操作(即抽象语句)组成,仅仅表示解决问题的一般策略和问题解的一般结构对抽象算法进一步求精,就进入下一层抽象每求精一步,抽象语句和抽象数据都将进一步分解和精细化如此继续下去,直到最后的算法能为计算机所“理解”为止易于用某种高级语言表达4.1模块化程序设计简而言之先全局后局部、先整体后细节、先抽象后具体的自顶向下方法实际程序开发过程不是纯粹的自顶向下和自底向上自顶向下的分解和自底向上的构造两个过程混合交织进行由不断的自底向上修正所补充的自顶向下的程序设计方法优点得到的程序是有良好结构的程序可简化程序的正确性验证结合逐步求精过程,采取边设计边逐级验证的方法与写完整个程序后再验证相比,可大大减少程序调试的时间4.1模块化程序设计模块分解应遵循的基本原则是保证每个模块的相对独立性(ModuleIndependence),衡量模块独立性程度的标准主要是看如下两个标准:(1)内聚度(Cohesion):内聚度,也称聚合度或聚合性,是指每个模块内各个元素(例如语句、程序段等)之间联系的紧密程度,它是模块内的元素之间的关联程度或聚合能力的度量。模块内各个元素之间的联系越紧密,则其内聚度越大,模块独立性就越强,系统就越容易理解和维护。(2)耦合度(Coupling):耦合度,也称关联度或耦合性,是指不同模块之间相互联系的紧密程度,它是模块之间关联程度(即依赖关系,或者说接口复杂性)的一种度量。模块之间的依赖关系包括控制关系、调用关系、数据传递关系。耦合度是从模块外部考察模块的独立性程度。耦合度的强弱取决于模块间接口的复杂性、调用模块的方式以及通过接口传送数据的多少。【例4.1】按照模块化程序设计方法设计猜数游戏,游戏的要求为:显示一个菜单,让用户选择游戏的方式:(1)选择1,则只猜一个数次;(2)选择2,则直到猜对为止猜多个数,直到用户选择0退出为止;(3)选择3,则最多猜10次;(4)选择0,退出游戏。其中,猜每一个数的方式有三种:只猜一次,直到猜对为止,最多猜10次。4.1模块化程序设计4.1模块化程序设计4.1模块化程序设计【例5.6】按照模块化程序设计方法重新设计猜数游戏。intmain(void){intmagic;//计算机“想”的数

charchoice='\0';//将保存用户选择的变量初始化为ASCII码值为0的空字符

while(choice!='0')//只要用户不选0,就继续猜下一个数

{

计算机生成一个随机数显示一个固定式菜单并返回用户的选择

switch(choice)//判断用户选择的是何种操作

{

case'1':

用户猜数,只猜一次

break;case'2':

用户猜数,直到猜对为止

break;case'3':

用户猜数,最多猜10次

break;case'0':

提示游戏结束

break;default:

提示输入数据错误}}

return0;}至少需要设计下面5个子模块:(1)计算机生成一个随机数(2)显示一个固定式菜单并返回用户的选择(3)用户猜数,只猜一次(4)用户猜数,直到猜对为止(5)用户猜数,最多猜10次从上述对应三种游戏方式的三个模块中进一步提炼出两个公共子任务,按执行顺序划分再抽象出3个子模块:(1)输入用户猜的数(2)对用户猜对与否做出决策其中,“输入用户猜的数”子模块可直接调用scanf()函数来实现输入用户猜的数,其它子模块要用户自定义函数来实现。4.1模块化程序设计4.2函数的定义用户自定义函数的基本语法格式为:4.2函数的定义【例4.2】将例4.1猜数游戏实例中按功能划分的如下两个子模块定义为函数。(1)显示一个固定式菜单并返回用户的选择(2)计算机生成一个随机数4.2函数的定义#include<stdio.h>//调用printf()和scanf()所需包含的头文件//函数功能:显示菜单并返回用户的选择charMenuSelection(void){charchoice;//用户的选项

printf("1.GuessOnce\n");printf("2.Guessuntilright\n");printf("3.Guessuptotentimes\n");printf("0.Exit\n");printf("Inputyourchoice:");scanf("%c",&choice);//注意这里%c前面有个空格,避免读入前面的回车

returnchoice;}charMenuSelection(void){charchoice;//用户的选项

printf("1.GuessOnce\n");printf("2.Guessuntilright\n");printf("3.Guessuptotentimes\n");printf("0.Exit\n");printf("Inputyourchoice:");scanf("%c",&choice);//注意这里%c前面有个空格,避免读入前面的回车

returnchoice;}7.2.2函数的定义函数名标识符形参表,函数的入口,接收调用者传入的参数函数的出口,只能返回一个值给调用者函数体的定界符函数体—函数功能的主体实现部分返回值类型,与实际返回的变量类型一致4.2函数的定义#include<time.h>//调用time()所需包含的头文件#include<stdlib.h>//调用rand()所需包含的头文件#defineMAX_NUMBER100//计算机生成的随机数的上限#defineMIN_NUMBER1//计算机生成的随机数的下限//函数功能:计算机生成并返回一个随机数intMakeNumber(void){srand(time(NULL));//为函数rand()设置随机数种子

intmagic=(rand()%(MAX_NUMBER-MIN_NUMBER+1))+MIN_NUMBER;returnmagic;}【例4.3】将例4.1猜数游戏实例中按功能划分的如下4个子模块定义为函数。(1)用户猜数,只猜一次(2)用户猜数,直到猜对为止(3

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论