为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > 雄县济康医院专家解答哪些孕妇易出现早产

雄县济康医院专家解答哪些孕妇易出现早产

2013-11-22 1页 doc 12KB 20阅读

用户头像

is_624840

暂无简介

举报
雄县济康医院专家解答哪些孕妇易出现早产C语言程序设计Copyer:Vigiking第一章计算机语言与C语言概述1.1计算机语言概念■计算机语言定义计算机能够识别和接受的语言。要使计算机按自己的意图工作,必须使用计算机所能接受、理解和执行的指令指挥计算机工作。■计算机语言的种类机器语言低级语言汇编语言(面向计算机)BASIC入门语言F77科学计算高级语言Foxpro数据库管理(面向问题)C多用途计算机语言…………•机器语言最早问世,用二进制代码构成指令。如:100000(+)110000(-)用机器语...
雄县济康医院专家解答哪些孕妇易出现早产
C语言程序设计Copyer:Vigiking第一章计算机语言与C语言概述1.1计算机语言概念■计算机语言定义计算机能够识别和接受的语言。要使计算机按自己的意图工作,必须使用计算机所能接受、理解和执行的指令指挥计算机工作。■计算机语言的种类机器语言低级语言汇编语言(面向计算机)BASIC入门语言F77科学计算高级语言Foxpro数据库管理(面向问题)C多用途计算机语言…………•机器语言最早问世,用二进制代码构成指令。如:100000(+)110000(-)用机器语言编程的缺点:─繁琐、不直观、不易调试。如计算y=2x2+3x-1需要七八条指令。─移植性差。依赖于计算机。•汇编语言用符号构成指令,如:MOV、ADD用汇编语言编程:相对直观,但仍繁琐,仍是面向计算机的语言。汇编语言是计算机间接接受的语言•高级语言与低级语言相比,有根本性的区别:是面向问题的语言。高级语言的一条指令(语句):y=2*x*x+3*x-1;对应于:y=2x2+3x-1y=sin(x);对应于:y=sinx用高级语言编程:直观、易懂、移植性好(不依赖于具体计算机)上机运行高级语言程序需经过编译:编译执行 要上机完成一个计算问题,主要的任务就是用高级语言编写出相应的源程序。即至少要学会一种计算机语言。 高级语言源程序机器指令目的程序结果编译程序1.2C语言的特点集高级语言和低级语言的优点于一身:●能实现低级语言的大部分功能(如直接访问内存物理地址、进行位操作等)。●图形功能强。●运算符和数据结构丰富。●语法限制不太严格,程序设计自由度大。●生成目标代码质量高,程序执行效率高。1.3简单的C程序介绍例1:main()主说明{程序框架printf(“abcdef”);函数体}语句程序的功能是输出字符串:abcdef例2:求两数之和。main(){inta,b,c;aa=100;b=50;bc=a+b;cprintf(“\nc=%d”,c);}程序运行结果:c=150例3:求两数中的最大值。函数类型函数名形参main()intmax(intx,inty){inta,b,c;{intz;scanf(“%d,%d”,&a,&b);if(x>y)z=x;c=max(a,b);elsez=y;printf(“\nmaxis:%d”,c);return(z);}}axbycz(两个函数组成)353555总结上例可知:(1)C程序由函数构成。(2)函数由两部分组成:函数说明部分:函数名、函数类型、形参名、形参类型。函数体:实现函数的具体操作;由语句构成。(3)程序总是从main函数开始执行。(4)自由。(5)语句必须有分号。:第二章算法2.1算法的概念要利用计算机处理问题,光学习语言的语法规则还不够,最重要的是要学会针对各类型的问题,拟定出有效的解题方法和步骤。解题方法和步骤就是算法。算法:为了解决一个问题而采取的有限步骤。计算机算法:如何使计算机一步一步地工作的具体过程。利用计算机处理问题的步骤:1)设计好算法——算法设计;2)用计算机语言实现算法——程序设计。算法必须是“有效”的。算法设计还要充分考虑算法的好坏。衡量算法好坏的主要标准:①程序简练。②执行速度快。③占空间少。例:考虑的算法。算法①:直接表达。直接用语句s=1+2+3+4+5+6+7+8+9+10当项数较多时该算法不适用s=∑i110算法②:迭代法(累加求和法)s=1+2+3+4+5+6+7+8+9+10算法步骤:si ①使s=0+②使i=1累加器记数器③s+i→s④i+1→i⑤若i≤10转③,否则转⑥⑥输出s01123364105该算法通用,是好算法2.2算法的表示算法需要有统一的表示方法常用的表示方法有:自然语言流程图结构化流程图N-S流程图.1、自然语言对于计算s=1+2+3+4+5+6+7+8+9+10用自然语言表示为:①    使s=0(s为累加器)②    使i=1(i为计数器)③    s+i→s(累加求和公式)④    i+1→i(计数器加1)⑤    若i≤10转③,否则转⑥⑥输出s的值特点:通俗易懂、文字冗长、含义不大严格。2、流程图用流程图符号表示算法。常用的流程图符号起止框输入输出框处理框流程线判断框对于计算s=1+2+3+4+5+6+7+8+9+10用流程图表示为:s+i→si+1→iS+i→sS+i→si≤10输出s0→s1→i直观形象,易于理解,次序清楚YN3、结构化流程图传统的流程图有一个弊端:对流程线没有严格的限制,对于较复杂的算法可能会变成乱麻一般(BS型算法)。为克服这一弊端,提出了由三个基本结构组成算法流程图的思想:结构化流程图三个基本结构:① 顺序结构按固定顺序(从上到下或从左到右)执行的结构。ABab   ② 选择结构根据条件P选择执行哪一个分支。成立不成立pABab成立不成立例:计算y=1/x当x≠0时y=10000当x=0时的算法流程图图:选择结构输入xX=0?10000→y1/x→y输出yYN③ 循环结构重复执行某些操作的结构。分为两种:当型循环和直到型循环。当型循环直到型循环P1AAP2aabbYYNN可以看出,每个基本结构都只有一个入口和一个出口,因此,用三个基本结构构成的流程图不会象乱麻一般,用三个基本结构构成的流程图就成为结构化流程图,用结构化流程图描述的算法称为结构化算法,相应的程序设计就称为结构化程序设计。观察前例:0→s1→iS+i→si+1→ii≤10输出s顺序结构循环结构yn4N-S流程图N-S流程图的三个基本结构:ABP成立不成立ABAB当P1直到P2顺序结构选择结构循环结构例:计算y=1/x当x≠0时y=10000当x=0时的N-S流程图: 输入xX=0?是否10000→y1/x→y输出y例:计算s=1+2+3+4+5+6+7+8+9+10的N-S流程图:i≤10直到i>10直到型当型0→s1→i输出s1→i0→ss+i→si+1→is+i→si+1→i输出s第三章数据类型、运算符与表达式3.1C的数据类型●基本类型(整型、实型、字符型、枚举型)●构造类型(略)●指针类型(略)●空类型各类型包含常量与变量3.2常量与变量■常量与符号常量常量在程序运行过程中其值保持不变的量。符号常量用来代表一个常量的标识符。#definePI3.1415926例:#definePI3.1415926main(){floatr=2,c;c=2*PI*r;printf(“%f”,c);}■变量其值可以改变的量。变量的三要素: ①  变量名每个变量有一个名字,作为识别该变量的标识符。②变量的值每个变量有一个值,变量的值是随时可以改变的。 ③变量的存储单元每个变量占据一个内存单元,用于存放变量的值。变量名a变量值存储单元 3变量的命名规则:由字母、数字和下划线组成以字母或下划线开头a、x1、y_2、_b1、_1c合法1x、a+2、Ф、Ω不合法变量必须先定义后使用。程序中何时使用常量?何时使用变量?3.3整型数据■整型常量即整常数,c的整常数有三种形式:①十进制整数与数学中的整数一致,如:100,123,15等。 ②八进制整数以0开头的整数,如:010,07,020等。 ③十六进制整数以0x开头的整数,如:0x10,0xff,0x2a等。■整型变量用于存放整数的变量。分4种类型:①基本型:inta16位,可表示的数值范围:-32768—32767②短整型:shortintb16位,可表示的数值范围:-32768—32767③长整型:longintc32位,数值范围:-2147483648—2147483647④无符号型:加上unsigned只存放正数。如:unsignedintx变量x为无符号整数,16位全表示数码,数值范围:0—65535在程序设计中,如果要使用整型变量,必须首先选择以上类型符来定义变量,然后才能使用;例:main()定义{inta,b,c;a=100;b=50;使用c=a+b;printf(“%d”,c);}一般根据什么原则选择变量的类型?3.4实型数据■实型常量可使用两种形式表示:①小数形式:如1.23,3.141592615.48②指数形式:如1e-201.23e5■实型变量用于存放实数的变量分单精度和双精度两种:floata,b定义a和b为单精度型变量32位,7位有效数字,10-38—1038doublex,y定义x和y为双精度型变量64位,15位有效数字,10-308—10308例:main(){floatr,c;doubler,c;r=5;c=2*3.1415926*r;printf(“%f”,c);}3.5字符型数据■字符常量用单引号括起来的一个字符。’a’,’x’,’*’,’1’等除此外,以’\’开头的字符如’\n’,’\t’等称为转义字符,祥见书表3.3■字符型变量用于存放字符的变量。charc1,c2定义c1和c2为字符型变量c1=’a’;c2=’b’;字符赋值字符型变量存放一个字符,占据一个字节■字符型数据的存储形式存放ASCII码不是而是如字符’a’在内存中存放97,’b’存放98。与整数的存储形式一致,它们之间可以通用一个字符数据既可以作字符用,也可以作整数用(取其ASCII代码)。如:32+’a’相当于32+97若intx;charc;则x=’a’;c=97;x=97;c=’a’;都允许a97■字符串常量用双引号括起来的字符序列。如:”abcde”,”china””a”也属字符串。注意”a”与’a’的区别。对于:charc;c=”a”;用法错误字符串中每个字符各占一个字节,并且在字符串结尾加上一个结束标记’\0’如:”china”在内存中占6个字节。 china\0C语言中专门的字符串变量,可用字符数组存放(以后介绍)。3.6变量赋初值在定义变量的同时给相应的变量赋初值。如:inta=3;afloatb=5.2;charc=’a’;intx=y=z=6;效果:在给变量分配内存单元的同时在相应的单元中存放初值。33.7各数值型数据间的混合运算整型、实型、字符型数据间可以进行混合运算,如:10-‘a’*1.5运算时,参加运算的两个数据如果类型不同,则首先将其类型转换成一致再运算,转换规则是:将优先级低的类型转换到优先级高的类型数据类型的优先级:高doublefloatlongunsignde低intchar3.8算术运算符与算术表达式■基本的算术运算符+-*/%■算术表达式用算术运算符将运算对象连接起来的式子用于表达数学公式的式子如:2*x+y-1/a表达式经过运算最终得到一个值:算术表达式的值■运算符的优先级与结合性优先级:在对表达式求值时,如果存在多个运算符,则运算的先后次序按运算符的优先级别从高到底进行。运算符的优先级关系为:高:*/%低:+-如:a-2*x先算*2*(a+2)有括号的情况?结合性:如果在一个运算对象两边的运算符的优先级相同,则按规定的“结合方向”处理。如:a-b+cb与-结合是从左到右,称“左结合性”。b与+结合是从右到左,称“右结合性”。每个运算符都有相应的优先级和结合性。基本算术运算符都是左结合性。计算表达式例:2+’A’-1/2.01+3/2-1构造表达式例2x2+3x-1  a+ba-ba+ba-bx+yx-ya+b/a-b?(a+b)/(a-b)2*x*x+3*x-1(*不能省)(a+b)/(a-b)/(x+y)/(x-y)(a+b)/(a-b)/((x+y)/(x-y))(a+b)/(a-b)/(x+y)*(x-y)■强制类型转换可以用强制类型转换运算符将一个表达式的值转换成所需类型:如:(int)(x+y)(float)(7%3)应用举例:inta=200,b=300,c;c=a*b/100;?可知,有自动转换和强制转换,当自动转换达不到目的时,可用强制转换。c=(long)a*b/100;c=(long)(a*b)/100;■自增、自减运算符自增运算符:++使变量值加1自减运算符:--使变量值减1两种用法:++i,--i先加(减)后用i++,i--先用后加(减)两种用法对i效果一样,但表达式的值不同。例:假设i的原值为5:j=++i;j=?j=i++;j=?注意:●++和--只能用于变量。如:3++和(a+1)++不合法●++和--为右结合性。(-i)++-i++-(i++)  若i的原值是5,则该表达式的值是多少?例:分析执行下列语句后的结果:a=5;abcd b=a++;c=--a-b++;d=(a++)-(++b)+c--; 5565067-26-1两种特殊情况:①k=(i++)+(i++)+(i++)②i+++j是i+(++j)还是(i++)+j?i++虽然与i=i+1等效,但使用自增自减运算符的代码优化程度好,因而经常使用;但用时需特别小心。3.9赋值运算符和赋值表达式■赋值运算符“=”称赋值运算符,其作用是将一个数据赋给一个变量。如:a=5不要理解为“等号”。执行赋值运算的结果,是将右边的数据存入左边变量所对应的内存单元中。■赋值规则如果赋值运算符两侧的类型不一致,则在赋值时要进行类型转换,转换规则为:●实型→整变量舍去小数部分。inta=5.5;a中为5。●整型→实变量数值不变,以浮点形式存储。●字符型→整变量放在整形变量低8位。保持原值不变原则。inta=‘A’;■复合赋值运算符在赋值运算符前加上其它运算符,可以构成复合赋值运算符。a+=3——a=a+3b-=x+5——b=b-(x+5)x*=c-6——x=x*(c-6)y/=a*4——y=y/(a*4)k%=b-2——k=k%(b-2)属于高效率运算符。■赋值表达式主要实现赋值运算的表达式。一般形式:<变量>=<表达式>如:a=5y=2*x+3a=a+1不是衡等作用:将右边表达式的值赋给左边的变量。赋值表达式的值取左边变量的值。赋值表达式右边的<表达式>可以是任何表达式,如:a=(b=5)赋值表达式中包含赋值表达式赋值运算符的优先级低于所有算术运算符,且是右结合性。a=(b=5)与a=b=5等效。例:计算以下表达式的值:a=b=c=5a=5+(c=6)a=(b=4)+(c=6)a=(b=4.5)+(c=6.5)(a、b、c为整型变量)a+=a-=a*a(设a的原值为3)赋值表达式是C语言中的一个重要成分,在赋值表达式后加一分号就成为常用的赋值语句。如y=2*x+1;赋值表达式作为表达式的一种,可以出现在任何表达式中,如:x+2-(b/3-(a=k-5)+’b’3.10逗号表达式逗号也是一种运算符,用它对两个表达式实现连接运算。3+5,6+8称逗号表达式。逗号表达式的一般形式:表达式1,表达式2取表达式2的值作为整个逗号表达式的值。如:a=3*5,a*4逗号表达式的值为:60一个逗号表达式又可以与另一个表达式组成一个新的逗号表达式,如:(a=3*5,a*4),a+5因此,逗号表达式的一般形式可以扩展为:表达式1,表达式2,表达式3,……,表达式n取表达式n的值作为整个逗号表达式的值。逗号运算符的优先级最低,且是左结合性。逗号运算符只起到连接作用,没有实际操作。第四章最简单的C程序设计C程序最基本的成分是语句目前我们已掌握的语句:变量说明语句:inta,b,c;表达式语句:x+y;特别地:a=5;赋值语句可以编写简单程序如:main(){intx,y;x=5;y=2*x*x+3*x-1;}该程序语法上完整,但还缺少输出。■数据的输出用输出函数实现,其中的两种输出函数:1.putchar函数(字符输出函数)用于输出一个字符。如:putchar(‘a’);putchar(100);charc=’b’;putchar(c); 例:输出单词Boy的完整程序:#include“stdio.h”注意该语句的作用main(){chara,b,c;a=’B’;b=’o’;c=’y’;putchar(a);putchar(b);putchar(c);}2.printf函数(格式输出函数)任意类型、任意格式、任意个数。例如:inta=100,b=56;printf(“a=%d,b=%d”,a,b);普通字符格式说明格式控制输出表列输出结果:a=100,b=56“%”后的字符称格式字符,不同格式字符对应不同的数据类型。d格式符:按整数格式输出几种用法:%d不指定宽度,按实际宽度输出%md按指定宽度输出,m为宽度%ld用于输出长整型数例:inta=125,b=453;longc=65535;printf(“a=%d,b=%5d,c=%ld”,a,b,c);输出结果:a=125,b=453,c=65535%ld也可以按指定宽度输出:printf(“c=%8ld”,c);输出结果:c=65535注意:格式字符的类型要与对应的输出对象的类型一致。c格式符:用于输出字符charc=’A’;printf(“c=%c,%c”,c,’B’);输出结果:c=A,B输出对象既可以是字符变量、字符常量,还可以是整型表达式。 如:inta=100;charb=’A’;printf(“\n%d,%c”,a,a);printf(“\n%c,%d”,b,b);输出结果:100,dA,65s格式符:用于输出字符串 %s不指定宽度 %-ms指定宽度,左靠齐 %ms指定宽度,右靠齐 %m.ns指定宽度m,只取左端n个字符, 右靠齐 %-m.ns指定宽度m,只取左端n个字符, 左靠齐例:printf(“1:%s”,”abcd”);printf(“2:%8s”,”abcd”);printf(“3:%-8s”,”abcd”);printf(“4:%8.3s”,”abcd”);printf(“5:%-8.3s”,”abcd”);1:abcd2:abcd3:abcd4:abc5:abcf格式符:按小数形式输出实数 %f由系统指定宽度(6位小数) %m.nf指定宽度m,小数位数n,右靠齐 %-m.nf指定宽度m,小数位数n,左靠齐 注意:宽度包括符号和小数点。例:floata=3.141592654,b=14.326795,c=-125.2468;printf(“\na=%f,b=%8.3f,c=%-10.2f”,a,b,c);输出结果:a=3.141592,b=14.326,c=-125.24完整前面的程序:main(){intx,y;x=5;y=2*x*x+3*x-1;printf(“\ny=%d”,y);}程序设计例:编写程序计算如图中的电流I.    假设U=220,R1=30,R2=60,R3=45UIR1R2R3算法设计:I=U/R1+U/R2+U/R3程序设计:main(){ }I=U/R1+U/R2+U/R3;intU=220,R1=30,R2=60,R3=45;floatI;printf(“\nI=%f”,I);正确的程序:main(){intU=220,R1=30,R2=60,R3=45;floatI;I=(float)U/R1+(float)U/R2+(float)U/R3;printf(“\nI=%f”,I);}考虑通用:main(){intU,R1,R2,R3;floatI;输入U,R1,R2,R3I=(float)U/R1+(float)U/R2+(float)U/R3;printf(“\nI=%f”,I);}■数据的输入getchar函数(字符输入)#include“stdio.h”main(){charc;c=getchar();等待键盘输入putchar(c);}scanf函数(格式输入)与printf函数相反。用于输入若干任意类型的数据。scanf(“%d%d%d”,&a,&b,&c);格式控制地址列表  scanf(“%d%d%d”,&a,&b,&c);执行此函数时,等待从键盘输入三个整数给a,b,c若从键盘输入358则系统即从键盘缓冲区取出这三个数分别赋给a,b,c注意与printf的区别,注意格式的匹配如:scanf(“%3d%2d%4d”,&a,&b,&c);若从键盘输入123456789a=123,b=45,c=6789若想使a=12,b=5,c=100则键盘输入应为:125100方便的输入格式一般不指定宽度,如:scanf(“%d%d%d”,&a,&b,&c);在键盘输入时,用分隔符把每个数据隔开,标准的分隔符是空格。如:12315023若想用逗号作分隔符,则:scanf(“%d,%d,%d”,&a,&b,&c);不要随便使用普通字符,如使用:scanf(“a=%d,b=%dc=%d”,&a,&b,&c)对应数据输入:a=123,b=150,c=23前面的欧姆定律:main(){intU,R1,R2,R3;floatI;scanf(“%d%d%d%d”,&U,&R1,&R2,&R3);I=(float)U/R1+(float)U/R2+(float)U/R3;printf(“\nI=%f”,I);}求三角形面积#include“math.h”main(){floata,b,c,area,s;scanf(“%f,%f,%f”,&a,&b,&c);s=1.0/2*(a+b+c);area=sqrt(s*(s-a)*(s-b)*(s-c));printf(“\narea=%f”,area);}使用数学函数使用三角函数#include“math.h”main(){floatx,y;scanf(“%f”,&x);y=sin(x*3.1415926/180);以弧度为单位printf(“\ny=%f”,y);}第五章  选择结构程序设计对于如下的函数计算,算法上属于一个选择结构。y=用于实现选择结构的主要是if语句。1/x当x≠0时10000当x=0时if语句的最常见形式为:if(关系表达式)语句1;else语句2;如:if(x!=0)y=1/x;elsey=10000;其中x!=0就是一个关系表达式!=就是一个关系运算符5.1关系运算符和关系表达式1、关系运算符用于进行比较运算的运算符。共有六种:<<=>>===!=■优先级与结合性:①前4种大于后两种。②低于算术运算符而高于赋值运算符。③左结合性。2、关系表达式一般形式:〈表达式〉〈关系运算符〉〈表达式〉如:a>ba+b>b+c经过关系运算后最终有一个值--关系表达式的值。关系表达式的值只有0(假)或1(真)例:设a=2,b=4,c=1计算以下关系表达式的值:a>ba+b>b+c‘a’>’b’可以是字符表达式(x=2)>(y=5)可以是赋值表达式(a<b)>(b<c)甚至可以是关系表达式a<b==b<c例:假设x=3,y=5,z=1,计算以下关系表达式的值:x+z>yx<y==y<zy>z==x>zy>x>z(x==y-2)<z+1==x+ya=x+y==x+z<y+x!=z+1>x+15.2逻辑运算符和逻辑表达式有时,只用一个简单的关系表达式无法完整地表达一个条件,如:y=其中的条件需要用逻辑表达式来表达:x!=0&&a!=0&&就是一种逻辑运算符。1/x+1/a当x≠0,a≠0时10000其它1、逻辑运算符&&逻辑与两个操作数都为真时&&运算结果为真。||逻辑或两个操作数之一为真时即为真。!逻辑非(单目运算)操作数为真(假)时为假(真)。如:若a=2,b=3,c=0则:a<b&&b<c0a<b||b<c1!(a<b)0■优先级(由高到低):!逻辑非算术运算符关系运算符&&逻辑与||逻辑或赋值运算符■结合性:左结合性2、逻辑表达式实际上,前面所举例子即为逻辑表达式:a<b&&b<ca<b||b<c!(a<b)逻辑表达式的值同样只有1和0,但参加逻辑运算的操作数可以是任意类型的数据,可以是任意大小。例:a+b&&b+c是合法的逻辑表达式。此时以0代表假,非0代表真。例:设a=2,b=3,c=0,计算以下表达式的值:a&&bb&&ca||c!a+c&&b+c!c+a==b||b<aa+c||a+b>c+10对于逻辑表达式的两种基本技能:①逻辑表达式的计算。②逻辑表达式的构造。逻辑表达式的构造举例:a≥b≥ca和b之一为0,但不同时为0a>=b>=c5>=4>=3a>=b&&b>=ca==0&&b!=0||a!=0&&b==0a*b==0a*b==0&&a+b!=0对于a==0&&b!=0||a!=0&&b==0a==0可以用!a代替a!=0可以直接用a!a&&b||a&&!b但必须是运算结果作为逻辑量的情况下。y=(a!=0)与y=a不等效5.3if语句1、if语句的三种形式①  if(表达式)语句;有一分支为空。scanf(“%d”,&score);if(score>=60)printf(“pass”); ② if(表达式)语句1;else语句2;if(x!=0)y=1/x;elsey=10000; ③ if(表达式1)语句1;elseif(表达式2)语句2;elseif(表达式3)语句3;┇else语句n;if(score==100)printf(“A”);elseif(score>=90)printf(“B”);elseif(score>=80)printf(“C”);elseif(score>=70)printf(“D”);elseif(score>=60)printf(“E”);elseprintf(“F”);对于:  1/x当x≠0时10000当x=0时一般用:if(x!=0)y=1/x;elsey=10000;也可用:y=10000;if(x!=0)y=1/x;y=?y=1/x;if(x==0)y=10000例:(习题5.5):x(x<1)2x-1(1≤x<10)3x-11(x≥10)y=main(){floatx,y;scanf(“%f”,&x);if(x<1)y=x;elseif(x<10)y=2*x-1;elsey=3*x-11;printf(“\ny=%f”,y);}说明:① 语句中的表达式可以是任意表达式:if(x)y=1/x;elsey=10000;②一个if结构不可分割:if(x)y=1/x;z=10;elsey=10000;③一个分支中包含多个语句时,要用{}:if(a<0){x=1;y=2;}else{x=10;y=20;}分支程序设计举例(基本技巧和算法)例:从键盘输入三个整数到变量a,b,c,输出其中最大的数。两种典型算法:①枚举法(将各种可能性枚举出来)。②选择法(先假设后判断更新)。选择法main(){inta,b,c,max;scanf(“%d,%d,%d”,&a,&b,&c);max=a;if(b>max)max=b;if(c>max)max=c;printf(“\nmax=%d”,max);}}例:从键盘输入三个整数到变量a,b,c,要求按从大到小的顺序输出。两种典型算法:①枚举法(将各种可能的排列枚举出来)。②换位法(将a,b,c中的数据换位)。换位法main(){inta,b,c,t;scanf(“%d,%d,%d”,&a,&b,&c);if(a<b){t=a;a=b;b=t;}if(a<c){t=a;a=c;c=t;}if(b<c){t=b;b=c;c=t;}printf(“\n%d,%d,%d”,a,b,c);}}358538553abc2、if语句的嵌套在if语句中,又包含一个或多个if语句:if(score>=80)if(score>=90)printf(“A”);elseprintf(“B”);elseif(score>=60)printf(“C”);elseprintf(“D”);注意else与if的匹配3、条件运算符如果两个分支的内容都是给同一个变量赋值,则可用简单的条件运算符处理:if(a>b)max=a;elsemax=b;可用:max=a>b?a:b;赋值运算符右边为一条件表达式。条件表达式的一般形式:表达式1?表达式2:表达式3条件表达式的执行过程:a>b?a:b      优先级:低于关系运算符,高于赋值运算符。结合性:右结合性。 表达式1条件表达式取表达式3的值条件表达式取表达式2的值非00例:求a,b,c中的最大值:max=a>b?(a>c?a:c):(b>c?b:c);5.4switch语句(多分支)适用于根据一个表达式的值就可确定走哪个分支的情况。switch(表达式){常量表达式1:语句1常量表达式2:语句2┋常量表达式n:语句ndefault:语句n+1}例:成绩分档:switch(score/10){case10:printf(“A”);case9:printf(“B”);case8:printf(“C”);case7:printf(“E”);case6:printf(“F”);default:printf(“G”);}注:应使用break.switch(score/10){case10:printf(“A”);break;case9:printf(“B”);break;case8:printf(“C”);break;case7:printf(“E”);break;case6:printf(“F”);break;default:printf(“G”);}5.5程序举例(习题5.10)有4个圆塔,圆心分别为:(2,2),(-2,2),(-2,-2),(2,-2),圆半径为1。这4个塔的高度为10m,塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为0)。算法设计:条件“在某一圆内”:“在圆1内或在圆2内或在圆3内或在圆4内”若设变量c1、c2、c3、c4分别代表是否在相应的圆内,则以上条件为:c1||c2||c3||c4 10在某一圆内0在圆外(x,y)h=c1=(x-2)2+(y-2)2≤1c2=(x+2)2+(y-2)2≤1c3=(x+2)2+(y+2)2≤1c4=(x-2)2+(y+2)2≤1main(){inth,c1,c2,c3,c4;floatx,y;scanf(“%f%f”,&x,&y);c1=(x-2)*(x-2)+(y-2)*(y-2)<=1;c2=(x+2)*(x+2)+(y-2)*(y-2)<=1;c3=(x+2)*(x+2)+(y+2)*(y+2)<=1;c4=(x-2)*(x-2)+(y+2)*(y+2)<=1;if(c1||c2||c3||c4)h=10;elseh=0;printf(“\nh=%d”,h);}          第六章循环控制6.1概述所谓循环控制,就是如何实现循环结构的控制问题。有4种方法:① 用goto语句和if构成循环。② 用while语句。③ 用do-while语句。④ 用for语句。6.2用goto语句和if语句构成循环例:对于计算s=1+2+3+4+5+6+7+8+9+100s1is+i→si+1→ii≤10输出syns=0;i=1;lable:s+=i;i++;if(i<=10)gotolable;printf(“%d”,s);语句标号无条件转向语句goto语句可以构造循环,但不主张用,因为它容易破坏结构化程序设计。goto语句可以构造循环,但不主张用,因为它容易破坏结构化程序设计。6.3while语句while语句是专门用于实现循环控制的语句之一。其一般形式为:while(表达式)语句含义:当表达式的值为非0时,执行循环体,否则执行后续语句。语句关键表达循环条件的表达式循环体语句关键字执行过程:while(表达式)语句表达式循环体0非0i≤10?s=0i=1s=s+ii=i+1例:用while语句实现前面算法:main(){inti=1,s=0;while(i<=10){s=s+i;i++;}printf(“\n%d”,s);}注意与if语句的区别。循环体中要有使循环条件趋于成立的条件ynwhile(i<=10){s=s+i;i++;}可简写为:while(i<=10)s+=i++;非0(真)0(假)表达式循环体6.4do-while语句do-while语句主要用于实现直到型循环。其一般形式为:do循环体while(表达式);执行过程:真s=0i=1i≤10?s=s+ii=i+1假例:用do-while语句实现前面算法:main(){inti=1,s=0;dos+=i++;while(i<=10);printf(“\n%d”,s);}注意与while语句的区别。假表达式2求解表达式1循环体求解表达式3真6.5for语句for语句是一种使用最为灵活,并且是用得最多的循环控制语句,其一般形式为:for(表达式1;表达式2;表达式3)循环体大体含义:对于()的情况执行循环体内容。例:用for语句实现前面的算法:s=0;for(i=1;i<=10;i++)s+=i;标准形式表达式1表达式2表达式3循环体可以理解:循环变量i从初值1开始到终值10,步长为1,重复执行循环体。for语句的常见变化:s=0;i=1;for(;i<=10;i++)s+=i;s=0;for(i=1;i<=10;)s+=i++;s=0;i=1;for(;i<=10;)s+=i++;省略表达式1省略表达式3省略表达式1和3 s=0;i=1;for(;;){s+=i++;if(i>10)break;}s=10;i=10;for(;--i;)s+=i;省略表达式2表达式2是任意表达式 s=0;for(i=1,j=10;i<j;i++,j--)s+=i+j;12345678910在程序设计中不要过分追求它的多变性ij用逗号表达式例:求n!n!=1*2*3…(n-1)*n参照累加求和main(){inti,n=5,s=1;for(i=1;i<=n;i++)s*=i;printf(“\ns=%d”,s);}注意s的初值。注意当n较大时的情况。求和与连乘都是最常用的算法,要熟练掌握。例:求自然数1-100中能被3整除的数之和。main(){inti,s=0;printf(“\n%d”,s);}求能被3整除但不被7整除的数之和?for(i=1;i<=100;i++)s+=i;for(i=1;i<=100;i++)if(i%3==0)s+=i;for(i=3;i<=100;i+=3)s+=i;for(i=3;i<=100;i+=3)if(i%7)s+=i;例:求任意100个数中的最大值。main(){inti,a,max;max=?for(i=1;i<=100;i++){scanf(“%d”,&a);if(a>max)max=a;}printf(“\nmax=%d”,max);}循环体中没有引用循环变量。i的作用?求任意个数中的最大值?for(i=1;;i++)if(a==-9999)break;max=-32768;外重循环内重循环执行200次要掌握多重循环执行的全过程6.6循环的嵌套循环体内又包含另一个完整的循环结构(多重循环)。for(i=1;i<=10;i++){for(j=1;j<=20;j++){s+=i+j;}}以上多重循环结构可以简写为:for(i=1;i<=10;i++)for(j=1;j<=20;j++)s+=i+j;例:找出行号乘以列号等于100的座位。main(){inti,j;for(i=1;i<=30;i++)for(j=1;j<=20;j++)if(i*j==100)printf(“\n%d,%d”,i,j);}注意循环的关系例:百钱买百鸡问题。给定100块钱,要求正好买100只鸡,已知公鸡5元/只,母鸡3元/只,小鸡1元/3只,问公鸡、母鸡和小鸡应各买多少只?若考虑用方程组:x+y+z=1005x+3y+z/3=100是一多解问题。用测试法求解的程序:main(){intx,y,z;for(x=1;x<=100;x++)for(y=1;y<=100;y++)for(z=1;z<=100;z++)if(x+y+z==100&&5*x+3*y+z/3.0==100)printf(“\n%d,%d,%d”,x,y,z);}程序可进一步简化为:main(){intx,y,z;for(x=1;x<=20;x++)for(y=1;y<=33;y++){z=100-x-y;if(5*x+3*y+z/3.0==100)printf(“\n%d,%d,%d”,x,y,z);}}用测试法求解问题的典型例子测试法求解的程序设计有两个要点:⑴通过循环列出所有可能的解。⑵对所有列出的可能的解进行条件测试。例:判断一个数m是否为素数。main(){inti,m;scanf(“%d”,&m);for(i=2;i<m;i++)if(m%i==0)break;if(i==m)printf(“\n%disaprime”,m);elseprintf(“\n%disnotaprime”,m);}用测试法求解例:(习题6.6)打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字的立方和等于该数本身。如:153是一水仙花数,因为153=13+53+33。main(){inti,j,k,n;for(n=100;n<=999;n++){i=?j=?k=?if(i*i*i+j*j*j+k*k*k==n)printf(“\n%d”,n);}}通过循环列出n的所有可能的范围i=n/100;k=n%10;j=n/10%10;main(){inti,j,k,n;for(i=1;i<=9;i++)for(j=0;j<=9;j++)for(k=0;k<=9;k++){n=i*100+j*10+k;if(i*i*i+j*j*j+k*k*k==n)printf(“\n%d”,n);}}通过循环列出i,j,k的所有可能的范围例:(习题6.4)求S=∑i!=1!+2!+3!+4!+…+19!+20!20i=1main(){inti,j;floatt,s=0;for(i=1;i<=20;i++){s+=?;}printf(“\ns=%f”,s);}用两重循环实现s+=t;t=1;for(j=1;j<=i;j++)t*=j;用递推法:递推公式:ti=ti-1.i求S=∑i!=1!+2!+3!+4!+…+19!+20!20i=1=1+∑(i-1)!.i=1+∑ti-1.i20i=220i=2main(){inti,j;floatt=1,s=t;for(i=2;i<=20;i++){t=t*i;s+=t;}printf(“\ns=%f”,s);}例:递推公式:s=∑—i!1120=—+—+—+—+…+—1!2!3!4!20!11111ti=ti-1/imain(){inti,j;floatt=1,s=t;for(i=2;i<=20;i++){t=t*i;s+=t;}printf(“\ns=%f”,s);}t=t/i;习题6.3:s=a+aa+aaa+aaaa+aaaaa2+22+222+2222+22222递推公式:ti=ti-1·?ti=ti-1*10+amain(){inti,j,a=2;floatt=a,s=t;for(i=2;i<=5;i++){t=t*10+a;s+=t;}printf(“\ns=%f”,s);}例:求方程2x3+3x2-4x+1=0的根。简单迭代法基本思想:将原方程f(x)化为:x2=g(x1)x2=(2x13+3x12+1)/4迭代公式迭代过程:假定一个x1x2=g(x1)不成立|x2-x1∣<εx1=x2输出x2成立main(){floatx1,x2;scanf(“%f”,&x1);while(1){x2=(2*x1*x1*x1+3*x1*x1+1)/4;if(fabs(x2-x1)<1e-6)break;?}printf(“\n%f”,x2);}x1=x2;牛顿迭代法基本思想:牛顿迭代公式f′(x1)=f(x1)/(x1-x2)x2=x1-f(x1)/f′(x1)x1x2yxf(x1)f(x2)main(){floatx1,x2,f1,f;scanf(“%f”,&x1);while(1){f=2*x1*x1*x1+3*x1*x1-4*x1+1;f1=6*x1*x1+6*x1-4;x2=x1-f/f1;if(fabs(x2-x1)<1e-6)break;x1=x2;}printf(“\n%f”,x2);}例:求定积分:数值积分f(x)abx∫—sinxxdxab等分nh=—b-an第i个矩形:x=?x=a+(i-1).h#include“math.h”main(){intn,i;floata,b,x,y,h,s=0;scanf(“%f%f%d”,&a,&b,&n);h=(b-a)/n;for(i=1;i<=n;i++){x=a+(i-1)*h;y=sin(x)/x;s+=h*y;}printf(“\ns=%f”,s);}第七章数组7.1数据结构与数组的概念影响程序设计的因素除算法外还有数据结构。■数据结构概念编写一个程序除了重视算法的设计外,还需重视数据类型的选择,即选择合适的数据类型来存放要处理的数据。在程序设计中,数据类型就称为数据结构,选择合适的数据类型实际上就是进行数据结构的设计。在程序设计中有格言:数据结构+算法=程序说明数据结构与算法同等重要,算法依赖于数据结构,对于同一个问题的求解,可以采用不同的数据结构和不同的算法,对不同的数据结构有不同的算法,其复杂程度也会不同,选择合适的数据结构,可以降低算法的复杂程度。因此,在程序设计中应重视数据结构的设计。例:求任意100个数中的最大值。main(){inti,a,max;max=-32768for(i=1;i<=100;i++){scanf(“%d”,&a);if(a>max)max=a;}printf(“\nmax=%d”,max);}用一个简单变量作为数据结构,合理,算法简单对于三个数的排序:main(){inta,b,c,t;scanf(“%d,%d,%d”,&a,&b,&c);if(a<b){t=a;a=b;b=t;}if(a<c){t=a;a=c;c=t;}if(b<c){t=b;b=c;c=t;}printf(“\n%d,%d,%d”,a,b,c);}对于很多个数的排序用变量会很复杂而用数组会使算法很简单。仍可用变量作为数据结构■数组的概念inta[10]a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]一组具有同样类型的数据的集合统一用一个名字代表---数组名(代表一组数)数组元素下标数组名数组中的各成员称数组元素,由数组名加下标唯一地确定。将一组数用一个名字代表,便于管理。只有一个下标的数组称为一维数组;可有二维数组、三维数组、…、七维数组。7.2一维数组的定义和引用■定义一般形式:类型符数组名[常量表达式]; inta[10];floatb[10];类型符数组名长度作用:分配一组连续的内存单元说明:●数组必须先定义后使用。●数组名的命名规则与变量相同。●常量表达式表示元素的个数(长度),下标从0开始。●常量表达式不能包含变量,即不允许作动态定义。■引用逐个引用其元素,不能进行整体引用。引用的一般形式:数组名[下标]如:a[0]=50;a[1]=100;a[2]=a[0]+a[1];与a2=a0+a1有根本性的区别:下标可变。例:从键盘输入10个数。用变量:(不方便)scanf(“%d%d%d%d%d%d%d%d%d%d”,&a0,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8,&a9);用数组:(灵活方便)for(i=0;i<10;i++)scanf(“%d”,&a[i]);用循环控制输入个数和下标的变化。注意下标的变化范围。■初始化在定义数组的同时给数组赋初值。inta[10]={0,1,2,3,4,5,6,7,8,9};inta[10]={0,1,2,3,4};inta[]={0,1,2,3,4};■应用举例(1)对100个学生的分数统计最高分、最低分和平均分。两种方法:用变量作为存放初始数据的数据结构用数组作为存放初始数据的数据结构main(){inti,a,max,min;floataver=0;max=0;min=100;for(i=0;i<100;i++){scanf(“%d”,&a);if(a>max)max=a;if(a<min)min=a;aver+=a;}aver/=100;printf(“\n%d,%d,%f”,max,min,aver);}用变量main(){inti,a[100],max,min;floataver=0;for(i=0;i<100;i++)scanf(“%d”,&a[i]);max=a[0];min=a[0];for(i=0;i<100;i++){if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];aver+=a[i];}aver/=100;printf(“\n%d,%d,%f”,max,min,aver);}用数组找最大最小的位置?max=0;min=0;if(a[i]>a[max])max=i;if(a[i]<a[min])min=i;(2)统计高于平均分的人数。main(){inti,a,n;floataver=0;for(i=0;i<100;i++){scanf(“%d”,&a);aver+=a;}aver/=100;n=0;for(i=0;i<100;i++){scanf(“%d”,&a);if(a>aver)n++;}printf(“\n%d”,n);}用变量数据结构不合理main(){inti,a[100],n;floataver=0;for(i=0;i<100;i++)scanf(“%d”,&a[i]);for(i=0;i<100;i++)aver+=a[i];aver/=100;n=0;for(i=0;i<100;i++)if(a[i]>aver)n++;printf(“\n%d”,n);}用数组1(3)对100个学生的分数统计出每分一档人数。0?1?2 ?    3  ?    4  ?┇┇99?100?main(){inti,a; for(i=1;i<=100;i++){scanf(“%d”,&a); }输出}inti,a,n[101];for(i=0;i<101;i++)n[i]=0;n[a]++;完整程序:main(){inti,a,n[101];for(i=0;i<101;i++)n[i]=0; for(i=1;i<=100;i++){scanf(“%d”,&a);n[a]++; }for(i=100;i>=0;i--)printf(“\n%3d:%3d”,i,n[i]);}体会数组作为存放结果的数据结构时的优越性。按10分一档统计?main(){inti,a,n[101];for(i=0;i<101;i++)n[i]=0; for(i=1;i<=100;i++){scanf(“%d”,&a);n[a]++; }}inti,a,n[11];for(i=0;i<11;i++)n[i]=0;n[a/10]++;(4)对10个学生的分数按从小到大的顺序排序后输出。两种典型的排序算法:选择法和起泡法。选择法基本思想:首先选择最小的数放在0位置,再在剩下的数中选择最小的数放在下一位置,┈┈,依次类推,共进行9次选择。 5874390126每次选择都要与其后的所有数进行比较换位。5874390126 ijmain(){inta[10],i,j,t;for(i=0;i<10;i++)scanf(“%d”,&a[i]);for(i=0;i<9;i++)for(j=i+1;j<10;j++)if(a[i]>a[j]){t=a[i];a[i]=a[j];a[j]=t;}for(j=0;j<10;j++)printf(“%3d”,a[j]);}58743901265874390126 ij先找最小值所在的位置,最后再换位:main(){inta[10],i,j,t,k;for(i=0;i<10;i++)scanf(“%d”,&a[i]);for(i=0;i<9;i++){k=i;for(j=i+1;j<10;j++)if(a[j]<a[k])k=j;t=a[i];a[i]=a[k];a[k]=t;}for(j=0;j<10;j++)printf(“%3d”,a[j]);}起泡法基本思想:首先将所有数中的最大值“冒泡”到最后位置,再将剩下的数中的最大值“冒泡”到上一位置,┈┈,依次类推,共进行9次“冒泡”。每次“冒泡”都是一种翻滚过程,即相邻两个数进行比较换位。5874390126main(){inta[10],i,j,t;for(i=0;i<10;i++)scanf(“%d”,&a[i]);for(j=1;j<=9;j++)for(i=0;i<10-j;i++)if(a[i]>a[i+1]){t=a[i];a[i]=a[i+1];a[i+1]=t;}for(j=0;j<10;j++)printf(“%3d”,a[j]);}要特别注意两个循环的范围。 ((5)循环移位对一数列中的每个数向后移3个位置,最后3个数移到最前面。58743901261265874390用循环移位实现:5874390126main(){inti,j,k,a[10];for(i=0;i<10;i++)scanf(“%d”,&a[i]); for(i=0;i<10;i++)printf(“%3d”,a[i]);}for(i=1;i<10;i++)a[i]=a[i-1];for(i=9;i>0;i--)a[i]=a[i-1];k=a[9];a[0]=k;for(j=1;j<=3;j++){k=a[9];}(6)狐狸找兔子问题绕围绕着山顶有10个洞,一只兔子和一只狐狸分别住在洞里,狐狸总想吃掉兔子;一天,兔子对狐狸说:你想吃掉我有一个条件,先把洞顺序编号,你从最后一个洞出发,第一次先到第一个洞找我,第二次隔一个洞找,第三次隔两个洞找,┈,依次类推,寻找次数不限,我躲在一个洞里不动,只要找到我你就可以饱餐一顿。狐狸一想只有10个洞,寻找次数又不限,那有找不到的呢?马上答应了条件,结果狐狸跑断了腿也没找到,请问兔子躲在哪个洞里?12346789105算法思想:开辟数组,每个元素代表一个洞,并赋初值0,表示各个洞都还未找,然后按规律找,每找一个洞,对应的数组元素就赋值1,表示已找过,┈┈,最后根据数组元素值1与0来识别各洞是否已找过。main(){inti,k=10;inta[10]={0,0,0,0,0,0,0,0,0,0};for(i=1;i<=10000;i++){k=(k+i)%10;if(k==0)k=10;a[k-1]=1; }for(i=0;i<10;i++)if(a[i]==0)printf(“%3d”,i+1);}7.3二维数组的定义和引用■定义一般形式:类型符数组名[常量表达式][常量表达式];inta[3][4];floatb[5][10]; 行列 二维数组的逻辑结构就如同一张:a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3] 存放形式:按行存放。a[0]a[1]a[2]二维数组可以看作是一个特殊的一维数组,它的元素又是一个一维数组。C语言这样的处理方法在很多情况下显得很方便。与一维数组相比,二维数组的定义多一个长度,其元素多一个下标。在应用中,如果要处理的数据如同一数列,则可定义一维数组来存放;而如果要处理的数据如同一张表格,则应定义二维数组来存放。■引用引用形式:数组名[下标][下标]如:a[0][3]=a[1][2]+a[2][3];其元素有两个下标。例:从键盘输入12个数到二维数组中。inta[3][4],i,j;for(i=0;i<3;i++)for(j=0;j<4;j++)scanf(“%d”,&a[i][j]);需要用两重循环来控制两个下标的变化。如果键盘输入的数据是:123456789101112,则在数组中如何存放?两个循环换位呢?两个下标换位呢? inta[3][4],i,j;for(i=0;i<3;i++)for(j=0;j<4;j++)scanf(“%d”,&a[i][j]);  for(j=0;j<4;j++)for(i=0;i<3;i++)scanf(“%d”,&a[i][j]);for(i=0;i<3;i++)for(j=0;j<4;j++)scanf(“%d”,&a[j][i]);例:输入一个表格的数据到二维数组中,并找最大值所在的位置main(){inta[3][4],i,j,i1,j1;for(i=0;i<3;i++)for(j=0;j<4;j++)scanf(“%d”,&a[i][j]);i1=0;j1=0;for(i=0;i<3;i++)for(j=0;j<4;j++)if(a[i][j]>a[i1][j1]){i1=i;j1=j;}printf(“\n%d,%d”,i1,j1);}■初始化对二维数组赋初值的几种方法:inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};inta[3][4]={{1},{5},{9}};inta[3][4]={{1},{0,6},{0,0,11}};inta[][4]={1,2,3,4,5,6,7,8,9,10,11,12};inta[][4]={{0,0,3},{},{9,10}};■举例(1)矩阵的基本操作二维数组的逻辑结构就如同一个矩阵,因此,矩阵操作都可用二维数组实现。a11a12a13…a1na21a22a23…a2na31a32a33…a3n…………am1am2am3…amnA=假定M=3,N=4求和:main(){inta[4][4],i,j,s=0;┈┈┈for(i=0;i<4;i++)for(j=0;j<4;j++)s+=a[i][j];┈┈┈}上三角?下三角?主对角线?for(i=0;i<4;i++)for(j=i;j<4;j++)s+=a[i][j];for(i=0;i<4;i++)for(j=0;j<=i;j++)s+=a[i][j];for(i=0;i<4;i++)for(j=i;j<=i;j++)s+=a[i][j];for(i=0;i<4;i++)s+=a[i][i];12345678 101112 13141516非方阵转置:aij→bjimain(){inta[3][4],b[4][3],i,j;┈┈┈for(i=0;i<3;i++)for(j=0;j<4;j++)b[j][i]=a[i][j];┈┈┈}123456789101112159261037114812方阵转置:aij∽ajimain(){inta[3][3],i,j,t;┈┈┈for(i=0;i<3;i++)for(j=0;j<3;j++){t=a[i][j];a[i][j]=a[j][i];a[j][i]=t;}┈┈┈}123456789for(j=i+1;j<3;j++)将矩阵中和值为最大的那一行元素与首行对换。main(){inta[3][4],i,j,t,s,smax=-32768,row;┈┈┈for(i=0;i<3;i++){s=0;for(j=0;j<4;j++)s+=a[i][j];if(s>smax){smax=s;row=i;}}for(j=0;j<4;j++){t=a[0][j];a[0][j]=a[row][j];a[row][j]=t;}┈┈┈}1538461792567.4字符数组用于存放字符的数组称字符数组。字符数组的每一个元素存放一个字符。字符数组的独特之处:(1)字符数组可以看作字符串变量。(2)对字符数组可以进行某些整体操作。(3)有专用的字符串处理函数。1、将字符数组作为字符串变量charc[10];给c分配10个字节的内存单元。把c看作数组时,按数组元素的形式访问:c[0]=’a’;c[1]=’b’;c[2]=’c’;c[3]=’d’;abcdcharc[10]={‘a’,’b’,’c’,’d’};也属于字符赋初值的形式。如果把字符序列看作一个整体(字符串),则c就可看作是存放这个字符串的串变量;但必须在字符序列后加上“字符串结束标志”后,才能成为完整的字符串。如:c[4]=’\0’;或c[4]=0; abcd\0也可以按字符串形式初始化:charc[10]=”abcd”;charc[]=”abcd”;分配5个字节2、对字符数组的整体操作对字符数组的有些操作可以整体进行,如输入输出。for(i=0;i<10;i++)printf(“%c”,c[i]);对数组元素操作printf(“%s”,c);整体操作注意以上两种操作有区别。可将前者改为:for(i=0;c[i]!=’\0’;i++)printf(“%c”,c[i]);对于输入:for(i=0;i<10;i++)scanf(“%c”,&c[i]);对数组元素操作scanf(“%s”,c);整体操作对字符数组输入输出可以整体进行,但不允许整体赋值:charc[10]=”abcd”,x[10];x=c;不允许对于二维字符数组,可以看作是一维的字符串数组。例:从键盘输入10个人的名字到计算机:main(){inti;charname[10][20];10个元素的一维字符串数组for(i=0;i<10;i++)scanf(“%s”,name[i]);…}只给一个下标3、字符串处理函数c语言的函数库中提供了一系列专用于字符串处理的函数,需要时可直接调用。(1)puts(字符串)用于输出字符串。其中字符串可以是字符串常量,也可以是字符数组。例:charstr[]=”China”;puts(str);puts(”China”);两个输出等效(2)gets(字符数组)用于从键盘输入一个字符串到字符数组中。函数返回字符数组的起始地址。例:charstr[10];gets(str);执行该函数调用时,计算机等待输入字符串(3)strcat(字符数组,字符串)用于将字符串连接到字符数组的后面。其中字符串可以是字符串常量,也可以是字符数组。例:chara[10]=”abcd”,b[10]=”xyz”;strcat(a,b);与strcat(a,”xyz”)等效puts(a);输出结果是:abcdxyz(4)strcpy(字符数组,字符串)用于将字符串拷贝到字符数组中。其中字符串可以是字符串常量,也可以是字符数组。例:chara[10],b[10]=”abcdef”;strcpy(a,b);与strcpy(a,”abcdef”)等效不能用a=b赋值puts(a);输出结果是:abcdef(5)strcmp(字符串1,字符串2)用于比较两个字符串的大小。比较结果通过函数的返回值体现:字符串1=字符串2时:返回0。字符串1>字符串2时:返回一正整数。字符串1<字符串2时:返回一负整数。两个字符串之间谁大谁小取决于最先有差异的两个字符的ASCII代码的大小。如:strcmp(“abcde”,”abcde”);返回0strcmp(“abcdefgh”,”abcxyz”);返回负整数strcmp(“a”,”ABCD”);返回正整数例:从键盘输入两个字符串,输出其中大的一个。#include“string.h”main(){chara[10],b[10];gets(a);gets(b);if(strcmp(a,b)>0)puts(a);不能用a>belseputs(b);}使用字符串处理函数需要包含头文件string.h(6)strlen(字符数组)测试字符串的实际长度(从返回值得到)。(7)strlwr(字符串)将字符串中的大写字母全改为小写字母。(8)strupr(字符串)将字符串中的小写字母全改为大写字母。注意:在使用字符串处理函数时,别忘了将头文件string.h包含进去。4、字符串操作举例(1)从键盘输入一字符串到数组a中,再拷贝到数组b中(不用库函数)。main(){chara[50],b[50];inti;scanf(“%s”,a);for(i=0;a[i];i++)b[i]=a[i];b[i]=0;printf(“%s”,b);}(2)从键盘输入两个字符串到数组a和b中,在将b中的内容连接到a中(不用库函数)。main(){chara[50],b[50];inti,j;scanf(“%s%s”,a,b);for(i=0;a[i];i++);for(j=0;b[j];j++)a[i++]=b[j];a[i]=0;printf(“%s”,a);}(3)从键盘输入一字符串,并将其中的大写字母改成小写字母后输出(不用库函数)。main(){chara[50];inti;scanf(“%s”,a);for(i=0;a[i];i++)if(a[i]>=’A’&&a[i]<=’Z’)a[i]+=32;printf(“%s”,a);}第八章函数8.1概述C语言的程序除主函数外,还可以有若干个其他函数—块状结构。一般把其中相对独立的算法和功能定义成一个独立的函数,以供需要的地方调用。优点:(1)减少代码的重复现象。(2)便于分工合作。(3)便于阅读。(4)便于独立算法的代码移植。8.2函数的定义和调用举例说明:对于求两个数中的最大值,有三个步骤:(1)从键盘输入两个数给a和b。(2)求a和b中的最大值。(3)输出结果。把求最大值的算法部分定义成一个独立的函数:函数类型函数名函数参数(形参)intmax(intx,inty)main(){intz;{inta,b,c;if(x>y)z=x;scanf(“%d%d”,&a,&b);elsez=y;c=max(a,b);return(z);printf(“%d”,c);}}xyzabc35说明:(1)程序由两个函数组成,它们逻辑上相互独立(功能、变量)。(2)程序的执行总是从主函数开始,主函数总是被执行一次,其他函数只有在被调用时才获得控制。(3)函数调用有两个作用:转移控制权和传递参数。(4)return的作用也有两个:交回控制权和返回结果。(5)实参可以是常量、变量或表达式,但类型要一致。定义一个函数除考虑算法外就是:如何设计函数的参数,通过何种途径交回结果。例:求自然数1—100中的素数之和。?prime(?)main(){inti;{inti,s=0;for(i=2;i<m;i++)for(i=1;i<=100;i++)if(m%i==0)?if(prime(i))s+=i;?printf(“\n%d”,s);}}intm)intreturn0;elsereturn1;return1;例:求5!+7!+4!的值。?fac(?) {inti,s=1;for(i=1;i<=n;i++)s*=i;return(s);}main(){printf(“\n%d”,fac(5)+fac(7)+fac(4));}intnintmain(){floats,fac();对被调函数声明s=fac(5)+fac(7)+fac(4);printf(“\n%f”,s);}floatfac(intn){inti;floats=1;for(i=1;i<=n;i++)s*=i;return(s);}不需声明的情况:intchar主调函数在后若被调用的函数是库函数,则应用#include命令将所调用函数的有关信息包含进来,如:例:#include“math.h”main(){floatx,y;scanf(%f”,&x);y=sin(x);printf(“%f”,y);}8.3函数的嵌套调用C语言的函数定义虽然相互平行、相互独立的,但可以嵌套调用,形如:主函数函数A函数B例:求多项式S=∑i!+∑i!+∑i!的值。floatfac(intn){…}?sum(?){inti;floats=0;for(i=?)s+=fac(i);return(s);}main(){printf(“%f”,sum(1,5)+sum(7,11)+sum(15,20);}157111520inta,intbfloati=a;i<=b;i++8.4函数的递归调用在函数调用的过程中,出现直接或间接地调用该函数本身。如:f1()f2()f3(){{{f1();f3();f2();}}}直接间接递归调用递归调用在实际应用中,有些问题既可用递归实现,也可不用递归(如求n!);也有些问题非有递归不可(如汉诺塔问题);不少问题使用递归显得很方便。用递归方法求n!:递推公式:1当n=0或n=1时n!=n(n-1)!当n>1时floatfac(intn)main(){floatf;{floatf;if(n==0||n==1)f=1;f=fac(4);elsef=?printf(“\n%f”,f);return(f);}}递归调用的执行过程:n*fac(n-1);主函数函数fac函数fac函数fac函数fac问题:4个return的执行顺序?后进先出!f=fac(4);n=4if(n==0||n==1)f=1;elsef=n*fac(n-1);return(f)n=3if(n==0||n==1)f=1;elsef=n*fac(n-1);return(f)n=2if(n==0||n==1)f=1;elsef=n*fac(n-1);return(f)n=1if(n==0||n==1)f=1;elsef=n*fac(n-1);return(f)8.5数组作为函数的参数当要传递的参数较少时,用简单变量作为函数的参数是方便的,但当要传递的参数是批量时,需要用数组作为函数的参数。例:编写函数,求100个数的平均数。floataver(inta[100]){inti;floats=0;for(i=0;i<100;i++)s+=a[i];return(s/100);}main(){intx[100];floatav;输入x;av=aver(x);}对应的实参也应为数组型参数组的长度可省略a[]通用函数考虑:floataver(inta[],intn)main(){inti;floats=0;{intx[100],n=100;for(i=0;i<n;i++)floatav;s+=a[i];输入xreturn(s/n);av=aver(x,n);}}xa100nn值传递地址传递100n=5;5a[0]=3;3例:阅读程序:main()sa,intb){inta=3,b=5;{intt;s);t=a;a=b;b=t;printf(“\n%d,%d”,a,b);printf(“\n%d,%d”,a,b);}}abab35以下程序的运行结果是?main()f(intb[],intx){inta[2]={2,4},x=5;{x++;f(a,x);b[0]+=2;printf(“%d,%d,%d”,b[1]+=3;x,a[0],a[1]);}}A)5,2,4B)6,4,7C)6,2,4D)5,4,7例:排序。voidsort(inta[],intn){inti,j,t;for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)if(a[i]>a[j]){t=a[i];a[i]=a[j];a[j]=t;}}main(){intx[5],i;for(i=0;i<5;i++)scanf(“%d”,&x[i]);sort(x,5);for(i=0;i<5;i++)printf(“%4d”,x[i]);}xa例:方阵转置(二维数组情况)。at(inta[3][3])xa{inti,j,t;for(i=0;i<3;i++)for(j=i+1;i<3;i++){t=a[i][j];a[i][j]=a[j][i];a[j][i]=t;}}intx[3][3];at(x);行长不等情况?通用函数的处理?通用函数,按一维数组处理:at(inta[],intn){inti,j,t;for(i=0;i<n;i++)for(j=i+1;i<n;i++){t=a[i*n+j];a[i*n+j]=a[j*n+i];a[j*n+i]=t;}}intx[3][3];at(x,3);8.6局部变量和全局变量1、局部变量在函数内定义的变量称局部变量。局部变量只在该函数内使用。floatf1(intx)intf2()main(){inti,j;{inta,b,c;{intm,n;┊┊{inti,j;┊┊┊}}}}说明:(1)任何函数(包括主函数)内定义的变量都是局部变量。(2)不同函数内定义的变量即使同名也互不干扰。(3)复合语句中定义的变量只在该复合语句中有效。2、 全局变量在函数以外定义的变量,也称外部变量。全局变量可以为为本文件中其它函数所共用。它的作用范围是从定义变量的位置开始到本源文件结束。intp=1,q=5;floatf1(inta){intb,c;┊}charc1,c2;charf2(intx,inty){inti,j;┊}main(){intm,n;┊}全局变量c1,c2的作用范围全局变量p,q的作用范围全局变量主要用于作为不同函数间数据传递的桥梁。例:编写一个函数,求n个数中的最大值、最小值和平均值。并编写主函数完成:输入100个数,调用该函数进行统计,输出结果。 intmax,min;floataver(inta[],intn){inti;floats=0;for(i=0;i<n;i++){if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];s+=a[i];}return(s/n);}main(){intx[100],i;floatav;for(i=0;i<100;i++)scanf(“%d”,&x[i]);av=aver(x,100);printf(“\n%d,%d,%f”,max,min,av);}用全局变量传递结果分析不用全局变量的情况:floataver(inta[],intn){inti;floats=0;intmax,min;for(i=0;i<n;i++){if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];s+=a[i];}return(s/n);}main(){intx[100],i;floatav;intmax,min;for(i=0;i<100;i++)scanf(“%d”,&x[i]);av=aver(x,100);printf(“\n%d,%d,%f”,max,min,av);}intmax,min;floataver(inta[],intn){inti;floats=0;for(i=0;i<n;i++){if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];s+=a[i];}return(s/n);}main(){intx[100],i;floatav;intmax,min;for(i=0;i<100;i++)scanf(“%d”,&x[i]);av=aver(x,100);printf(“\n%d,%d,%f”,max,min,av);}分析全局变量与局部变量同名的情况maxminmaxmin阅读程序,给出运行结果:inta=4,b=5,c=6;intf(inta,intb){a/=2;c+=b-a;return(a+b+c);}main(){inta=2,d;d=f(a+2,a+b);printf(“\n%d,%d,%d,%d”,a,b,c,d);}4526abcabad47211208.7变量存储类别1、动态存储方式和静态存储方式静态存储方式:在程序运行期间分配固定存储单元的方式。动态存储方式:在程序运行期间根据需要动态分配存储单元的方式。变量变量局部变量动态存储方式变量全局变量静态存储方式变量空间角度生存期角度 存放在静态存储区的变量:静态存储方式。 存放在动态存储区的变量:动态存储方式。 程序区静态存储区动态存储区程序开始运行时分配空间,运行结束时释放主要存放全局变量和静态局部变量根据需要动态分配,动态释放的区域主要存放动态局部变量和现场保护等用户区2、局部变量的存储方式每个局部变量在定义时可以指定其存储方式,即对每个局部变量的定义除定义其数据类型外,还应定义其存储方式。定义存储方式用auto(自动的)static(静态的)。如:intf1()intf2(){autointa=1;{staticintb=1;┊┊}}缺省时为auto动态局部变量在函数调用时分配、赋初值,调用结束时释放。静态局部变量在第一次调用时分配、赋初值,调用结束时不释放,其单元及其值仍保留,下次调用时不重新分配,不重新赋初值。在实际应用中,如果希望在函数调用结束后仍保留某个局部变量的值给下次调用时使用,则可定义该变量为静态的。例:编写一个函数计算:y=2x-1第一次计算3x+1第二次计算4x+2其他floatf(floatx)main(){floaty;{staticintn=1;printf(“%f”,f(2.0));if(n==1)y=2*x-1;printf(“%f”,f(1.0));elseif(n==2)y=3*x+1;printf(“%f”,f(3.0));elsey=4*x+2;}n++;return(y);}      3、全局变量的存储方式全局变量都是静态存储方式,不允许用auto来定义全局变量。可以用static来定义全局变量。如:staticintx;静态全局变量(内部的)inty;非静态全局变量(外部的)对于非静态全局变量,其它文件中的函数只要用extern加以外部说明,就可以访问。而对于静态全局变量,只局限在本文件中的所有函数访问,其它文件中的函数即使用extern加以外部说明,也不能访问。inty;main(){y=0;}intf1(){y=2;}externinty;intf3(){y=10;}intf4(){y=100;}staticinty;8.8内部函数和外部函数用extern加以定义的函数称外部函数。用extern加以定义的函数称外部函数。externintf1()staticintf2(){{┊┊}}缺省为外部函数。外部函数可以为其他文件中的函数所调用。内部函数只为本文件中的函数所调用(保护)。main(){f3();允许}intf1(){f4();不允许}externintf3(){f4();允许}staticintf4(){}第九章编译预处理C语言提供了一些以#开头的指令,如:#define#include等。这些指令是在编译以前就事先进行处理的,因而称为“编译预处理”指令。可以用编译预处理指令实现以下三种功能:1)宏定义2)文件包含3)条件编译9.1宏定义1、不带参的宏定义用一个指定的标识符(宏名)代表一个字符串。一般形式:#define标识符字符串如:#definePI3.1415926有了这一宏定义后,程序中凡是用到3.1415926的地方都可以以宏名PI出现。例:定义一个宏名来代表一个参数。#definePI3.1415926main(){floatr=2,c,s;c=2*PI*r;s=PI*r*r;┈}系统在对程序进行编译以前,首先将所有的编译预处理指令进行预处理,对本例来说,就是将程序中所有的宏名PI还原成3.1415926,——宏展开。例:定义一个宏名来代表一个数据个数。#defineN100main(){inta[N],i;floats=0;for(i=0;i<N;i++)scanf(“%d”,&a[i]);for(i=0;i<N;i++)s+=a[i];s/=N;printf(“\n%f”,s);}宏名N---符号常量,可以作为数组说明的长度。方便修改参数。例:定义一个宏名来代表一个计算公式。#definePI3.1415926#defineAREAPI*r*rmain(){r=3,s;s=AREA;printf(“\n%f”,s);}注意:系统对宏定义的预处理是一个字符串的还原过程,不要把宏名看成一个整体。注意以下程序的运行结果:#defineFx+ymain(){intx=3,y=5,z;z=2*F;printf(“\n%d”,z);}2、带参的宏定义宏定义也可以带参数,其一般形式为:#define宏名(参数表)字符串如:#defineS(a,b)a*barea=S(3,2);定义宏名S代表矩形面积,参数a,b为边长。宏展开过程:9.2文件包含处理在一个源文件中将另一个源文件的内容包含进来。文件包含指令的一般形式:#include“文件名”或#include<文件名>#include“”AABB例:#include“math.h”main(){floata,b,c,s,area;scanf(“%f%f%f”,&a,&,&c);s=0.5*(a+b+c);area=sqrt(s*(s-a)*(s-b)*(s-c));printf(“\n%f”,area);}#include“f.h”main(){printf(“\n%f”,f1(3.0));printf(“\n%f”,fac(10));}floatf1(floatr){return(PI*r*r);}floatfac(intn){inti;floats=1;for(i=1;i<=n;i++)s*=i;return(s);}#definePI3.1415926floatf1(floatr);floatfac(intn);f.cf.h第十章指针指针:C的一个重要概念、重要特色。它使C具备了强大的功能,使C成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。不掌握指针等于没有掌握C语言的精华。10.1指针的概念简单地说,指针就是地址。要掌握指针的概念就必须弄清:■内存地址概念?■变量与地址的关系?■如何通过地址进行变量的存取?说明例:内存用户数据10003i10026j10049k对变量值的存取总是按地址进行的----直接访问。inti,j,k;i=3;j=6;k=i+j;程序经编译后,变量名就不复存在,以地址对应。也可以采用“间接访问”方式:先将变量i的地址存放到另一变量p1中,要访问i时,先取出p1的内容(变量i的地址),再去访问该地址所对应的内存单元中的内容(变量i的值)。内存用户数据10003i10026j10049k20001000p120041002p2inti,j,k;i=3;j=6;k=i+j;int*p1,*p2;p1=&i;p2=&j;在以上概念的基础上对指针下定义:变量的地址就是该变量的指针。存放地址的变量称指针变量。p1是指向变量i的指针变量。10001002100410001002ijkp1p210.2变量的指针变量的指针指针变量指向变量的指针变量用“*”代表“指向”如*p1代表它所指向的变量i,同一内存单元。以下两个语句等价:i=3;直接访问*p1=3;间接访问内存用户数据10003i10026j10049k20021000p120041002p2inti,j,k;i=3;j=6;k=i+j;int*p1,*p2;p1=&i;p2=&j;*p1=3;■指针变量的定义指针变量也必须先定义后使用。int*p1;注意:①*表示该变量为指针变量,但变量名是p1。②一个指针变量只能指向同一类型的变量。inti,*p1;floata;p1=&i;合法p1=&a;不合法■指针变量的引用两种用法:①用地址运算符&p1=&i;②用指针运算符*(实行间接访问)*p1=100;k=*p1;注意:指针变量只能放地址(指针)。p1=100;不允许例:main(){inta=100,b=10;int*p1,*p2;定义指针变量,尚无具体指向p1=&a;p1指向ap2=&b;p2指向bprintf(“\n%d,%d”,a,b);printf(“\n%d,%d”,*p1,*p2);}注意:要区别定义和引用中的“*”要特别注意以下用法的后果:int*p1;*p1=100;例:输入a和b两个整数,按先大后小的顺序输出main(){inta,b,*p1,*p2,*p;scanf(“%d,%d”,&a,&b);10005ap1=&a;p2=&b;10029bif(a<b){p=p1;p1=p2;p2=p;}printf(“\n%d,%d”,a,b);2000p1printf(“\n%d,%d”,*p1,*p2);2004p2}2006p改变p1和p2的指向1000100210021000重要概念:只要得到某变量的地址(指针),就可通过指针而不需通过逻辑名来访问该变量。手段:用指针变量保存变量的地址。■指针变量作为函数的参数可将指针变量作函数的参数,接受实参地址,获得具体指向,进而通过指针变量间接访问主调函数的变量。s*p1,int*p2){intt;t=*p1; *p1=*p2;*p2=t;10005a}10029bmain(){inta,b;scanf(“%d,%d”,&a,&b);2000p1if(a<b)swap(&a,&b);2004p2printf(“\n%d,%d”,a,b);2006t}1000100259跨越逻辑上的限制sp1,intp2)不用指针变量情况{intt;t=p1; p1=p2;p2=t;10005a}10029bmain(){inta,b;scanf(“%d,%d”,&a,&b);2000p1if(a<b)swap(a,b);2004p2printf(“\n%d,%d”,a,b);2006t}5959重要概念:使用指针变量作函数参数,被调函数可以通过主调函数给定的地址去操作主调函数中的局部变量。(可用于传递多个结果)例:编写函数,求一元二次方程的两个实根。#include“math.h”?root(floata,floatb,floatc,){floatd;d=b*b-4*a*c;if(d<0||a==0)return(0);?=(-b+sqrt(d))/2/a;?=(-b-sqrt(d))/2/a;return(1);}float*x1,float*x2*x1*x2intmain(){intk;floata,b,c,xa,xb;scanf(“%f,%f,%f”,&a,&b,&c);k=root(a,b,c,&xa,&xb);if(k)printf(“\n%f,%f”,xa,xb);}例:求n个数的最大值、最小值和平均值。floataver(inta[],intn,int*max,int*min){inti;floats=0;*max=a[0];*min=a[0];for(i=0;i<n;i++){s+=a[i];if(a[i]>*max)*max=a[i];if(a[i]<*min)*min=a[i];}return(s/100);}main(){inta[100],i,max,min;floatav;for(i=0;i<100;i++)scanf(“%d”,&a[i]);av=aver(a,100,&max,&min);printf(“%d,%d,%f”,max,min,av);}10.3数组的指针数组有一个首地址:数组的指针。每个数组元素也都有地址:数组元素的指针。532168742000200220042006■指向数组元素的指针变量inta[10],*p;p=a;指向数组p=&a[0];指向数组元素51247680392000200220042006p■通过指针引用数组元素p=&a[0];p指向a[0]*p=1;等效于a[0]=1;即可通过p来访问a[0]也可以通过p来访问其它元素:*(p+1)=3;等效于a[1]=3;其中p+1指向a[1]注意:p+1不是地址加1,而是加一个数据类型单位。一般地,当p指向a[0]时:p+i∽a+i∽&a[i]*(p+i)∽*(a+i)∽a[i]∽p[i]即以下几个语句等效:a[i]=10;*(p+i)=10;*(a+i)=10;p[i]=10;例:从键盘输入10个数到数组a:inta[10],i,*p=a,s=0for(i=0;i<10;i++)scanf(“%d”,&a[i]);for(i=0;i<10;i++)scanf(“%d”,a+i);for(i=0;i<10;i++)scanf(“%d”,p+i);累加求和的各种用法:for(i=0;i<10;i++)s+=a[i];for(i=0;i<10;i++)s+=*(a+i);for(i=0;i<10;i++)s+=*(p+i);for(i=0;i<10;i++)s+=p[i];for(i=0;i<10;i++)s+=*p++;等效于*(p++)for(p=a;p<a+10;p++)s+=*p;注意不能使用a++后两种用法效率高。使用指针变量访问数组时,要特别注意指针变量的当前值。注意下例: main(){inta[10],*p=a,i;for(p=a;p<a+10;p++)scanf(“%d”,p); for(i=0;i<10;i++)printf(“%d”,*p++);}pp=a;■数组名作为函数参数有了指针概念的基础上,重新回顾数组名作为函数参数时,数据的传递情况:例:将数组a中的n个数按相反顺序存放。intinv(intx[],intn){i,j,m,t;main()m=(n-1)/2;{for(i=0;i<=m;i++)inta[10],i;{j=n-1-i;输入at=x[i];inv(a,10);x[i]=x[j];输出ax[j]=t;}}}a与x共用同一片内存单元axintinv(int*x,intn)指针变量作函数参数时的传递情况{i,j,m,t;main()m=(n-1)/2;{for(i=0;i<=m;i++)inta[10],i;{j=n-1-i;输入at=x[i];inv(a,10);x[i]=x[j];输出ax[j]=t;}}下标法}a10001000x{j=n-1-i;t=*(x+i);*(x+i)=*(x+j);*(x+j)=t;}指针法进一步优化:intinv(int*x,intn){main()int*i=x,*j=x+n-1,t;{for(;i<j;i++,j--)inta[10],i;{输入at=*i;inv(a,10);*i=*j;输出a*j=t;}}}优点:简练效率高ij例:选择法排序函数voidsort(int*a,intn){inti,j,t;for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)if(a[i]>a[j]){t=a[i];a[i]=a[j];a[j]=t;}}只将形参改为指针变量,仍按下标法使用voidsort(int*a,intn){inti,j,t;for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)if(*(a+i)>*(a+j)){t=*(a+i);*(a+i)=*(a+j);*(a+j)=t;}}按指针法使用进一步优化:voidsort(int*a,intn){int*i,*j,t;for(i=a;i<a+n-1;i++)for(j=i+1;j<a+n;j++)if(*i>*j){t=*i;*i=*j;*j=t;}}main(){inta[10],j;for(j=0;j<10;j++)scanf(“%d”,a+j);sort(a,10);for(j=0;j<10;j++)printf(“%5d”,a[j]);}分段排序?main(){inta[10],j;for(j=0;j<10;j++)scanf(“%d”,a+j);for(j=0;j<10;j++)printf(“%5d”,a[j]);}sort(a,5);sort(a+5,5);■指向多维数组的指针和指针变量从本质上说,多维数组的指针与一维数组的指针相同,但在概念上和使用上,多维数组的指针要复杂些。以二维数组的指针为例:●二维数组的地址:一维:a,&a[i],a+i二维:a,&a[i][j],a+i(行指针),a[i](特殊的一维数组元素,列指针),a[i]+j358724691604inta[3][4]100010081016a+0a+1a+2a[0]a[1]a[2]讨论以下用法的效果:for(i=0;i<3;i++)scanf(“%d”,a+i);输入数据:123讨论以下用法的效果:for(i=0;i<3;i++)scanf(“%d”,a[1]+i);输入数据:123讨论以下用法的效果:for(i=0;i<3;i++)scanf(“%d”,a[1]+i+2);输入数据:123讨论以下用法的效果:for(i=0;i<3;i++)scanf(“%d”,a+i+1);输入数据:123注意:指针运算符*作用在行指针上的结果仍是指针----列指针;*作用在列指针上的结果---具体元素。*(a+0),*(a+1),*(a+2)——仍是地址。*(a+i)*(a[0]),*(a[1]),*(a[1])——具体元素值。*(a[i])*(a+i)+j也是地址,但要区别:(a+i)+j——行指针(a+1)+1?*(a+i)+j——列指针*(a+1)+1?100010081016a+0a+1a+2a[0]a[1]a[2]*(a+1)如果要通过a+i形式的地址访问数组元素的具体内容,则:*(*(a+i))或*(*(a+i)+j)如:*(*(a+1))——a[1][0]*(*(a+1)+2)——a[1][2]讨论:*(a+2)*(*(a+1)+3)*(a[1]+1)*(*(a+1)+5)例:求数组a的所有元素之和。可有多种用法:for(i=0;i<3;i++)for(i=0;i<3;i++)for(j=0;j<4;j++)for(j=0;j<4;j++)s+=a[i][j];s+=*(a[i]+j);for(i=0;i<3;i++)for(j=0;j<4;j++)s+=*(*(a+i)+j);(●指向二维数组的指针变量同样可使一个指针变量p指向二维数组a,再通过p访问数组元素。main(){inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};inti,k,*p;p=a;k=*p;?k=*(p+2);?for(p=a;p<a+2;p++)printf(“%3d”,*p);?}123456789101112k=p[1][2];不合法k=*(*(p+1)+2);k=p[1*4+2];合法k=*(p+1*4+2);例:求矩阵的上三角元素之和。main(){inta[3][4],*p,i,j,s=0;输入ap=a;for(i=0;i<3;i++)for(j=i;j<4;j++)s+=p[i*4+j];或s+=*(p+4*i+j)printf(“\n%d”,s);}●指向由m个元素组成的一维数组的指针变量可以这样定义一个指针变量:int(*p)[4]表示p为指向由4个元素组成的行指针变量。当p=a时,可通过p引用a[i][j]:p[i][j]或*(*(p+i)+j)例:求矩阵的上三角元素之和。main(){inta[3][4],(*p)[4],i,j,s=0;输入ap=a;for(i=0;i<3;i++)for(j=i;j<4;j++)s+=p[i][j];或s+=*(*(p+i)+j)printf(“\n%d”,s);}●多维数组的指针作函数参数用于接受实参数组地址的形参可用两种:行指针和列指针。以方阵转置为例:voidat(int(*a)[3])用行指针{inti,j,t;缺点:不通用for(i=0;i<3;i++)for(j=i+1;j<3;j++){t=a[i][j];a[i][j]=a[j][i];a[j][i]=t;}}用列指针:voidat(int*a,intn){inti,j,t;for(i=0;i<n;i++)for(j=i+1;j<n;j++){t=a[i*n+j];a[i*n+j]=a[j*n+i];a[j*n+i]=t;}}优点:通用在编通用函数时,一般使用列指针。10.4字符串的指针和指向字符串的指针变量■字符串的表示形式可用两种方法访问字符串:①用字符数组存放字符串②用字符指针指向一个字符串main(){charc[5]=”abc”;定义字符数组,并将字符串存入char*p1=c,*p=”abc”;定义指针变量,指向字符串printf(“%s”,c);通过数组名访问字符串printf(“%s”,p);通过指针变量访问字符串printf(“%-c”,*(p+3));通过指针变量访问字符}cabc\0abc\010001000p与其它一维数组的指针相比,字符串的指针有其独特之处:①可以通过指针对字符串进行整体访问。②对字符串的操作依赖于结束符。③可以整体赋初值。④有各种字符串处理函数。本节重点掌握:①通过数组和通过指针操作字符串的基本方法。②常用的字符串处理方法。例:字符串拷贝操作。main(){chara[]=”abcdef”,b[20];inti;for(i=0;*(a+i)!=’\0’;i++)*(b+i)=*(a+i);*(b+i)=’\0’;printf(“%s”,b);}main(){chara[]=”abcdef”,b[20],*p1,*p2;p1=a;p2=b;for(;*p1!=’\0’;p1++,p2++)*p2=*p1;*p2=’\0’;printf(“%s”,b);}用指针变量处理将拷贝操作编成一函数:voidcopy_string(char*from,char*to){for(;*from;from++,to++)*to=*from;*to=0;}还可以改成:voidcopy_string(char*from,char*to){for(;*from;)*to++=*from++;*to=0;}字符串合并函数:voidappend_string(char*from,char*to){for(;*to;to++);for(;*from;)*to++=*from++;*to=0;}阅读程序:voidf(char*c)main(){{c+=2;charc[20]=”abcdef”;(*c)++;f(c+1);c++;*c=0;printf(“%s”,c);}} ■内存空间的动态分配在程序设计中,对于要处理的批量数据,我们往往是选用数组作为存放这些数据的数据结构,然而,数组有一个明显的缺点,就是在定义数组时,其长度必须是常值,无法根据需要动态地定义。这样,在很多情况下,不是定义的数组长度不够,就是定义太长以至于浪费。采用动态分配可以克服这一缺点,并且可以随时释放。动态分配内存空间步骤:①定义一指针变量。②申请一片内存空间,并将其首地址赋给指针变量。此时便可通过指针变量访问这片内存。③用完后释放这片内存空间。 int*p;p=malloc(byte);……free(p);以上函数的原形在stdio.h中。p例:对n个学生的分数排序后输出。#include“stdio.h”voidsort(int*a,intn){┈}main(){int*a,j,n;scanf(“%d”,&n);a=malloc(n*sizeof(int));if(!a)exit(0);for(j=0;j<n;j++)scanf(“%d”,a+j);sort(a,n);for(j=0;j<n;j++)printf(“%5d”,a[j]);free(a);}10.5函数的指针和指向函数的指针变量■用函数指针变量调用函数可以用指针变量指向一个函数,一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针。可以用指针变量指向函数,然后通过该指针变量调用此函数。intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}main(){int(*p)();定义指向函数的指针变量pinta,b,c;p=max;将p指向函数maxscanf(“%d%d”,&a,&b);c=(*p)(a,b);通过p调用函数max等效于c=max(a,b);printf(“\n%d”,c);}■把指向函数的指针变量作为函数参数指向函数的指针变量最常见的用途是把它作为函数的参数,用于接受主调函数传来的某一函数的入口地址,从而在被调函数中可以通过该指针变量调用它所指向的函数,这样,被调函数中就可实现非固定函数的调用,以达到编写通用函数的目的。例:用矩形法编写一个通用的求定积分的函数。关键问题:如何处理被积函数是未知的。doubleintgral(doublea,doubleb,intn,double(*f)()){inti;doubleh,x,y,s=0;h=(b-a)/n;for(i=1;i<=n;i++){x=a+(i-1)*h;y=(*f)(x);s+=h*y;}return(s);}doublef1(doublex){return(3*x*x+2*x-1);}main(){doubles;s=integral(1.0,2.0,100,f1);}第十一章结构体11.1概述在实际应用中,有不少应用问题如果只采用已学的变量和数组作为数据结构显得很不方便。例:输入100个学生的学号、姓名和考试成绩,编写程序找出高分者和低分者。用变量和数组作数据结构可编写程序如下:main(){inti,num,maxnum,minnum;charname[20],maxname[20],minname[20];intscore,maxscore,minscore;maxscore=0;minscore=100;for(i=1;i<=100;i++){scanf(%d%s%d”,&num,name,&score);if(score>maxscore){maxscore=score;maxnum=num;strcpy(maxname,name);}if(score<minscore){minscore=score;minnum=num;strcpy(minname,name);}}输出}明显缺点:①变量过多,同一学生的各个数据无联系,没有整体概念,不便管理。②操作不便(如更新过程)。显然,选用一种能把一个学生的数据构造成一个整体的构造型数据结构更合适,但不能是数组。对于这种情况,可以将一个学生的数据定义为一个结构体类型: structstudent类型名{intnum;成员表charname[20];intscore;};定义了一个结构体类型,它包含三个成员。11.2定义结构体类型变量的方法前面定义的结构体类型只是一种“模型”,还必须定义结构体变量后才能存放数据。定义结构体变量有三种方法:1、先定义结构体类型再定义结构体变量定义了结构体类型后:structstudentst,stmax,stmin;类型符变量名定义了三个结构体变量,每个变量包含三个成员,每个变量可存放一个学生的数据。2、在定义结构体类型的同时定义结构体变量structstudent{intnum;charname[20];intscore;}st,stmax,stmin; 3、直接定义结构体类型变量struct不出现类型名{intnum;charname[20];intscore;}st,stmax,stmin;常用第一种方法说明:①类型与变量不同,只对变量分配空间与操作。②对成员可以单独使用,相当于普通变量。③成员也可以是一个结构体变量。structdatestructstudent{intmonth;{intnum;intday;charname[20];intyear;structdatebirthday;};}st1,st2;④成员名可以与程序中的变量名相同,两者代表不同的对象。11.3结构体变量的引用■成员引用可以对成员单独引用,形式为:结构体变量名.成员名成员运算符st.num=1001;st.score=90;strcpy(st.name,”Li”);printf(“%d%s%d”,st.num,st.name,st.score);scanf(“%d%s%d”,&st.num,st.name,&st.score);可以引用成员的地址如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员,只能对最低级的成员进行存取与运算。st1.birthday.year=1960;st1.birthday.month=5;st1.birthday.day=15;■整体引用可以对结构体变量进行整体赋值:stmax=st;将st中的所有内容赋值给stmax。对结构体变量的整体操作只限于赋值操作和参数传递,而且要求类型一致。不能对结构体变量进行整体输入输出。结构体应用举例:编写程序输入100个学生的学号、姓名和考试成绩,找出高分者和低分者。structstudent{intnum;charname[20];intscore;};main(){inti;structstudentst,stmax,stmin;stmax.score=0;stmin.score=100;for(i=1;i<=100;i++){scanf(“%d%s%d”,&st.num,st.name,&st.score);if(st.score>stmax.score)stmax=st;if(st.score<stmin.score)stmin=st;}printf(“\n%5d%15s%5d”,stmax.num,stmax.name,stmax.score);printf(“\n%5d%15s%5d”,stmin.num,stmin.name,stmin.score);}11.4结构体变量的初始化对结构体变量可以在定义时指定初始值structstudent{intnum;charname[20];intscore;}st={1001,”wang”,95};11.5结构体数组可以定义结构体数组来存放批量数据。■结构体数组的定义structstudent{intnum;charname[20];intscore;};structstudenta[100];定义a数组,可以存放100个学生的数据。a数组的每个元素又是一个结构体变量。■结构体数组的初始化在定义结构体数组的同时指定初值。structstudent{intnum;charname[20];intscore;};structstudenta[2]={{1001,”LiLi”,85},{1002,”wang”,90}};或:structstudent{intnum;charname[20];intscore;}a[2]={{1001,”LiLi”,85},{1002,”wang”,90}};■结构体数组元素的引用成员引用:a[0].num=1001;strcpy(a[0].name,”wang”);a[0].score=85;整体引用:a[1]=a[0];与普通数组元素的引用相同■结构体数组的应用输入100个学生的学号、姓名和考试成绩,然后按从高分到低分的顺序排列后输出。structstudent{intnum;charname[20];intscore;};main(){inti,j;structstudenta[100],t;for(i=0;i<100;i++)scanf(“%d%s%d”,&a[i].num,a[i].name,&a[i].score);for(i=0;i<99;i++)for(j=i+1;j<100;j++)if(a[i].score<a[j].score){t=a[i];a[i]=a[j];a[j]=t;}整体引用for(i=0;i<100;i++)printf((“\n%5d%15s%5d”,a[i].num,a[i].name,a[i].score);}例:(p266例11.2)对候选人得票的统计程序。设有三个候选人,每次输入一个得票候选人的名字,要求最后输出各候选人的得票结果。#include“string.h”structperson{charname[20];intcount;}leader[3]={“Li”,0,”zhang”,0,”wang”,0};main(){inti,j;charleader_name[20];for(i=1;i<=100;i++){scanf(“%s”,leader_name);for(j=0;j<3;j++)if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;}printf(“\n”);for(i=0;i<3;i++)printf(“\n%15s%5d”,leader[i].name,leader[i].count);}11.6指向结构体类型数据的指针■指向结构体类型变量的指针structstudentst,st1;structstudent*p;p=&st;定义指向结构体类型数据的指针变量p通过指针变量引用结构体变量:①成员引用(*p).num=1001;或p->num=1001;(*p).score=85;或p->score=85;strcpy((*p).name,”wang”);或strcpy(p->name,”wang”);②整体引用st1=*p;等效于st1=st;■指向结构体数组的指针structstudenta[100];structstudent*p;p=a;通过指针变量引用结构体数组元素:①成员引用(*p).num=1001;或p->num=1001;(*p).score=85;或p->score=85;strcpy((*p).name,”wang”);或strcpy(p->name,”wang”); 一般地:(*(p+i)).num=1001;或(p+i)->num=1001;(*(p+i)).score=85;或(p+i)->score=85;strcpy((*(p+i)).name,”wang”);或strcpy((p+i)->name,”wang”);也可以用下标法:p[i].num=1001;②整体引用*(p+1)=*(p+0);或p[1]=p[0];■用结构体变量和指向结构体的指针作函数参数用结构体变量作函数参数时,对应的实参应该是同类型的结构体变量(或数组元素),参数传递是“值传递”。用指向结构体的指针作函数参数时,对应的实参应该是同类型的结构体变量的地址(或数组的地址),参数传递是“地址传递”。main(){structstudentst={1001,”LiLi”,70};f(st);printf(“\n%5d%10s%5d”,st.num,st.name,st.score);}f(structstudenta){a.score=90;printf(“\n%5d%10s%5d”,a.num,a.name,a.score);}1001LiLi70st1001LiLi70a90main(){structstudentst={1001,”LiLi”,70};f(&st);printf(“\n%5d%10s%5d”,st.num,st.name,st.score);}f(structstudent*a){a->score=90;printf(“\n%5d%10s%5d”,a->num,a->name,a>score);}通过指针变量a可以访问它所指向的结构体。 1001LiLi70st20002000a9011.7用指针处理链表■链表概述链表是一种重要的数据结构─动态数据结构。以具体例子来说明链表的概念及其应用:例:选择合适的数据结构来存放一批学生的学号及考试成绩,以便进一步处理。由于学生人数未知,用静态数据结构不合适。用链表处理较恰当。用链表处理该问题的基本思路:将各学生的数据进行离散存放,来一个学生就分配一小块内存(结点)。并将各结点用指针依次连接起来─链表。每结点应包含下一结点的开始地址。最后一个结点中的指针为空。链头指针指向第一个结点,是访问链表的重要依据。这样的链表称单向链表。head学号成绩指针学号成绩指针学号成绩指针学号成绩指针学号成绩NULL一个结点可用如下结构体描述:typedefstructstudent{intnum;学号intscore;成绩structstudent*next;下一结点的首地址}STU;typedef:自定义类型符(见11.10)■单向链表的建立①输入一个学生的数据。②分配结点空间,数据存入。③将该结点的首地址赋给上一结点的next,若该结点是第一个结点,则赋给头指针。④将该结点的next置为空,表示该结点为当前的最后结点。head学号成绩next学号成绩next学号成绩next学号成绩next学号成绩NULLSTU*creat(){STUst,*p0=NULL,*p,*head=NULL;while(1){scanf("%d%d",&st.num,&st.score);if(st.num<0)break;p=malloc(sizeof(STU));*p=st;(*p).next=NULL;if(p0==NULL)head=p;p0为前一结点的指针else(*p0).next=p;p0=p;}returnhead;}head学号成绩next学号成绩next学号成绩NULL■单向链表的访问以输出为例①通过头指针找到第一个结点.②输出当前结点的内容,并通过next找到后继结点,┄┄,直到next为空.voidoutput(STU*head){STU*p=head;while(p){printf("\n%d%d",(*p).num,(*p).score);p=(*p).next;}}head学号成绩next学号成绩next学号成绩NULL学号成绩next■删除结点操作①按链表的访问方法找到相应结点。②若该结点是第一个结点,则将后继结点指针赋给头指针。若该结点是最后一个结点,则将前缀结点的next置为空。若该结点是中间结点,则将后继结点指针赋给前缀结点的next。③释放该结点所占的内存单元。head学号成绩next学号成绩next学号成绩NULLSTU*delete(STU*head,intnumber){STU*p=head,*p0=NULL;while(p){if((*p).num==number){ if(p==head)head=(*p).next; elseif((*p).next==NULL)(*p0).next=NULL; else(*p0).next=(*p).next; free(p);break;}else{p0=p;p=(*p).next;}}returnhead;}假定要删除某一指定学号的结点■插入操作假定将结点p插入到结点p0的后面,则插入操作的关键为:p->next=p0->next;p0->next=p;head学号成绩next学号成绩next学号成绩next学号成绩NULL第十三章文件3.1文件概述■文件概念所谓文件就是:存储在外部介质上的信息集合。根据存储的介质不同可分为:磁盘文件、磁带文件等。根据内容的不同可分为:程序文件、数据文件等。■使用文件输入输出的必要性这里主要讨论数据文件的输入输出,即如何将文件中的数据“输入”到程序的数据结构中,如何将程序的数据结构中的数据“输出”到文件中。以往的输入输出方法:键盘输入,屏幕输出。这种方法不适用于数据量大的情况。键盘输入和屏幕输出例:main(){inti,a[1000];for(i=0;i<1000;i++)scanf(“%d”,a+i);┊for(i=0;i<1000;i++)printf(“%5d”,a[i]);}缺点:①可能出现重复输入。②输出的数据不能保存,不便于进一步使用。采用文件输入输出可以克服这些缺点。main(){inti,a[1000];for(i=0;i<1000;i++)scanf(“%d”,a+i);┊for(i=0;i<1000;i++)printf(“%5d”,a[i]);}}文件文件■C文件分类按在磁盘上存储的形式不同,可分为:文本文件:以ASCII字符存放—可见、可编辑、占空间大。二进制文件:以二进制形式存放—不可见、不可编辑、占空间小。使用时可根据需要选择。13.2文件类型指针每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息。这些信息保存在一个FILE类型的结构体变量中。若FILE*fp;则fp就称为指向文件类型的指针变量。访问文件通过文件指针进行。FILE结构体类型是由系统定义的。具体定义如下:typedefstruct{shortlevel;缓冲区“满”或“空”的程度unsignedflags;文件状态标志charfd;文件描述符unsignedcharhold;如无缓冲区不读取字符shortbsize;缓冲区的大小unsignedchar*buffer;缓冲区的位置unsignedchar*curp;当前读写指针unsignedistemp;临时文件,指示器shorttoken;用于有效性检验}FILE;13.3文件的打开与关闭对文件的读写之前应“打开”该文件。使用结束后“关闭”此文件。■文件的打开(fopen函数)用fopen函数实现对文件的打开。fopen函数调用的一般形式:FILE*fp;fp=fopen(文件名,读写方式);例如:fp=fopen(“a1.txt”,”r”);以只读方式打开文件a1.txt。fopen函数返回指向a1.txt文件的指针,即fp是指向a1.txt文件的指针变量,往后就可以通过fp访问a1.txt文件。文件读写方式:“r”按只读方式打开一个文本文件“w”按只写方式打开一个文本文件“a”按追加方式打开一个文本文件“rb”按只读方式打开一个二进制文件“wb”按只写方式打开一个二进制文件“ab”按追加方式打开一个二进制文件“r+”按读写方式打开一个文本文件“w+”按读写方式建立一个新的文本文件“a+”按读写方式打开一个文本文件“rb+”按读写方式打开一个二进制文件“wb+”按读写方式建立一个新的二进制文“ab+”按读写方式打开一个二进制文件说明:(1)不能用”r”方式打开一个不存在的文件,”r”方式只读不能写。(2)“w”方式只写不能读,具有建立和覆盖功能。(3)调用fopen函数时,如果返回NULL则表示打开不成功。■文件的关闭(fclose函数)在使用完一个文件后应用fclose函数关闭文件,形式为:fclose(文件指针);如:fclose(fp);关闭后fp不再指向该文件。13.4文件的读写文件打开后,就可以对它进行读写了。■文本文件的读写即如何将以文本方式存放的文件输入到程序的数据结构中。如何将程序的数据结构中的数据以文本方式输出到文件中。用于对文本文件读写的函数有:fscanffprintffgetc,getcfputc,putcfgetsfputs以例子说明fscanf和fprintf的使用。例:已知文本文件f1.txt中存放有100个学生的分数,要求读入这些数据,并按从高到低的顺序排序后输出到另一文件中。#include“stdio.h”voidsort(int*a,intn){……}main(){inti,a[100];FILE*fp;fp=fopen(“f1.txt”,“r”);if(fp==NULL)exit(0);定义一个指向文件的指针变量打开文件,使fp指向文件f1.txtfor(i=0;i<100;i++)fscanf(fp,”%d”,a+i);fclose(fp);sort(a,100);fp=fopen(“f2.txt”,“w”);for(i=0;i<100;i++)fprintf(fp,”%4d”,a[i]);fclose(fp);}从fp所指的文件中读数据关闭fp所指的文件注意:文本文件的输入格式要与文件中的数据格式匹配。■二进制文件的读写即如何将以二进制方式存放的文件输入到程序的数据结构中。如何将数据结构中的数据以二进制方式输出到文件中。读写函数:freadfwritegetwputw例:将前例中的排序结果改用二进制方式输出到文件f3.dat中。#include“stdio.h”voidsort(int*a,intn){……}main(){inti,a[100];FILE*fp;fp=fopen(“f1.txt”,“r”);if(fp==NULL)exit(0);for(i=0;i<100;i++)fscanf(fp,”%d”,a+i);fclose1(fp);sort(a,100);fp=fopen(“f3.dat”,“wb”);fwrite(a,sizeof(int),100,fp);fclose(fp);}数据的开始地址数据的每一项的长度数据的项数文件的指针如果要将二进制文件f3.dat读到数组中,则有:#include“stdio.h”main(){inta[100];FILE*fp;fp=fopen(“f3.dat”,“rb”);if(fp==NULL)exit(0);fread(a,sizeof(int),100,fp);fclose(fp);┊}13.5文件的定位文件中有一个位置指针,指向当前读写位置。如果顺序读写一个文件,每次读写完一个字符后,该位置指针自动指向下一个字符位置。如果想改变这样的规律,强制使位置指针指向指定位置,可以用有关函数。■rewind函数rewind函数的作用是使位置指针重返回文件的开头。例:对文本文件f1.txt中的100个分数求超过平均分的人数。#include“stdio.h”main(){inti,a,n=0;floataver=0;FILE*fp;fp=fopen(“f1.txt”,“r”);for(i=0;i<100;i++){fscanf(fp,”%d”,&a);aver+=a;}aver/=100;rewind(fp);for(i=0;i<100;i++){fscanf(fp,”%d”,&score);if(score>aver)n++;}fclose(fp);printf(“\n%d”,n);}■fseek函数和随机读写使用fseek函数可以将位置指针指向所需的位置。fseek函数调用的一般形式:fseek(文件指针,位移量,参考点);以起始点为基准,向前移动的字节数0或SEEK_SET文件开始1或SEEK_CUR当前位置2或SEEK_END文件末尾例:如果fp是指向一个存放100个整数的二进制文件,要读取第50个数到变量n时:fseek(fp,sizeof(int)*(50-1),SEEK_SET);fread(&n,sizeof(int),1,fp);例:如果fp是指向一个存放100个整数的文本文件,并已知每个数按3位数字的定长格式存放,要读取第50个数到变量n时:fseek(fp,3*(50-1),SEEK_SE);fscanf(fp,”%3d”,&n);若要从当前位置跳过10个数后读取一个数:fseek(fp,3*10,SEEK_CUR);fscanf(fp,”%3d”,&n);例:已知文本文件f5.txt中存放有100个学生的学号、姓名和考试成绩;要求从键盘输入任一学号,检索出相应学生的数据。说明:(1)文件f5.txt中每行为一个学生的数据,按定长格式存放,依次为:学号(整数,占5格)、姓名(占10格)、成绩(整数,占4格)。(2)按学号从小到大的顺序连号存放,起始学号为1001。#include“stdio.h”typedefstruct{intnum;charname[20];intscore;}STU;main(){intno;STUst;FILE*fp;fp=fopen(“f5.txt”,”r”);scanf(“%d”,&no);fseek(fp,(no-1001)*19,0);fscanf(fp,”%5d%10s%4d”,&st.num,st.name,&st.score);printf(“\n%5d%10s%4d”,st.num,st.name,st.score);fclose(fp);}1001LiLi901002WangPing1001003HuHeng75┊如果是二进制文件呢?上例的检索方法称为“定位检索”。如果是非定长格式,则需要用“遍历检索”。while(!feof(fp)){fscanf(fp,”%d%s%d”,&st.num,st.name,&st.score);if(st.num==no){printf(“\n%5d%10s%4d”,st.num,st.name,st.score);break;}}速度慢,但不受限制综合例:已知文本文件f1.txt中存放有武汉市所有公民的有关性别和年龄的数据,请编写程序分别找出其中10名男寿星和10名女寿星,并将20名寿星的数据以文本文件的方式存入到文件f2.txt中(先男后女)。说明:① 文件f1.txt中每行为一个公民的数据,共有3项,依次为:姓名(不超过10个字符)、性别(0表示男,1表示女)和年龄(整数),项间以空格分隔。② 未给出公民个数,将文件中的数据读完为止。算法思想:开辟一个存放20名寿星数据的结果表a(结构体数组),然后逐个读取公民数据,每读取一个就向a中“判断插入”一个,男性公民往前段插,女性公民往后段插。读一个公民的数据到p读完否?NYWanghao0100Liming098┊wudan199xiaofang195┊男性插入女性插入寿星表a#include<stdio.h>typedefstruct{charname[10];intsex;intage;}PEP;插入函数,将一个公民的数据插入到寿星表voidinsert(PEP*a,intn,PEPt){inti,j;if(t.age<a[n-1].age)return;for(i=0;i<n;i++)if(t.age>a[i].age)break;for(j=n-1;j>i;j--)a[j]=a[j-1];移位a[i]=t;插入}main(){intj;PEPp,a[20];FILE*fp;fp=fopen(“f1.txt”,”r”);if(!fp)exit(0);for(j=0;j<20;j++)a[j].age=0;while(!feof(fp)){fscanf(fp,”%s%d%d”,p.name,&p.sex,&p.age);insert(a+10*p.sex,10,p);}fclose(fp);fp=fopen(“f2.txt”,”w”);for(j=0;j<20;j++)fprintf(fp,”\n%15s%2d%5d”,a[j].name,a[j].sex,a[j].age);fclose(fp);}此课件下载可自行编辑修改,此课件供参考!部分内容来源于网络,如有侵权请与我联系删除!
/
本文档为【雄县济康医院专家解答哪些孕妇易出现早产】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索