<ins id="h3npf"><span id="h3npf"></span></ins>
<cite id="h3npf"><span id="h3npf"></span></cite><progress id="h3npf"></progress>
<cite id="h3npf"></cite>
<listing id="h3npf"><dl id="h3npf"><progress id="h3npf"></progress></dl></listing>
<cite id="h3npf"><video id="h3npf"></video></cite>
<cite id="h3npf"><video id="h3npf"><menuitem id="h3npf"></menuitem></video></cite>
<ins id="h3npf"></ins><var id="h3npf"><video id="h3npf"></video></var><cite id="h3npf"></cite><cite id="h3npf"></cite>

C语言入门教程

来源:百度  [  文档由 RaNHaOFaN110 贡献   ]  责编:从大磊  |  侵权/违法举报

C语言程序设计Copyer:Vigiking第一章 计算机语言与C语言概述1.1 计算机语言概念 ■计算机语言定义 计算机能够识别和接受的语言。 要使计算机按自己的意图工作,必 须使用计算机所能接受、理解和执 行的指令指挥计算机工作。■计算机语言的种类机器语言计 算 机 语 言?#22270;?#35821;言(面向计算机)汇编语言BASIC 入门语言 F77 科学计算 高级语言 Foxpro 数据库管理 (面向问题 ) C 多用途…… ……?机器语言 最早问世,用二进制代码构成指令。 如: 100000 (+) 110000 (-) 用机器语言编程的缺点: ─繁琐、不直观、不易调试。 如计算y=2x2+3x-1需要七八条指令。 ─移植性差。 依赖于计算机。?汇编语言 用符号构成指令,如:MOV、ADD 用汇编语言编程: 相对直观,但仍繁琐,仍是面向计算 机的语言。汇编语言是计算机间接接受的语言?高级语言 与?#22270;?#35821;言相比,有根本性的区别: 是面向问题的语言。 高级语言的一条指令(语句): y=2*x*x+3*x-1; 对应于:y=2x2+3x-1 y=sin(x); 对应于:y=sinx 用高级语言编程: 直观、易懂、移植性好(不依赖于具体计 算机)上机运行高级语言程序需经过编译:编译高级语言源程序执行机器指令 目的程序 结果编译程序要上机完成一个计算问题,主要的任务就是 用高级语言编写出相应的源程序。即至少要 学会一种计算机语言。1.2C语言的特点集高级语言和?#22270;?#35821;言的优点于一身: ●能实现?#22270;?#35821;言的大部分功能(如直接 访问内存物理地址、进?#24418;?#25805;作等)。 ●图形功能强。 ●运算符和数据结构丰富。 ●语法限制不太?#32454;瘢?#31243;序设计自由度大。 ●生成目标代码质量高,程序执行效率高。1.3简单的C程序介绍例1:main() 主函数说明 { 程序框架 printf(“abcdef”); 函数体 } 语句程序的功能是输出字符串:abcdef例2:求两数之和。 main() { int a,b,c; a=100; b=50; c=a+b; printf(“\ c=%d”,c); }程序运行结果:c=150a b c例3:求两数中的最大值。 函数类型 函数名 形参 main() int max (int x,int y) { int a,b,c; { int z; scanf(“%d,%d”,&a,&b); if(x>y) z=x; c=max(a,b); else z=y; printf(“\max is:%d”,c); return(z); } }a b c3 5 5x y z3 5 5(两个函数组成)总结上例可知: (1) C程序由函数构成。 (2) 函数由两部分组成: 函数说明部分:函数名、函数类型、形 参名、形参类型。 函数体:实现函数的具体操作;由语句 构成。 (3) 程序总是从main函数开始执行。 (4) 书写格式自由。 (5)语句必须有分号。 :第二章2.1 算法的概念算法要利用计算机处理问题,光学习语言的语法规则还不够,最重要的是要学会针对各类

因转码可能存在排版等问题,敬请谅解!以下文字仅供您参考:

C语言程序设计

Copyer:Vigiking

第一章 计算机语言与C语言概述

1.1 计算机语言概念 ■计算机语言定义 计算机能够识别和接受的语言。

要使计算机按自己的意图工作,必 须使用计算机所能接受、理解和执 行的指令指挥计算机工作。

■计算机语言的种类

机器语言

计 算 机 语 言

?#22270;?#35821;言

(面向计算机)

汇编语言

BASIC 入门语言 F77 科学计算 高级语言 Foxpro 数据库管理 (面向问题 ) C 多用途

…… ……

?机器语言 最早问世,用二进制代码构成指令。

如: 100000 (+) 110000 (-) 用机器语言编程的缺点: ─繁琐、不直观、不易调试。

如计算y=2x2+3x-1需要七八条指令。

─移植性差。

依赖于计算机。

?汇编语言 用符号构成指令,如:MOV、ADD 用汇编语言编程: 相对直观,但仍繁琐,仍是面向计算 机的语言。

汇编语言是计算机间接接受的语言

?高级语言 与?#22270;?#35821;言相比,有根本性的区别: 是面向问题的语言。

高级语言的一条指令(语句): y=2*x*x+3*x-1; 对应于:y=2x2+3x-1 y=sin(x); 对应于:y=sinx 用高级语言编程: 直观、易懂、移植性好(不依赖于具体计 算机)

上机运行高级语言程序需经过编译:

编译

高级语言源程序

执行

机器指令 目的程序 结果

编译程序

要上机完成一个计算问题,主要的任务就是 用高级语言编写出相应的源程序。

即至少要 学会一种计算机语言。

1.2

C语言的特点

集高级语言和?#22270;?#35821;言的优点于一身: ●能实现?#22270;?#35821;言的大部分功能(如直接 访问内存物理地址、进?#24418;?#25805;作等)。

●图形功能强。

●运算符和数据结构丰富。

●语法限制不太?#32454;瘢?#31243;序设计自由度大。

●生成目标代码质量高,程序执行效率高。

1.3

简单的C程序介绍

例1:

main() 主函数说明 { 程序框架 printf(“abcdef”); 函数体 } 语句

程序的功能是输出字符串:abcdef

例2:求两数之和。

main() { int a,b,c; a=100; b=50; c=a+b; printf(“ c=%d”,c); }

程序运行结果:c=150

a b c

例3:求两数中的最大值。

函数类型 函数名 形参 main() int max (int x,int y) { int a,b,c; { int z; scanf(“%d,%d”,&a,&b); if(x>y) z=x; c=max(a,b); else z=y; printf(“max is:%d”,c); return(z); } }

a b c

3 5 5

x y z

3 5 5

(两个函数组成)

总结上例可知: (1) C程序由函数构成。

(2) 函数由两部分组成: 函数说明部分:函数名、函数类型、形 参名、形参类型。

函数体:实现函数的具体操作;

由语句 构成。

(3) 程序总是从main函数开始执行。

(4) 书写格式自由。

(5)语句必须有分号。

第二章

2.1 算法的概念

算法

要利用计算机处理问题,光学习语言

的语法规则还不够,最重要的是要学会

针对各类型的问题,拟定出?#34892;?#30340;解题

方法和步骤。

解题方法和步骤就是算法。

算法:

为了解决一个问题而采取的有限步骤。

计算机算法:

如何使计算机一步一步地工作的具体过程。

利用计算机处理问题的步骤: 1)设计好算法——算法设计;

2)用计算机语言实现算法——程序设计。

算法必须是“?#34892;А?#30340;。

算法设计还要充分考虑算法的好坏。

衡量算法好坏的主要标准: ① 程序简练。

② 执行速度快。

③ 占空间少。

例:考虑 s=∑i

1

10

的算法。

算法①:直接表达。

直接用语句 s=1+2+3+4+5+6+7+8+9+10

当项数较多时该算法不适用

算法②:迭代法(累加求和法) s=1+2+3+4+5+6+7+8+9+10 算法步骤: s i ① 使s=0 + 10 6 3 1 0 5 4 3 2 1 ② 使i=1 累加器 记数器 ③ s+i→s 该算法通用,是好算法 ④ i+1→i ⑤ 若i≤10转③,否则转⑥ ⑥ 输出s

2.2

算法的表示

算法需要?#22411;?#19968;的表示方法 常用的表示方法有: 自然语言 流程图 结构化流程图 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的值 特点?#21644;?#20439;易懂、文字冗长、含义不大?#32454;瘛?p> 2、流程图 用流程图符号表示算法。

常用的流程图符号

起止框 处理框 输入输出框 流程线

判断框

对于计算 s=1+2+3+4+5+6+7+8+9+10 用流程图表示为:

s+i → s

0→ s

S+i → s

i+1 → i Y i≤10

1→ i

N

输出s

直 观 形 象 , 易 于 理 解 , 次 序 清 楚

3、结构化流程图

传统的流程图有一个弊端:对流程线没 有?#32454;?#30340;限制,对于较复杂的算法可能会 变成乱麻一般(BS型算法)。

为克服这一弊端,提出了由三个基本结构 组成算法流程图的思想: 结构化流程图

三个基本结构: ① 顺序结构 按固定顺序(从上到下或从左?#25509;遙?#25191;行 的结构。

a A

B

b

② 选择结构 根据条件P选择执行哪一个分支。

a

成立

成立 不成立

不成立

p A B

b

例:计算

y= 1/x y= 10000 当x≠0时 当x=0时 的算法流程图图:

选择结构

输入x Y N

X=0?

10000→y

输出y

1/x→y

③ 循环结构 重复执行某些操作的结构。

分为两种: 当型循环和直到型循环。

a a

A

P1 N b Y

A

P2 Y b N

当型循环

直到型循环

可以看出,每个基本结构都只有 一个入口和一个出口,因此,用三 个基本结构构成的流程图不会象乱 麻一般,用三个基本结构构成的流 程图就成为结构化流程图,用结构 化流程图描述的算法称为结构化算 法,相应的程序设计就称为结构化 程序设计。

观察前例:

顺 序 结 构

0→ s 1→ i y

S+i → s i+1 → i

循 环 结 构

i≤10 n

输出s

4 N-S流程图

N-S流程图的三个基本结构: 顺 序 结 构

A

P

成立

B

A

选 不成立 择 结 B 构

B

循 环 结 构

当P1

A 直到P2

例:计算 y= 1/x y= 10000 的N-S流程图:

输入x

X=0? 是

当x≠0时 当x=0时

10000→y

输出y

1/x→y

例: 计算 s=1+2+3+4+5+6+7+8+9+10 的N-S流程图:

0→ s 1→ i 0→ s 1→ i

i≤10

s+i → s

i+1 → i

直到i>10

s+i → s i+1 → i 输出s

输出s

直到型

当型

第三章

3.1

数据类型、运算符 与 表达式

C 的数据类型

●基本类型 (整型、实型、字符型、枚举型) ●构造类型 (略) ●指针类型 (略)

●空类型

各类型包含常量与变量

3.2

常量与变量

■常量与符号常量 常量 在程序运行过程中其值保持不变的量。

符号常量

用来代表一个常量的标识符。

#define PI 3.1415926

例: #define PI 3.1415926 main() { float r=2,c; c=2*PI*r; printf(“%f”,c); }

■变量 其值可以改变的量。

变量的三要素: ① 变量名 每个变量有一个名字,作为识别该变量的 标识符。

② 变量的值 每个变量有一个值,变量的值是随时 可以改变的。

③变量的存储单元 每个变量占据一个内存单元,用于存放变量 的值。

变量名

a 变量值

3

存储单元

变量的命名规则: 由字母、数字和下划线组成 以字?#23500;?#19979;划线开头

a、x1、y_2、_b1、_1c 1x、a+2、Ф、Ω 合法 不合法

变量必须先定义后使用。

程序中何时使用常量?何时使用变量?

3.3 整型数据 ■整型常量 即整常数,c的整常数有三种形式: ①十进制整数 与数学中的整数一致,如:100,123,15等。

②八进制整数 以0开头的整数,如:010,07,020等。

③十六进制整数 以0x开头的整数,如:0x10,0xff,0x2a等。

■整型变量 用于存放整数的变量。

分4种类型: ①基本型:int a 16位,可表示的数值范围:-32768—32767 ②短整型:short int b 16位,可表示的数值范围:-32768—32767 ③长整型:long int c 32位,数值范围:-2147483648—2147483647

④无符号型:加上 unsigned 只存放正数。

如:unsigned int x 变量x为无符号整数,16位全表示数码, 数值范围:0—65535 在程序设计中,如果要使用整型变 量,必须首先选择以上类型符来定义变量, 然后才能使用;

例: main() { int a,b,c; a=100; b=50; c=a+b; printf(“%d”,c); }

定义

使用

一般根据什么原则选择变量的类型?

3.4

实型数据

■实型常量 可使用两种形式表示: ①小数形式:如 1.23, 3.1415926 ②指数形式:如 1e-20 1.23e5 15.48

■实型变量 用于存放实数的变量 分单精度和双精度两种: float a,b 定义a和b为单精度型变量 32位,7?#25381;行?#25968;字,10-38—1038 double x,y 定义x和y为双精度型变量 64位,15?#25381;行?#25968;字,10-308—10308

例: main() { float r,c; double r,c; r=5; c=2*3.1415926*r; printf(“%f”,c); }

3.5

字符型数据

■字符常量 用单引号括起来的一个字符。

’a?,?x?,?*?,?1?等

除此外,以’\?开头的字符如’?,??等 称为转义字符,祥见书表3.3

■字符型变量

用于存放字符的变量。

char c1,c2 定义c1和c2为字符型变量 c1=?a?; c2=?b?; 字符赋值

字符型变量存放一个字符,占据一个字节

■字符型数据的存储形式 a 存放ASCII码 不是 而是 97 如字符’a?在内存中存放97,’b? 存放98。

与整数的存储形式一致,它?#20405;?#38388;可以通 用 一个字符数据既可以作字符用,也可以作 整数用(取其ASCII代码)。

如:32+?a?相当于 32+97 若 int x; char c; 则 x=?a?; c=97; x=97; c=?a?; 都允许

■字符串常量 用双引号括起来的字符序?#23567;?p>如:”abcde”,”china” ”a”也属字符串。

注意”a”与’a?的区 别。

对于: char c; c=”a”; 用法错误

字符串中每个字符各占一个字节,并且在 字符串结尾加上一个结束标记’\0?

如:”china” 在内存中占6个字节。

c h i n a \0

C语言中专门的字符串变量,可用字符数 组存放(以后介绍)。

3.6 变量赋初值 在定义变量的同时给相应的变量赋初值。

如: int a=3; a 3 float b=5.2; char c=?a?; int x=y=z=6; 效果: 在给变量分配内存单元的同时在相应的单 元中存放初值。

3.7

各数值型数据间的混合运算

整型、实型、字符型数据间可以进行混合运 算,如: 10-?a?*1.5 运算时,参加运算的两个数据如果类型不同, 则首先将其类型转换成一?#30053;?#36816;算,转?#36824;?#21017; 是: 将优先级低的类型转?#22351;接?#20808;级高的类型

数据类型的优先级:

double long unsignde 低 float

int

char

算术运算符与算术表达式 ■基本的算术运算符 + - * / % ■算术表达式 用算术运算符将运算对象连接起来的式子 用于表达数学公式的式子 如:2*x+y-1/a 表达式经过运算最终得到一个值: 算术表达式的值

3.8

■运算符的优先级与结合性 优先级: 在对表达式求值时,如果存在多个运算符,则 运算的先后次序按运算符的优先级别从高到底进 行。

运算符的优先级关系为: 高:* / % 低:+ 如:a-2*x 先算 * 2*(a+2) 有括号的情况?

结合性: 如果在一个运算对象两边的运算符的优先?#26029;?同,则按规定的“结合方向”处理。

如:a-b+c b与-结合是从左?#25509;遙?#31216;“左结合性”。

b与+结合是从右到左,称“右结合性”。

每个运算符都有相应的优先级和结合性。

基本算术运算符都是左结合性。

计算表达式例: 2+?A?-1/2.0 1+3/2-1 构造表达式例 2x2+3x-1 a+b a+b

a-b

2*x*x+3*x-1 (a+b)/(a-b) ? a+b/a-b

(*不能省)

a-b x+y x-y

(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)

应用举例:

int a=200,b=300,c; c=(long)a*b/100; ? c=(long)(a*b)/100; c=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; a b=a++; 6 5 c=--a-b++; d=(a++)-(++b)+c--;

b 7 6 5

c -1 0

d -2

两种特殊情况: ① k=(i++)+(i++)+(i++)

i+++j

是 i+(++j) 还是 (i++)+j ?

i++虽然与i=i+1等效,但使用自增自减 运算符的代码优化程度好,因而经常使用;

但用时需特别小心。

3.9 赋值运算符和赋值表达式

■赋值运算符

“=”称赋值运算符,其作用是将一个数据

赋给一个变量。

如: a=5

不要理解为“等号”。

执行赋值运算的结果,是将右边的数据存

入左边变量所对应的内存单元?#23567;?p> ■赋值规则 如果赋值运算符两侧的类型不一致,则在赋 值时要进行类型转换,转?#36824;?#21017;为: ●实型→整变量 舍去小数部分。

int a=5.5; a?#24418;?。

●整型→实变量 数值不变,以浮点形式存储。

●字符型→整变量 放在整形变量低8位。

保持原值不变原则。

int a=?A?;

■复?#32454;?#20540;运算符 在赋值运算符前加上其它运算符,可以构成 复?#32454;?#20540;运算符。

a+=3 —— a=a+3 b-=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) 属于高效?#35797;?#31639;符。

■赋值表达式 主要实现赋值运算的表达式。

一般形式: <变量>=<表达式> 如: a=5 y=2*x+3 a=a+1

不是衡等

作用:将右边表达式的值赋给左边的变量。

赋值表达式的?#31561;?#24038;边变量的值。

赋值表达式右边的<表达式>可以是任何表 达式,如: a=(b=5) 赋值表达式中包含赋值表达式

赋值运算符的优先级低于所有算术运算符,

且是右结合性。

a=(b=5) 与 a=b=5 等效。

例:计算以下表达式的值:

a=b=c=5

a=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

?#27721;?#34920;达式

?#27721;?#20063;是一种运算符,用它对两个表达式

实现连接运算。

3+5,6+8 称?#27721;?#34920;达式。

?#27721;?#34920;达式的一般形式: 表达式1,表达式2 取表达式2的值作为整个?#27721;?#34920;达式的值。

如: a=3*5,a*4 ?#27721;?#34920;达式的值为:60

一个?#27721;?#34920;达式又可以与另一个表达式组成 一个新的?#27721;?#34920;达式,如: (a=3*5,a*4),a+5 因此,?#27721;?#34920;达式的一般形式可以扩展为: 表达式1,表达式2,表达式3,……, 表达式n 取表达式n的值作为整个?#27721;?#34920;达式的值。

?#27721;?#36816;算符的优先级最低,且是左结合性。

?#27721;?#36816;算符只起到连接作用,没有实际操作。

第四章

最简单的C程序设计

C 程序最基本的成分是语句 目前我们已掌握的语句: 变量说明语句: int a,b,c; 表达式语句: x+y; 特别地: a=5; 赋值语句

可以编写简单程序如:

main()

{ int

x,y;

x=5;

y=2*x*x+3*x-1;

} 该程序语法上完整,但还缺少输出。

■数据的输出

用输出函数实现,其中的两种输出函数: 1.putchar 函数 (字符输出函数) 用于输出一个字符。

如: putchar (?a?); putchar (100); char c=?b?; putchar (c);

例:输出单词Boy的完整程序: #include “stdio.h” 注意该语句的作用 main() { char a, b, c;

a=?B?; b=?o?; c=?y?;

putchar (a);

putchar (b);

putchar (c);

}

2. printf函数(格式输出函数) 任意类型、任意格式、任意个数。

例如: int a=100,b=56; printf(“a=%d,b=%d”,a,b);

普通字符 格式说明 格式控制 输出表列

输出结果:a=100,b=56

“%” 后的字符称格式字符,不同格式字符对应不同的数据类型。

d格式符:按整数格式输出 几种用法: %d 不指定宽度,按实际宽度输出 %md 按指定宽度输出,m为宽度 %ld 用于输出长整型数

例: int a=125,b=453;

long

c=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格式符:用于输出字符 char c=?A?; printf(“c=%c,%c”,c,?B?);

输出结果:c=A,B

输出对象既可以是字符变量、字符常量,还 可以是整型表达式。

如:

int a=100;

char

b=?A?;

printf(“%d,%c”,a,a); printf(“%c,%d”,b,b); 输出结果: 100,d A,65

s格式符:用于输出字符串 %s %-ms %ms %m.ns 不指定宽度 指定宽度,左?#31185;?指定宽度,右?#31185;?指定宽度m,只取左端n个字符, 右?#31185;?%-m.ns 指定宽度m,只取左端n个字符, 左?#31185;?p> 例:

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:abcd 4: abc5:abc

f格式符:按小数形式输出实数

%f ?#19978;低?#25351;定宽度(6位小数) 指定宽度m,小数位数n,右?#31185;?p>%m.nf

%-m.nf 指定宽度m,小数位数n,左?#31185;?注意:宽度包括符号和小数点。

例: float a=3.141592654,b=14.326795, c=-125.2468; printf(“a=%f,b=%8.3f,c=%-10.2f”,a,b,c); 输出结果: a=3.141592,b= 14.326,c=-125.24

完整前面的程序:

main()

{

int

x=5;

x,y;

y=2*x*x+3*x-1; printf(“ y=%d”,y); }

程序设计例:

编写程序计算如图中的电流I.

I

U

R1

R2

R3

假设 U=220,R1=30,R2=60,R3=45

算法设计: 程序设计: main() {

I=U/R1+U/R2+U/R3

int U=220,R1=30,R2=60,R3=45; float I; I=U/R1+U/R2+U/R3; printf(“ I=%f”,I); }

正确的程序: main() { int U=220,R1=30,R2=60,R3=45; float I; I=(float)U/R1+(float)U/R2+(float)U/R3; printf(“ I=%f”,I); }

考虑通用: main() { int U,R1,R2,R3; float I; 输入 U,R1,R2,R3 I=(float)U/R1+(float)U/R2+(float)U/R3; printf(“ I=%f”,I); }

■数据的输入 getchar函数(字符输入)

#include “stdio.h” main() { char c; c=getchar(); 等待键盘输入 putchar(c); }

scanf 函数(格式输入)

与printf函数相反。

用于输入若干任意类型的数据。

scanf(“%d%d%d”,&a,&b,&c);

格式控制 地址列表

scanf(“%d%d%d”,&a,&b,&c);

执行此函数时,等待从键盘输入三个整 数给a,b,c 若从键盘输入 3 5 8 则?#20302;?#21363;从键盘缓冲区取出这三个数分 别赋给a,b,c 注意与printf的区别,注意格式的匹配

如: scanf(“%3d%2d%4d”,&a,&b,&c); 若从键盘输入123456789 a=123,b=45,c=6789 若想使a=12,b=5,c=100 则键盘输入应为: 12 5 100 方便的输入格式一般不 指定宽度, 如: scanf(“%d%d%d”,&a,&b,&c);

在键盘输入时,用分隔符把每个数据隔开, 标准的分隔符是空格。

如:123 150 23 若想用?#27721;?#20316;分隔符,则: scanf(“%d,%d,%d”,&a,&b,&c); 不要随便使用普通字符,如使用: scanf(“a=%d,b=%d c=%d”,&a,&b,&c) 对应数据输入: a=123,b=150,c=23

前面的欧姆定律: main() { int U,R1,R2,R3; float I; scanf(“%d%d%d%d”,&U,&R1,&R2,&R3); I=(float)U/R1+(float)U/R2+(float)U/R3; printf(“ I=%f”,I); }

求三角形面积

#include “math.h” main() { float a,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(“ area=%f”,area); }

使用数学函数

使用三角函数

#include “math.h” main() { float x, y; scanf ( “%f”, &x); y=sin(x*3.1415926/180); printf(“ y=%f”,y); }

以弧度为单位

第五章 选择结构程序设计

对于如下的函数计算,算法上属于一个选 择结构。

1/x 当x≠0时

y=

10000 当x=0时 用于实现选择结构的主要是if语句。

if语句的最常见形式为:

if(关系表达式)语句1;

else 语句2;

如: if(x!=0) y=1/x; else y=10000; 其中 x!=0 !=

就是一个关系表达式 就是一个关系运算符

5.1 关系运算符和关系表达式

1、关系运算符

用于进行比较运算的运算符。

共有六种:

< <= > >= = = != ■优先级与结合性: ① 前4?#25191;?#20110;后两种。

② 低于算术运算符而高于赋值运算符。

③ 左结合性。

2、关系表达式 一般形式: 〈表达式〉〈关系运算符〉〈表达式〉

如:a>b

a+b>b+c

经过关系运算后最终有一个值--关系表达 式的值。

关系表达式的值只有 0(假)或1(真)

例:设 a=2, b=4, c=1 式的值:

a>b a+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>y x<y==y<z y>z==x>z y>x>z (x==y-2)<z+1==x+y a=x+y==x+z<y+x!=z+1>x+1

5.2 逻辑运算符和逻辑表达式 有时,只用一个简单的关系表达式无法完整 地表达一个条件,如:

1/x+1/a 10000 当x≠0,a≠0时 其它

y=

其中的条件需要用逻辑表达式来表达: x!=0 &&a!=0 &&就是一种逻辑运算符。

1、逻辑运算符

&& 逻辑与 两个操作数都为真时&&运算结果为真。

|| 逻辑或 两个操作数之一为真时即为真。

! 逻辑非 (单目运算) 操作数为真(假)时为假(真)。

如:若 a=2, b=3, c=0 则: a<b&&b<c 0 a<b||b<c 1 !(a<b) 0

■优先级(由高到低): ! 逻辑非 算术运算符 关系运算符 &&逻辑与 ||逻辑或 赋值运算符

■结合性:左结合性

2、逻辑表达式 实际上,前面所举例子即为逻辑表达式: a<b&&b<c a<b||b<c !(a<b) 逻辑表达式的?#20302;?#26679;只有1和0,但参加逻辑 运算的操作数可以是任意类型的数据,可以是 任意大小。

例: a+b&&b+c 是合法的逻辑表达式。

此时以0代表假,非0代表真。

例:设 a=2, b=3, c=0 , 计算以下表达式

的值: a&&b b&&c a||c

!a+c&&b+c

!c+a==b||b<a

a+c||a+b>c+10

对于逻辑表达式的两种基本技能: ① 逻辑表达式的计算。

② 逻辑表达式的构造。

逻辑表达式的构造举例: a≥b≥c a>=b>=c 5>=4>=3 a>=b&&b>=c

a和b之一为0,但不同时为0 a==0&&b!=0 || a!=0&&b==0 a*b==0 a*b==0&&a+b!=0

对于 a==0 && b!=0 || a!=0 && b==0 a==0可以用!a代替 a!=0可以直接用a !a && b || a && !b 但必须是运算结果作为逻辑量的情况下。

y=(a!=0) 与

y=a

不等效

5.3

if语句

1、if语句的三种形式 ① if(表达式)语句;

有一分支为空。

scanf(“%d”,&score); if(score>=60) printf(“pass”);

② if(表达式)语句1;

else 语句2;

if(x!=0) y=1/x; else y=10000;

③ if(表达式1)语句1;

else if(表达式2)语句2;

else if(表达式3)语句3;

┇ else 语句n;

if(score==100) printf(“A”); else if(score>=90) printf(“B”); else if(score>=80) printf(“C”); else if(score>=70) printf(“D”); else if(score>=60) printf(“E”); else printf(“F”);

对于: 1/x

y=

当x≠0时

? y=1/x; if(x==0)y=10000

10000 当x=0时

一般用: if(x!=0) y=1/x; else y=10000;

也可用: y=10000; if(x!=0) y=1/x;

例:(习题5.5): x (x<1) y= 2x-1 (1≤x<10) 3x-11 (x≥10)

main()

{

float x,y; scanf(“%f”,&x); if(x<1) y=x; else else if(x<10) y=2*x-1; y=3*x-11;

printf(“ y=%f”,y); }

说明: ① 语句中的表达式可以是任意表达式: if(x) y=1/x; else y=10000; ② 一个if结构不可分割: if(x) y=1/x; z=10; else y=10000; ③一个分支中包含多个语句时,要用{ }: if(a<0) { x=1; y=2;} else {x=10; y=20;}

分支程序设计举例(基本技巧和算法)

例:从键盘输入三个整数到变量a,b,c,输 出其中最大的数。

两种典型算法: ①枚举法(将各种可能性枚举出来)。

②选择法(先假设后判断更新)。

}

选择法 main() { int a,b,c,max; scanf(“%d,%d,%d”,&a,&b,&c); max=a; if(b>max) max=b; if(c>max) max=c; printf(“ max=%d”,max); }

例:从键盘输入三个整数到变量a,b,c,要求

按从大到小的顺序输出。

两种典型算法: ①枚举法(将各种可能的排列枚举出来) 。

②换位法(将a,b,c中的数据换位)。

}

换位法 a b c 3 8 8 5 3 3 5 5 main() { int a,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(“ %d,%d,%d”,a,b,c); }

2、if语句的?#30701;?在if语句中,又包含一个或多个if语句: if(score>=80) if(score>=90) printf(“A”); else printf(“B”); else if(score>=60) printf(“C”); else printf(“D”); 注意else与if的匹配

3、条件运算符 如果两个分支的内容都是给同一个变量赋值 ,则可用简单的条件运算符处理: if(a>b) max=a; else max=b; 可用: max=a>b ? a : b; 赋值运算符右边为一条件表达式。

条件表达式的一般形式: 表达式1 ? 表达式2 : 表达式3

条件表达式的执行过程: a>b ? a : b

非0 表达式1 0

条件表达式 取表达式2的值

条件表达式 取表达式3的值

优先级:低于关系运算符,高于赋值运算符。

结合性:右结合性。

例:求a,b,c中的最大值:

max= a>b ? (a>c?a:c) : (b>c?b:c) ;

5.4

switch语句(多分支)

适用于根据一个表达式的值就可确定 走哪个分支的情况。

switch(表达式) { 常量表达式1: 语句1 常量表达式2: 语句2 ┋ 常量表达式n: 语句n default: 语句n+1 }

例:成绩分档: switch(score/10) { case 10: printf(“A”); case 9: printf(“B”); case 8: printf(“C”); case 7: printf(“E”); case 6: printf(“F”); default : printf(“G”); } 注:应使用break.

switch(score/10) { case 10: printf(“A”); case 9: printf(“B”); case 8: printf(“C”); case 7: printf(“E”); case 6: printf(“F”); default : printf(“G”); }

break; break; break; break; break;

5.5 程序举例 (习题5.10) 有4个圆塔,圆心分别为:(2,2), (-2,2),(-2,-2),(2,-2),圆 半径为1。

这4个塔的高度为10m,塔以外无 建筑物。

今输入任一点的坐标,求该点的 建筑高度(塔外的高度为0)。

算法设计:

10 在某一圆内 (x,y)

h=

0 在圆外

条件“在某一圆内” : “在圆1内或在圆2内或在圆3内或在圆4内” 若设变量c1、c2、c3、c4分别代表是否在相 应的圆内,则以上条件为: c1||c2||c3||c4

c1=(x-2)2+(y-2)2≤1 c2=(x+2)2+(y-2)2≤1 c3=(x+2)2+(y+2)2≤1 c4=(x-2)2+(y+2)2≤1

main() { int h,c1,c2,c3,c4; float x,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; else h=0; printf(“ h=%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+10

0

1

s

i

s+i → s

i+1 → i

y i≤10

n 输出s

s=0;

i=1; lable:s+=i; i++;

goto 语句可以构造循环, goto 语句可以构 但不主张用,因为它容易破 造循环,但不主张用, 坏结构化程序设计。

因为它容易破坏结构 化程序设计。

if(i<=10) goto lable;

printf(“%d”,s) ;

语句标号 无条件转向语句

6.3 while语句 while语句是专门用于实现循环控制的语 句之一。

其一般形式为: while (表达式) 语句

语句关键字 语句关键

表达循环条件的 表达式

循环体

含义:当表达式的值为非0时,执行循环体, 否则执行后续语句。

执行过程:

while (表达式) 语句

表 达 式 非0 循环体

0

例:用while语句实现前面算法: s=0 main() i=1 { int i=1,s=0; while(i<=10) i≤10 { ? s=s+i; y i++; s=s+i i=i+1 } printf(“ %d”,s); }

n

注意与if语句的区别。

循环体中要有使循环条件趋于成立的条件

while(i<=10) { s=s+i; i++; }

可简写为:

while(i<=10) s+=i++;

6.4 do-while语句 do-while语句主要用于实现直到型循环。

其一般形式为: do 循环体 while(表达式); 执行过程:

循环体

非0(真)

表达式

0(假)

例:用do-while语句实现前面算法: main() { int i=1,s=0; do s+=i++; while(i<=10); printf(“%d”,s); 真 } 注意与while语句的区别。

s=0 i=1 s=s+i i=i+1

i≤10?

6.5

for 语句

求解表达式1

for语句是一种使用最为灵活, 并且是用得最多的循环控制语句,

表达式2

其一般形式为:

for(表达式1;表达式2;表达式3) 循环体

大体含义: 对于()的情况执行循环体内容。

循环体

求解表达式3

例:用for语句实现前面的算法:

s=0;

for(i=1;i<=10;i++) s+=i;

标准形式

表达式1

表达式2

表达式3

循环体

可以理解: 循?#32321;?#37327;i从初值1开始到终值10,步长为1,重复执 行循环体。

for语句的常见变化: s=0; i=1; for(;i<=10;i++)s+=i;

省略表达式1

s=0; 省略表达式3 for(i=1;i<=10;)s+=i++;

s=0;i=1; 省略表达式1和3 for(;i<=10;)s+=i++;

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; 1 2 3 4 5 6 7 8 9 10

用?#27721;?#34920;达式

i

j

在程序设计中不要过分追求它的多变性

例:求n! n!=1*2*3…(n-1)*n 参照累加求和 main() { int i,n=5,s=1; for(i=1;i<=n;i++)s*=i; printf(“ s=%d”,s); } 注意s的初值。

注意当n较大时的情况。

求和与连乘都是最常用的算法,要熟练掌握。

例:求自然数1-100中能被3整除的数之和。

main() { int i,s=0; for(i=1;i<=100;i++) if(i%3==0)s+=i; s+=i; for(i=3;i<=100;i+=3) s+=i; for(i=3;i<=100;i+=3) if (i%7)s+=i; printf(“ %d”,s); } 求能被3整除但不被7整除的数之和?

例:求任意100个数中的最大值。

main() { int i,a,max; max=-32768; max=? for(i=1;i<=100;i++) for(i=1; ;i++) { scanf(“%d”,&a); if(a==-9999)break; if(a>max) max=a; } printf(“ max=%d”,max); } 循环体中没有引用循?#32321;?#37327;。

i的作用? 求任意个数中的最大值?

6.6 循环的?#30701;?循环体内又包含另一个完整的循环结构(多重 循环)。

外重循环 for(i=1;i<=10;i++) { for(j=1;j<=20;j++) 内重循环 { s+=i+j; 执行200次 } }

要掌握多重循环 执行的全过程

以上多重循环结构可以简写为:

for(i=1;i<=10;i++) for(j=1;j<=20;j++) s+=i+j;

例:?#39029;?#34892;号乘以列号等于100的座位。

main() { int i,j; for(i=1;i<=30;i++) for(j=1;j<=20;j++) if(i*j==100) printf(“%d,%d”,i,j); }

注意循环的关系

例:百钱买百鸡问题。

给定100块钱,要求正好买100只鸡,已知公 鸡5元/只,母鸡3元/只,小鸡1元/3只,?#20351;?鸡、母鸡和小鸡应各买多少只? 若考虑用方程组:

x+y+z=100

5x+3y+z/3=100

是一多解问题。

用测试法求解的程序: main() { int x,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(“%d,%d,%d”,x,y,z); }

程序可进一步简化为: main() { int x,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(“%d,%d,%d”,x,y,z); } } 用测试法求解问题的典型例子

测试法求解的程序设计有两个要点: ⑴通过循环列出所有可能的解。

⑵对所有列出的可能的解进行条件测试。

例?#21495;?#26029;一个数m是否为素数。

main() { 用测试法求解 int i,m; scanf(“%d”,&m); for(i=2;i<m;i++) if(m%i==0)break; if(i==m) printf(“ %d is a prime”,m); else printf(“ %d is not a prime”,m); }

例:(习题6.6) 打印出所有的?#20843;?#20185;花数?#20445;?#25152;谓?#20843;?仙花数”是指一个三位数,其各位数字的 立方和等于该数本身。

如:153是一水仙花 数,因为 153=13+53+33。

main() { int i,j,k,n; for(n=100;n<=999;n++) { i=n/100; i=? j=n/10%10; j=? k=n%10; k=? if(i*i*i+j*j*j+k*k*k==n) printf(“%d”,n); } } 通过循环列出n的所有可能的范围

main() { int i,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(“%d”,n); } } 通过循环列出i,j,k的所有可能的范围

例:(习题6.4)

求S=∑i! =1!+2!+3!+4!+…+19!+20!

i=1

20

main() { int i,j; float t,s=0; for(i=1;i<=20;i++) { t=1; for(j=1;j<=i;j++) t*=j; s+=t; s+=?; } printf(“ s=%f”,s); } 用两重循环实现

用递推法: 求S=∑i! =1!+2!+3!+4!+…+19!+20!

i=1 20 i=2 20 i=2

20

=1+∑(i-1)!.i = 1+∑ti-1.i

递推公式:ti=ti-1.i

main() { int i,j; float t=1,s=t; for(i=2;i<=20;i++) { t=t*i; s+=t; } printf(“ s=%f”,s); }

例:

1 1 1 1 1 1 s=∑ — = — + — + — + — + …+ — 2! 3! 4! 20! 1 i! 1!

20

递推公式: ti= ti-1 / i

main() { int i,j; float t=1,s=t; for(i=2;i<=20;i++) { t=t*i; t=t/i; s+=t; } printf(“ s=%f”,s); }

习题6.3: s=a+aa+aaa+aaaa+aaaaa 2+22+222+2222+22222

递推公式:ti= ti-1· 10+a ? t *

main() { int i,j,a=2; float t=a,s=t; for(i=2;i<=5;i++) { t=t*10+a; s+=t; } printf(“ s=%f”,s); }

例:求方程 2x3+3x2-4x+1=0的根。

简单迭代法基本思想: 将原方程f(x)化为:x2=g(x1)

x2=(2x13+3x12+1)/4 迭代公式

迭代过程:

假定一个x1 x2=g(x1)

x1=x2

不成立

|x2x1∣<ε

成立

输出x2

main() { float x1,x2; scanf(“%f”,&x1); while(1) { x2=(2*x1*x1*x1+3*x1*x1+1)/4; if(fabs(x2-x1)<1e-6)break;

? x1=x2;

} printf(“ %f”,x2); }

牛顿迭代法基本思想:

y f (x1)

f (x2)

x

x2 x1

牛顿迭代公式 f′(x1)=f(x1)/(x1-x2) x2=x1-f(x1)/ f′(x1)

main() { float x1,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(“ %f”,x2); }

例:求定积分:∫ sinx dx a x

f (x)

b

数值积分

等分n

b-a h= — n

a

x

b

x=a+(i-1).h 第i个矩形:x=?

#include “math.h” main() { int n,i; float a,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;

s+=h*y; }

y=sin(x)/x;

printf(“ s=%f”,s); }

第七章 数 组

7.1 数据结构与数组的概念 影响程序设计的因素除算法外还有数据结构。

■数据结构概念 编写一个程序除了重视算法的设计外,还需 重视数据类型的选择,即选择合?#23454;?#25968;据类型来 存放要处理的数据。

在程序设计中,数据类型就 称为数据结构,选择合?#23454;?#25968;据类型实际上就是 进行数据结构的设计。

在程序设计中有格言:

数据结构+算法=程序 说明数据结构与算法同等重要,算法依赖 于数据结构,对于同一个问题的求解,可以 采用不同的数据结构和不同的算法,对不同 的数据结构有不同的算法,其复杂程度?#19981;?不同,选择合?#23454;?#25968;据结构,可以?#26723;?#31639;法 的复杂程度。

因此,在程序设计中应重视数 据结构的设计。

例:求任意100个数中的最大值。

main() { int i,a,max; 用一个简单变量作为 max=-32768 数据结构,合理,算 法简单 for(i=1;i<=100;i++) { scanf(“%d”,&a); if(a>max) max=a; } printf(“ max=%d”,max); }

对于三个数的排序: main() 仍可用变量作 为数据结构 { int a,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(“ %d,%d,%d”,a,b,c); } 对于很多个数的排序用变量会很复杂而用数组会 使算法很简单。

■数组的概念

int a[10]

数组名

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

下标

数组元素

一组具?#22411;?#26679;类型的数据的集合 统一用一个名?#25191;?#34920;---数组名(代表一组数)

数组中的各成员称数组元素,由数组名加 下标唯一地确定。

将一组数用一个名?#25191;?#34920;,便于管理。

只有一个下标的数组称为一维数组;

可有二维数组、三维数组、…、七维数组。

7.2 一维数组的定义和引用 ■定义 一般形式: 类型符 数组名[常量表达式];

int a[10];

类型符

float b[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?#20445;?&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}; int a[10]={0,1,2,3,4}; int a[]={0,1,2,3,4};

■应用举例 (1)对100个学生的分数统计最高分、最低分 ?#25512;?#22343;分。

两种方法: 用变量作为存放初始数据的数据结构 用数组作为存放初始数据的数据结构

main() { int i,a,max,min; 用变量 float aver=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(“ %d,%d,%f”,max,min,aver); }

main() { int i,a[100],max,min; 用数组 float aver=0; for(i=0;i<100;i++) scanf(“%d”,&a[i]); max=a[0]; min=0; min=a[0]; max=0; for(i=0;i<100;i++) { if(a[i]>a[max]) max=i; if(a[i]>max) max=a[i]; if(a[i]<min) min=a[i]; if(a[i]<a[min]) min=i; aver+=a[i]; } 找最大最小的位置? aver/=100; printf(“ %d,%d,%f”,max,min,aver);

}

(2)统计高于平均分的人数。

用变量 main() n=0; { int i,a,n; for(i=0;i<100;i++) float aver=0; { scanf(“%d”,&a); for(i=0;i<100;i++) if(a>aver)n++; { scanf(“%d”,&a); } aver+=a; printf(“ %d”,n); } } aver/=100;

数据结构不合理

main() 用数组 { int i,a[100],n; float aver=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(“ %d”,n); }

1(3)对100个学生的分数统计出每分一档人数。

0 ? main() 1 ? { int i,a; int i,a,n[101]; 2 ? for(i=0;i<101;i++) n[i]=0; 3 ? for(i=1;i<=100;i++) 4 ? { scanf(“%d”,&a); ┇ n[a]++; ┇ } 99 ? 输出 100 ? }

完整程序: main() { int i,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(“ %3d:%3d”,i,n[i]); }

按10分一档统计? main() { int i,a,n[101]; i,a,n[11]; for(i=0;i<101;i++)n[i]=0; for(i=0;i<11;i++)n[i]=0; for(i=1;i<=100;i++) { scanf(“%d”,&a); n[a]++; n[a/10]++; } }

(4)对10个学生的分数按从小到大的顺序排序 后输出。

两种典型的排序算法:选择法?#25512;?#27873;法。

选择法基本思想: 首先选择最小的数放在0位臵,再在剩下的数 中选择最小的数放在下一位臵,┈┈,?#26469;?#31867; 推,共进行9次选择。

5 8 7 4 3 9 0 1 2 6

每次选择都要与其后的所有数进行比较换位。

5 8 7 4 3 9 0 1 2 6

i

j

main() { int a[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]); }

5 8 7 4 3 9 0 1 2 6

5

8

7

4

3

9

0

1

2

6

i

j

先找最小值所在的位臵,最后再换位: 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]); }

起泡法基本思想: 首先将所有数中的最大值“冒泡”到最后位 臵,再将剩下的数中的最大值“冒泡”到上一位 臵,┈┈,?#26469;?#31867;推,共进行9次“冒泡”。

每次“冒泡”都是一种翻滚过程,即相邻两个 数进行比较换位。

5

8

7

4

3

9

0

1

2

6

main() { int a[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个 数移到最前面。

5 8 7 4 3 9 0 1 2 6

1

2

6

5

8

7

4

3

9

0

用循环移位实现: 5 8 7 4 3 9 0 1 2 6 main() { int i,j,k,a[10]; for(i=0;i<10;i++)scanf(“%d”,&a[i]);

for(j=1;j<=3;j++) k=a[9]; { k=a[9]; for(i=9;i>0;i--)a[i]=a[i-1]; for(i=1;i<10;i++)a[i]=a[i-1]; a[0]=k; }

for(i=0;i<10;i++)printf(“%3d”,a[i]); }

(6)狐狸找兔子问题绕 围绕着山顶有10个洞,一只兔子和一只狐狸 分别住在洞里,狐狸总想吃掉兔子;

一天,兔子 对狐狸说:你想吃掉我有一个条件,先?#35759;?#39034;序 编号,你从最后一个洞出发,第一次先到第一个 洞找我,第二次隔一个洞找,第三次隔两个洞找, ┈,?#26469;?#31867;推,寻找次数不限,我躲在一个洞里 不动,只要找到我你就可以饱餐一顿。

狐狸一想 只有10个洞,寻找次数又不限,那有找不到的呢? 马上答应了条件,结果狐狸跑断了腿也没找到, 请问兔子躲在哪个洞里?

1 10 2

3

9

4 8 5 6

7

算法思想:

开辟数组,每个元素代表一个洞,并赋初值

0,表示各个洞都还未找,然后按规律找,每 找一个洞,对应的数组元素就赋值1,表示已 找过,┈┈,最后根据数组元素值1与0?#35789;?#21035; 各洞是否已找过。

main() { int i, k=10; int a[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 二维数组的定义和引用

■定义 一般形式: 类型符 数组名[常量表达式] [常量表达式];

int a[3][4]; 行 列 float b[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个数到二维数组?#23567;?p> int a[3][4],i,j; for(i=0;i<3;i++) for(j=0;j<4;j++) scanf(“%d”,&a[i][j]); 需要用两重循环来控制两个下标的变化。

如果键盘输入的数据是:1 2 3 4 5 6 7 8 9 10 11 12, 则在数组中如何存放?两个循环 换位呢?两个下标换位呢? int a[3][4],i,j; for(i=0;i<3;i++) for(i=0;i<3;i++) for(j=0;j<4;j++) for(j=0;j<4;j++) for(j=0;j<4;j++) for(i=0;i<3;i++) scanf(“%d”,&a[i][j]); scanf(“%d”,&a[j][i]);

例:输入一个表格的数据到二维数组中,并找最 大值所在的位臵 main() { int a[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(“ %d,%d”,i1,j1); }

■初始化

对二维数组赋初值的几种方法: int a[3][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int a[3][4]={{1},{5},{9}}; int a[3][4]={{1},{0,6},{0,0,11}}; int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int a[][4]={{0,0,3},{},{9,10}};

■ 举例 (1)矩阵的基本操作 二维数组的逻辑结构就如同一个矩阵,因此, 矩阵操作都可用二维数组实现。

a11 a12 a13 … a1n a21 a22 a23 … a2n A= a31 a32 a33 … a3n ………… am1 am2 am3 … amn

假定M=3,N=4

求和: 1 2 3 5 6 7 main() 9 10 11 { int a[4][4],i,j,s=0; 13 14 15 ┈┈┈ for(i=0;i<4;i++) for(i=0;i<4;i++) 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]; for(j=i;j<4;j++) s+=a[i][j]; for(j=0;j<4;j++) s+=a[i][j]; ┈┈┈ } for(i=0;i<4;i++) for(j=0;j<=i;j++) s+=a[i][j]; 上三角?下三角?主对角线?

4 8 12 16

非方阵转臵:aij→bji

main() { int a[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]; ┈┈┈ }

1 2 3 4 5 6 7 8 9 10 11 12

1 2 3 4

5 6 7 8

9 10 11 12

方阵转臵:aij∽aji main() { int a[3][3],i,j,t; ┈┈┈ for(i=0; i<3; i++) for(j=i+1; j<3; j++) for(j=0; j<3; j++)

1 2 3 4 5 6 7 8 9

{t=a[i][j]; a[i][j]=a[j][i]; a[j][i]=t;} ┈┈┈ }

将矩阵中和值为最大的那一行元素与首行对换。

main() { int a[3][4],i,j,t,s,smax=-32768,row; ┈┈┈ 1 5 3 8 for(i=0;i<3;i++) 4 6 1 7 { s=0;for(j=0;j<4;j++)s+=a[i][j]; 9 2 5 6 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;} ┈┈┈ }

7.4 字符数组 用于存放字符的数组称字符数组。

字符数组的每一个元素存放一个字符。

字符数组的独特之处: (1)字符数组可以看作字符串变量。

(2)对字符数组可以进行某些整体操作。

(3)有专用的字符串处理函数。

1、将字符数组作为字符串变量 char c[10]; 给c分配10个字节的内存单元。

把c看作数组时,按数组元素的形式访问: c[0]=?a?; c[1]=?b?; c[2]=?c?; c[3]=?d?; a b c d

char c[10]={?a?,?b?,?c?,?d?} ; 也属于字符赋初值的形式。

如果把字符序列看作一个整体(字符串), 则c就可看作是存放这个字符串的串变量;

但必 须在字符序列后加上“字符串结束标志”后,才 能成为完整的字符串。

如:c[4]=?\0?; 或 c[4]=0; a b c d \0

也可以按字符串形式初始化: char c[10]=”abcd”; char c[]=”abcd”; 分配5个字节

2、对字符数组的整体操作 对字符数组的?#34892;?#25805;作可以整体进行,如输入 输出。

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); 整体操作 对字符数组输入输出可以整体进行,但不允许 整体赋值: char c[10]=”abcd”,x[10]; x=c; 不允许

对于二维字符数组,可以看作是一维的字符 串数组。

例:从键盘输入10个?#35828;?#21517;字到计算机: main() { int i; char name[10][20]; 10个元素的一维字符串数组 for(i=0;i<10;i++) scanf(“%s”,name[i]); … }

只给一个下标

3、字符串处理函数 c语言的函数库中提供了一系列专用于字符串 处理的函数,需要时可直接调用。

(1)puts(字符串) 用于输出字符串。

其中字符串可以是字符串常量,也可以是字 符数组。

例: char str[]=”China”; puts(str); puts(”China”); 两个输出等效

(2)gets(字符数组) 用于从键盘输入一个字符串到字符数组?#23567;?p> 函数返回字符数组的起始地址。

例: char str[10]; gets(str); 执行该函数调用时,计算机等待输入字符串

(3)strcat(字符数组,字符串) 用于将字符串连接到字符数组的后面。

其中字符串可以是字符串常量,也可以是字 符数组。

例: char a[10]=”abcd”, b[10]=”xyz”; strcat(a,b); 与strcat(a,”xyz”)等效 puts(a); 输出结果是:abcdxyz

(4) strcpy(字符数组,字符串) 用于将字符串拷贝到字符数组?#23567;?p> 其中字符串可以是字符串常量,也可以是字 符数组。

例: char a[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”); strcmp(“a”,”ABCD”);

返回0 返回正整数 strcmp(“abcdefgh”,”abcxyz”);

返回负整数

例:从键盘输入两个字符串,输出其中大的一 个。

#include “string.h” main() { char a[10],b[10]; gets(a); gets(b); if(strcmp(a,b)>0) puts(a); 不能用a>b else puts(b); } 使用字符串处理函数需要包含头文件string.h

(6) strlen(字符数组) 测试字符串的实际长度(从返回?#26723;?#21040;)。

(7) strlwr(字符串) 将字符串中的大写字母全改为小写字母。

(8) strupr(字符串) 将字符串中的小写字母全改为大写字母。

注意:在使用字符串处理函数时,别忘了将 头文件string.h包含进去。

4、字符串操作举例 (1)从键盘输入一字符串到数组a中,再拷贝到 数组b中(不用库函数)。

main() { char a[50],b[50]; int i; 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() { char a[50],b[50]; int i,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() { char a[50]; int i; 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)输出结果。

把求最大值的算法部分定义成一个独立的 函数:

函数类型 函数名 函数参数(形参) int max(int x,int y) { int z; if(x>y)z=x; else z=y; return(z); } x y z main() { int a,b,c; scanf(“%d%d”,&a,&b); c=max(a,b); printf(“%d”,c);

}

a

3

b

5

c

说明: (1)程序由两个函数组成,它们逻辑上相互独 立(功能、变量)。

(2)程序的执行总是从主函数开始,主函数总 是被执行一次,其他函数只有在被调用时才获 ?#27599;?#21046;。

(3)函数调用有两个作用:转移控制权和传递 参数。

(4)return的作用也有两个:?#25442;?#25511;制权和返 回结果。

(5)实参可以是常量、变量或表达式,但类型 要一致。

定义一个函数除考虑算法外就是:如何设 计函数的参数,通过何种途径?#25442;?#32467;果。

例:求自然数1—100中的素数之和。

? ? ) main() int prime( int m) { int i; { int i,s=0; for(i=2;i<m;i++) for(i=1;i<=100;i++) if(m%i==0) return 0; ? if(prime(i) ) s+=i; return 1; ? printf(“ %d”,s); else return 1; } }

例:求5!+7!+4!的值。

int fac( int n ) ? ? { int i,s=1; for(i=1;i<=n;i++) s*=i; return(s); } main() { printf(“%d”,fac(5)+fac(7)+fac(4)); }

main() { float s,fac(); 对被调函数声明 s=fac(5)+fac(7)+fac(4); printf(“%f”,s); } float fac(int n) { int i; float s=1; for(i=1;i<=n;i++) s*=i; return(s); } 不需声明的情况:int char 主调函数在后

若被调用的函数是库函数,则应用#include 命令将所调用函数的有关信息包含进来,如: 例: #include “math.h” main() { float x,y; scanf(%f”,&x); y=sin(x); printf(“%f”,y); }

8.3 函数的?#30701;?#35843;用 C语言的函数定义虽然相互平行、相互独立的, 但可以?#30701;?#35843;用,形如: 主函数 函数A 函数B

例:求多项式 S= ∑i!+ ∑i!+ ∑i!的值。

1 7 15

5

11

20

float

fac(int n)

{…}

a, float sum( int ? int b ) ? { int i; float s=0; for( i=a;i<=b;i++ ) s+=fac(i); i=? return(s); } main()

{

printf(“%f”,sum(1,5)+sum(7,11)+sum(15,20); }

8.4 函数的递归调用 在函数调用的过程中,出现直接或间接地调用 该函数本身。

如: f1() f2() f3() { { { f1(); f3(); f2(); } } }

直接 递归调用

间接 递归调用

在实际应用中,?#34892;?#38382;题既可用递归实现, 也可不用递归(如求n!);

也?#34892;?#38382;题非有递归不可(如汉诺塔问 题);

不少问题使用递归显得很方便。

用递归方法求n! : 递推公式: 1 当n=0或n=1时 n!= n(n-1)! 当n>1时

float fac(int n) main() { float f; { float f; if(n==0||n==1) f=1; f=fac(4); else f= n*fac(n-1); ? printf(“%f”,f); return(f); } } 递归调用的执行过程:

主函数

函数fac

函数fac

f=fac(4);

n=4 if(n==0||n==1)f=1; else f=n*fac(n-1); return(f)

函数fac

n=3 if(n==0||n==1)f=1; else f=n*fac(n-1); return(f )

函数fac

n=1 if(n==0||n==1)f=1; else f=n*fac(n-1); return(f)

n=2 if(n==0||n==1)f=1; else f=n*fac(n-1); return(f)

问题:4个return的执行顺序?后进先出!

8.5 数组作为函数的参数 当要传递的参数较少时,用简单变量作为 函数的参数是方便的,但当要传递的参数是批量 时,需要用数组作为函数的参数。

例:编写函数,求100个数的平均数。

float aver(int a[100]) a[] { int i; float s=0; for(i=0;i<100;i++) s+=a[i] ; return(s/100); } main() { int x[100]; float av; 输入x;

对应的实参也应为数组 av=aver(x); 型参数组的长度可省略 }

通用函数考虑: float aver(int a[],int n) { int i; float s=0; n=5; for(i=0;i<n;i++) s+=a[i]; a[0]=3 ; return(s/n); }

a

3

main() { int x[100],n=100; float av; 输入x av=aver(x,n); }

n 100

x

n

5 100

值传递 地址传递

例:阅读程序: main() swap(int a, int b) { int a=3,b=5; { int t; swap(a,b); t=a; a=b; b=t; printf(“%d,%d”,a,b); printf(“%d,%d”,a,b); } } a

3

b

5

a

b

以下程序的运行结果是 ? main() f ( int b[], int x) { int a[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,4 B) 6,4,7 C) 6,2,4 D) 5,4,7

例?#21495;?#24207;。

void sort(int a[], int n) { int i,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() { int x[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]); }

x

a

例:方阵转臵(二维数组情况)。

at(int a[3][3]) x a { int i,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;} } int x[3][3]; at(x); 行长不等情况?通用函数的处理?

通用函数,按一维数组处理: at(int a[],int n) { int i,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;} } int x[3][3]; at(x,3);

8.6 局部变量和全?#30452;?#37327; 1、局部变量 在函数内定义的变量称局部变量。

局部变量只在该函数内使用。

float f1(int x) int f2() main() { int i,j; { int a,b,c; { int m,n; ┊ ┊ { int i,j; ┊ ┊ ┊ } } } }

说明: (1)任何函数(包括主函数)内定义的变量都 是局部变量。

(2)不同函数内定义的变?#32771;?#20351;同名?#19981;?#19981;干 扰。

(3)复合语句中定义的变量只在该复合语句中 ?#34892;А?p> 2 、 全?#30452;?#37327; 在函数以外定义的变量,也称外部变量。

全?#30452;?#37327;可以为为本文件中其它函数所共用。

它的作用范围是从定义变量的位臵开始到本源 文件结束。

int p=1,q=5; float f1(int a) { int b,c; ┊ } char c1,c2; char f2(int x,int y) { int i,j; ┊ } main() { int m,n; ┊ }

全?#30452;?量c1,c2 的作用 范围

全局 变量 p,q的 作用 范围

全?#30452;?#37327;主要用于作为不同函数间数据传 递的桥梁。

例:编写一个函数,求n个数中的最大值、 最小值?#25512;?#22343;值。

并编写主函数完成:输入100 个数,调用该函数进?#22411;?#35745;,输出结果。

int max,min; float aver(int a[],int n) 用全?#30452;?#37327;传递结果 { int i; float s=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() { int x[100],i; float av; for(i=0;i<100;i++) scanf(“%d”,&x[i]); av=aver(x,100); printf(“ %d,%d,%f”,max,min,av); }

分析不用全?#30452;?#37327;的情况: float aver(int a[],int n) { int i; float s=0; int max,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() { int x[100],i; float av; int max,min; for(i=0;i<100;i++) scanf(“%d”,&x[i]); av=aver(x,100); printf(“ %d,%d,%f”,max,min,av); }

int max,min; float aver(int a[],int n) max min { int i; float s=0; for(i=0;i<n;i++) { if(a[i]>max)max=a[i]; if(a[i]<min)min=a[i]; s+=a[i]; 分析全?#30452;?#37327;与局 } return (s/n); 部变量同名的情况 } main() { int x[100],i; float av; int max,min; max min for(i=0;i<100;i++) scanf(“%d”,&x[i]); av=aver(x,100); printf(“ %d,%d,%f”,max,min,av); }

阅读程序,给出运行结果: int a=4,b=5,c=6; a b int f(int a,int b) 4 5 { a/=2; c+=b-a; a b return(a+b+c); 2 4 7 } a main() 2 { int a=2,d; d=f(a+2,a+b); printf(“ %d,%d,%d,%d”, a,b,c,d); }

c 6 11

d 20

8.7 变量存储类别 1、动态存储方式和静态存储方式

变量 变量

局部变量 全?#30452;?#37327; 动态存储方式变量 静态存储方式变量

空间角度 生存期角度

静态存储方式:在程序运行期间分配固定存储单 元的方式。

动态存储方式:在程序运行期间根据需要动态分 配存储单元的方式。

用户区

程序区 静态存储区 动态存储区

程序开始运行时分配空间,运行结束时释放 主要存放全?#30452;?#37327;和静态局部变量 根据需要动态分配,动态释放的区域

主要存放动态局部变量和现场保护等

存放在静态存储区的变量:静态存储方式。

存放在动态存储区的变量:动态存储方式。

2、局部变量的存储方式 每个局部变量在定义时可以指定其存储方式, 即对每个局部变量的定义除定义其数据类型外, 还应定义其存储方式。

定义存储方式用auto (自动的)static(静态的)。

如:

int f1() { auto int a=1; ┊ } 缺省时为auto

int f2() {static int b=1; ┊ }

动态局部变量在函数调用时分配、赋初值, 调用结束时释放。

静态局部变量在第一次调用时分配、赋初 值,调用结束时不释放,其单元及其值仍保留, 下次调用时不重新分配,不重新赋初值。

在实际应用中,如果希望在函数调用结束 后仍保留某个局部变量的值给下次调用时使用, 则可定义该变量为静态的。

例:编写一个函数计算: 2x-1 y= 3x+1 4x+2 第一次计算 第二次计算 其他

float f ( float x) { float y; static int n=1; if(n==1)y=2*x-1; else if(n==2)y=3*x+1; else y=4*x+2; n++; return(y); }

main() { printf(“%f”,f(2.0)); printf(“%f”,f(1.0)); printf(“%f”,f(3.0)); }

3 、全?#30452;?#37327;的存储方式

全?#30452;?#37327;都是静态存储方式,不允许用auto来 定义全?#30452;?#37327;。

可以用static来定义全?#30452;?#37327;。

如: static int int y; x; 静态全?#30452;?#37327;(内部的) 非静态全?#30452;?#37327;(外部的)

对于非静态全?#30452;?#37327;,其它文件中的函数只 要用extern加以外部说明,就可以访问。

而对于静态全?#30452;?#37327;,只局限在本文件中 的所有函数访问,其它文件中的函数即使用 extern加以外部说明,也不能访问。

int y; int y; static main() { y=0; } int f1() { y=2; }

extern int y; int f3() { y=10; } int f4() { y=100; }

8.8 内部函数和外部函数 用extern加以定义的函数称外部函数 。

用extern加以定义的函数称外部函数 。

extern int f1() static int f2() { { ┊ ┊ } } 缺省为外部函数。

外部函数可以为其他文件中的函数所调用。

内部函数只为本文件中的函数所调用(保护)。

main() { f3(); 允许 } int f1() { f4(); 不允许 }

extern int f3() { f4(); 允许 }

static int f4() { }

第九章 编译预处理

C语言提供了一些以#开头的指令,如:

#define

#include

等。

这些指令是在编译以前就事先进行处理的,因 而称为“编译预处理”指令。

可以用编译预处理指令实现以下三种功能:

1) 宏定义

2) 文件包含

3) 条件编译

9.1 宏定义

1、不带参的宏定义 用一个指定的标识符(宏名)代表一个字符串。

一般形式:

#define

标识符

字符串

3.1415926

如:#define PI

有了这一宏定义后,程序中凡是用到3.1415926 的地方都可以以宏名PI出现。

例:定义一个宏名来代表一个参数。

#define PI 3.1415926 main() { float r=2,c,s; c=2*PI*r; s=PI*r*r; ┈} ?#20302;?#22312;对程序进行编译以前,首先将所有的编 译预处理指令进行预处理,对本例来说,就是 将程序中所有的宏名PI还原成3.1415926, ——宏展开。

例:定义一个宏名来代表一个数据个数。

#define N 100 main() { int a[N],i; float s=0; for(i=0;i<N;i++)scanf(“%d”,&a[i]); for(i=0;i<N;i++)s+=a[i]; s/=N; printf(“ %f”,s); }

宏名N---符号常量,可以作为数组说明的长度。

方便修改参数。

例:定义一个宏名来代表一个计算公式。

#define PI 3.1415926 #define AREA PI*r*r main() { r=3,s; s=AREA; printf(“ %f”,s); } 注意?#21512;低?#23545;宏定义的预处理是一个字符串的 还原过程,不要把宏名看成一个整体。

注意以下程序的运行结果:

#define F x+y

main()

{ int x=3,y=5,z;

z=2*F;

printf(“ %d”,z);

}

2、带参的宏定义

宏定义也可?#28304;?#21442;数,其一般形式为:

#define

宏名(参数表) 字符串

a*b

如:#define S(a,b)

area=S(3,2);

定义宏名S代表矩形面积,参数a,b为边长。

宏展开过程:

9.2 文件包含处理 在一个源文件中将另一个源文件的内容 包含进来。

文件包含指令的一般形式: #include 或 #include “文件名” <文件名>

file1.c

#include “file2.c”

file2.c

file1.c

B

B A

A

例: #include “math.h” main() { float a,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(“ %f”,area); }

f.c

#include “f.h” main() { printf(“%f”,f1(3.0)); printf(“ %f”,fac(10)); } float f1(float r) { return(PI*r*r); } float fac(int n) { int i; float s=1; for(i=1;i<=n;i++) s*=i; return(s); }

f.h

#define PI 3.1415926 float f1(float r); float fac(int n);

第十章

指针

指针:C的一个重要概念、重要特色。

它使C 正确而灵活地运用它,就可以方便地处理很多 其它高级语言所不能处理的问题。

不掌握指针等于没有掌握C语言的精华。

具备了强大的功能,使C成为程序设计语言之首。

10.1 指针的概念

简单地说,指针就是地址。

要掌握指针的概念就必须弄清:

■内存地址概念? ■变量与地址的关系? ■如何通过地址进行变量的存取?

说明例: int i,j,k; i=3; j=6; k=i+j;

内存用户数据

程序经编译后 ,变量名就不 复存在,以地 址对应。

1000 1002 1004

3 6 9

i j k

对变量值的存取总是按地址进行的----直接访问。

也可以采用“间接访问”方式:

先将变量i的地址存放到另一变量p1中, 要访问i时,先取出p1的内容(变量i的地址), 再去访问该地址所对应的内存单元中的内容 (变量i的值)。

内存用户数据

int i,j,k; i=3; j=6; k=i+j; int *p1, *p2; p1=&i; p2=&j;

1000 1002 1004

3 6 9

i j k

2000 2004

1000 1002

p1 p2

在以上概念的基础上对指针下定义: 变量的地址就是该变量的指针。

存放地址的变量称指针变量。

1000 1002

i j k

p1是指向变量i的指针变量。

1004

1000 p1 1002 p2

10.2 变量的指针

变量的指针 指针变量 指向变量的指针变量

用“*”代表“指向” 如*p1代表它所指向的变量i,同一内存单元。

以下两个语句等价: i=3; 直接访问 *p1=3; 间接访问

内存用户数据

int i,j,k; i=3; j=6; k=i+j; int *p1, *p2; p1=&i; p2=&j; *p1=3;

1000 1002 1004

3 6 9

i j k

2002 2004

1000 1002

p1 p2

■指针变量的定义 指针变量也必须先定义后使用。

int *p1; 注意: ① *表示该变量为指针变量,但变量名是p1。

② 一个指针变量只能指向同一类型的变量。

int i,*p1; float a; p1=&i; 合法 p1=&a; 不合法

■指针变量的引用 两种用法: ①用地址运算符& p1=&i;

②用指针运算符* (实行间接访问) *p1=100; k=*p1; 注意:指针变量只能放地址(指针)。

p1=100; 不允许

例: main() { int a=100,b=10; int *p1,*p2; 定义指针变量,?#24418;?#20855;体指向 p1=&a; p1指向a p2=&b; p2指向b printf(“ %d,%d”,a,b); printf(“ %d,%d”, *p1,*p2); }

注意:要区别定义和引用中的“*”

要特别注意以下用法的后果:

int *p1; *p1=100;

例:输入a和b两个整数,按先大后小的顺序输出 main() { int a,b,*p1, *p2, *p; scanf(“%d,%d”,&a,&b); 1000 5 a p1=&a; p2=&b; 1002 9 b if(a<b) { p=p1; p1=p2; p2=p;} printf(“ %d,%d”,a,b); 2000 1000 p1 1002 printf(“%d,%d”,*p1,*p2); 2004 1002 p2 1000 } 2006 p

改变p1和p2的指向

重要概念: 只要得到某变量的地址(指针),就可通 过指针而不需通过逻辑名来访问该变量。

手段:用指针变量保存变量的地址。

■指针变量作为函数的参数

可将指针变量作函数的参数,接受实参

地址,获得具体指向,进而通过指针变?#32771;?p>接访问主调函数的变量。

swap(int *p1, int *p2) { int t; t=*p1; *p1=*p2; *p2=t; } main() { int a,b; scanf(“%d,%d”,&a,&b); if(a<b)swap(&a,&b); printf(“ %d,%d”,a,b);

跨越逻辑上的限制

1000 1002

9 5 5 9

a b

2000 2004 2006

1000 1002

p1 p2 t

swap(int p1, int p2) 不用指针变量情况 { int t; t=p1; p1=p2; p2=t; 1000 5 } 1002 9 main() { int a,b; 5 9 scanf(“%d,%d”,&a,&b); 2000 if(a<b)swap(a, b); 2004 5 9 printf(“ %d,%d”,a,b); 2006

a b

p1 p2 t

重要概念:使用指针变量作函数参数, 被调函数可以通过主调函数给定的地址去 操作主调函数中的局部变量。

(可用于传递多个结果)

例:编写函数,求一元二次方程的两个实根。

#include “math.h” int root(float a,float b,float c, float *x1, float *x2 ) ? { float d; d=b*b-4*a*c; if(d<0||a==0)return(0); ? *x1 =(-b+sqrt(d))/2/a; *x2 =(-b-sqrt(d))/2/a; ? return(1); main() } { int k; float a,b,c,xa,xb;

scanf(“%f,%f,%f”,&a,&b,&c); k=root(a,b,c,&xa,&xb); if(k) printf(“ %f,%f”,xa,xb); }

例:求n个数的最大值、最小值?#25512;?#22343;值。

float aver(int a[], int n, int *max, int *min) { int i; float s=0; *max=a[0]; *min=a[0]; main() for(i=0;i<n;i++) { int a[100],i,max,min; { s+=a[i]; float av; if(a[i]>*max) *max=a[i]; for(i=0;i<100;i++) if(a[i]<*min) *min=a[i]; scanf(“%d”,&a[i]); av=aver(a,100,&max,&min); } printf(“ %d,%d,%f”,max,min,av); return(s/100); } }

10.3 数组的指针 数组有一个首地址: 数组的指针。

每个数组元素也都有地址: 数组元素的指针。

2000 2002 2004 2006

5 3 2 1 6 8 7 4

■指向数组元素的指针变量 p int a[10],*p; p=a; 指向数组 p=&a[0]; 指向数组元素

2000 2002 2004 2006

5 1 2 4 7

6 8 0 3 9

■通过指针引用数组元素

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] a[i] ∽ p[i]

*(p+i) ∽

*(a+i) ∽

即以?#24405;?#20010;语句等效:

a[i]=10; *(p+i)=10; *(a+i)=10; p[i]=10;

例:从键盘输入10个数到数组a:

int a[10],i,*p=a,s=0

for(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++; for(p=a;p<a+10;p++)s+=*p; 后两种用法效率高。

等效于*(p++)

注意不能使用a++

使用指针变量访问数组时,要特别注意指针 变量的当前值。

p 注意下例: main() { int a[10],*p=a,i; for(p=a;p<a+10;p++) scanf(“%d”,p); p=a; for(i=0;i<10;i++)printf(“%d”,*p++); }

■数组名作为函数参数

有了指针概念的基础上,重新回顾数组名作 为函数参数时,数据的传递情况: 例:将数组a中的n个数按相反顺序存放。

int inv(int x[], int n) { i,j,m,t; x a m=(n-1)/2; { for(i=0;i<=m;i++) { j=n-1-i; t=x[i]; x[i]=x[j]; x[j]=t; } } } a与x共用同一片内存单元

main() int a[10],i; 输入a inv(a,10); 输出a

int inv(int *x, int n) { i,j,m,t; m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; { j=n-1-i;

t=*(x+i); t=x[i]; *(x+i)= *(x+j); x[i]=x[j]; *(x+j)=t; x[j]=t; } 指针法 } 下标法 }

指针变量作函数参数时的传递情况

a

1000

main()

{

int a[10],i; 输入a inv(a,10); 输出a

}

x 1000

进一?#25509;?#21270;: int inv(int *x, int n) { int *i=x,*j=x+n-1,t; for(;i<j;i++,j--) i { t=*i; j *i=*j; *j=t; } } 优点:简练 效率高

main() { int a[10],i; 输入a inv(a,10); 输出a }

例:选择法排序函数

void sort(int *a, int n) void sort(int *a, int n) { {int i,j,t; int i,j,t; for(i=0;i<n-1;i++) for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) for(j=i+1;j<n;j++) if(*(a+i)>*(a+j)) if(a[i]>a[j]){t=a[i]; a[i]=a[j]; a[j]=t;} } {t=*(a+i); *(a+i)= *(a+j); *(a+j)=t;} 只将形参改为指针变量,仍按下标法使用 } 按指针法使用

进一?#25509;?#21270;: void sort(int *a, int n) { 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() { int a[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() { int a[10],j; for(j=0;j<10;j++)scanf(“%d”,a+j);

sort(a,5); sort(a+5,5);

for(j=0;j<10;j++)printf(“%5d”,a[j]);

}

■指向多维数组的指针和指针变量

从本质上说,多维数组的指针与一维数组 的指针相同,但在概念上和使用上,多维数组 的指针要复?#26377;?p>以二维数组的指针为例:

●二维数组的地址 : ?#33268;?#20197;下用法的效果: ?#33268;?#20197;下用法的效果: for(i=0;i<3;i++) scanf(“%d”,a[1]+i+2); for(i=0;i<3;i++) scanf(“%d”,a+i+1); scanf(“%d”,a[1]+i); 一维:a,&a[i],a+i scanf(“%d”,a+i); 输入数据:1 2 3 输入数据:1 2 3 二维:

int a[3][4]

a+0

1000 1008 1016

3 2 1

5 4 6

8 6 0

7 9 4

a[0]

a+1

a+2

a[1]

a[2]

a,&a[i][j],a+i (行指针),a[i](特殊的一维数 组元素,列指针),a[i]+j

注意:指针运算符*作用在行指针上的结果仍是指 针----列指针; *作用在列指针上的结果---具体元素。

a+0 a+1 a+2 1000 1008 1016 a[0] a[1] a[2] *(a+1)

*(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 ?

如果要通过a+i形式的地址访问数组元素的具体 内容,则: *(*(a+i)) 或 *(*(a+i)+j) 如:*(*(a+1)) —— a[1][0] *(*(a+1)+2) —— a[1][2] ?#33268;郟?*(a+2) *(*(a+1)+3) *(a[1]+1) *(*(a+1)+5)

例:求数组a的所有元素之和。

可有多种用法:

for(i=0;i<3;i++) for(j=0;j<4;j++) s+=a[i][j];

for(i=0;i<3;i++) for(j=0;j<4;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() { int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int i,k,*p; 1 2 3 4 p=a; 5 6 7 8 k=*p;? k=p[1][2]; k=p[1*4+2]; 不合法 合法 9 10 11 12 k=*(*(p+1)+2); k=*(p+1*4+2); k=*(p+2);? for(p=a;p<a+2;p++)printf(“%3d”,*p); ? }

例:求矩阵的上三角元素之和。

main() { int a[3][4],*p,i,j,s=0; 输入a p=a; for(i=0;i<3;i++) for(j=i;j<4;j++) s+=p[i*4+j]; 或 s+=*(p+4*i+j) printf(“ %d”,s); }

●指向由m个元素组成的一维数组的指针变量

可以这样定义一个指针变量: int (*p)[4] 表示p为指向由4个元素组成的行指针变量。

当p=a时,可通过p引用a[i][j]:

p[i][j] 或 *(*(p+i)+j)

例:求矩阵的上三角元素之和。

main() { int a[3][4],(*p)[4],i,j,s=0; 输入a p=a; for(i=0;i<3;i++) for(j=i;j<4;j++) s+=p[i][j]; 或 s+=*(*(p+i)+j) printf(“ %d”,s); }

●多维数组的指针作函数参数 用于接受实参数组地址的形参可用两种:行指 针和列指针。

以方阵转臵为例: void at(int (*a)[3]) 用行指针 { int i,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; } }

用列指针: void at(int *a,int n) { int i,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; } } 优点?#21644;?#29992; 在编通用函数时,一般使用列指针。

10.4 字符串的指针和指向字符串的指针变量

■字符串的表示形式

可用两种方法访?#39318;?#31526;串:

①用字符数组存放字符串

②用字符指针指向一个字符串

main() { char c[5]=”abc”; 定义字符数组,并将字符串存入 char *p1=c,*p=”abc”;定义指针变量,指向字符串 printf(“%s”,c); 通过数组名访?#39318;?#31526;串 printf(“%s”,p); 通过指针变量访?#39318;?#31526;串 printf(“%-c”,*(p+3)); 通过指针变量访?#39318;?#31526; }

c

1000

a

b c \0 p 1000

a

b

c \0

与其它一维数组的指针相比,字符串的指 针有其独特之处:

②对字符串的操作依赖于结束符。

③可以整体赋初值。

④有各种字符串处理函数。

①可以通过指针对字符串进行整体访问。

本节重点掌握: ①通过数组和通过指针操作字符串的 基本方法。

②常用的字符串处理方法。

例:字符串拷贝操作。

main() { char a[]=”abcdef”,b[20]; int i; for(i=0; *(a+i)!=?\0?; i++) *(b+i)=*(a+i); *(b+i)=?\0?; printf(“%s”,b); } main() 用指针变量处理 { char a[]=”abcdef”,b[20],*p1, *p2; p1=a; p2=b; for( ; *p1!=?\0?;p1++,p2++) *p2=*p1; *p2=?\0?; printf(“%s”,b); }

将拷贝操作编成一函数: void copy_string(char *from,char *to) { for(; *from; from++,to++) *to=*from; *to=0; } 还可以改成: void copy_string(char *from,char *to) { for(; *from;) *to++=*from++; *to=0; }

字符串合并函数: void append_string(char *from,char { for(;*to; to++); for(; *from;) *to++=*from++; *to=0; }

*to)

阅读程序: void f (char *c) { c+=2; (*c)++; c++; *c=0; }

main() { char c[20]=”abcdef”; f(c+1); printf(“%s”,c); }

■内存空间的动态分配

在程序设计中,对于要处理的批量数据, 我们往往是选用数组作为存放这些数据的数据 结构,然而,数组有一个明显的缺点,就是在 定义数组时,其长度必须是常值,无法根据需 要动态地定义。

这样,在很多情况下,不是定 义的数组长度不够,就是定义太长以至于浪?#36873;?p>采用动态分配可以克服这一缺点,并且可 ?#36816;?#26102;释放。

动态分配内存空间步骤: ①定义一指针变量。

②申请一片内存空间,并将其首地址赋给指 针变量。

此时便可通过指针变量访问这片内存。

③用完后释放这片内存空间。

int *p; p p=malloc(byte); …… free(p);

以上函数的原形在stdio.h?#23567;?p> 例:对n个学生的分数排序后输出。

#include “stdio.h” void sort(int *a, int n) { ┈ } 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 函数的指针和指向函数的指针变量

■用函数指针变量调用函数

可以用指针变量指向一个函数,一个函数在 编译时被分配给一个入口地址,这个入口地 址就称为函数的指针。

可以用指针变量指向 函数,然后通过该指针变量调用此函数。

int max(int x, int y) { int z; if(x>y) z=x; else z=y; return(z);} main() { int (*p)(); 定义指向函数的指针变量p int a,b,c; p=max; 将p指向函数max scanf(“%d%d”,&a,&b); c=(*p)(a,b); 通过p调用函数max 等效于c=max(a,b); printf(“ %d”,c); }

■把指向函数的指针变量作为函数参数

指向函数的指针变量最常见的用途是把它 作为函数的参数,用于接受主调函数传来的某 一函数的入口地址,从而在被调函数中可以通 过该指针变量调用它所指向的函数,这样,被 调函数中就可实现非固定函数的调用,?#28304;?#21040; 编写通用函数的目的。

关键问题:如何处理?#25442;?#20989;数是未知的。

例:用矩形法编写一个通用的求定积分的函数。

double {

intgral (double double int i; double h,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);

a,double b,int (*f)( ) )

n,

double f1(double x) { return(3*x*x+2*x-1); } main() { double s; s=integral(1.0,2.0,100,f1); }

}

第十一章

11.1 概述

结构体

在实际应用中,有不少应用问题如果只采 用已学的变量和数组作为数据结构显得很不方 便。

例:输入100个学生的学号、姓名和考试成 绩,编写程序?#39029;?#39640;分者和低分者。

用变量和数组作数据结构可编写程序如下:

main() { int i, num, maxnum, minnum; char name[20], maxname[20], minname[20]; int score, 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);} } 输出 }

明显缺点:

①变量过多,同一学生的各个数据无联系, 没有整体概念,不便管理。

②操作不便(如更新过程)。

显然,选用一种能把一个学生的数据构造成 一个整体的构造型数据结构更合适,但不能是数 组。

对于这种情况,可以将一个学生的数据定义 为一个结构体类型:

struct student { int num; char name[20]; int score; };

类型名

成员表

定义了一个结构体类型,它包含三个成员。

11.2 定义结构体类型变量的方法

前面定义的结构体类型只是一种“模型?#20445;?还必须定义结构体变量后才能存放数据。

定义结构体变量有三种方法:

1、先定义结构体类型再定义结构体变量

定义了结构体类型后:

struct

student

st, stmax, stmin; 变量名

类型符

定义了三个结构体变量,每个变量包含三个成 ?#20445;?#27599;个变量可存放一个学生的数据。

2、在定义结构体类型的同时定义结构体变量

struct student

{

int num;

char name[20];

int score;

}st, stmax, stmin;

3、直接定义结构体类型变量 struct 不出现类型名 { int num; char name[20]; int score; }st, stmax, stmin;

常用第一种方法

说明: ①类型与变量不同,只对变量分配空间与操作。

②对成员可以单独使用,相当于普通变量。

③成员也可以是一个结构体变量。

struct date struct student { int month; { int num; int day; char name[20]; int year; struct date birthday; }; }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) ;

可以引用成员的地址

如果成员本身?#36136;?#19968;个结构体类型,则 要用若干个成员运算符,一级一级地找到最 低一级的成?#20445;?#21482;能对最?#22270;?#30340;成员进行存 取与运算。

st1.birthday.year=1960; st1.birthday.month=5; st1.birthday.day=15;

■整体引用

可以对结构体变量进行整体赋值:

stmax=st; 将st中的所有内容赋值给stmax。

对结构体变量的整体操作只限于赋值操作 和参数传递,而且要求类型一致。

不能对结构 体变量进行整体输入输出。

结构体应用举例:

编写程序输入100个学生的学号、姓名和 考试成绩,?#39029;?#39640;分者和低分者。

struct student { int num; char name[20];

int score;

};

main() { int i; struct student st,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(“%5d%15s%5d”,stmax.num,stmax.name, stmax.score); printf(“%5d%15s%5d”,stmin.num,stmin.name, stmin.score); }

11.4 结构体变量的初始化

对结构体变量可以在定义时指定初始值 struct student { int num; char name[20]; int score; }st={1001,”wang”,95};

11.5 结构体数组 可以定义结构体数组来存?#25490;?#37327;数据。

■结构体数组的定义 struct student { int num; char name[20]; int score; };

struct student a[100]; 定义a数组,可?#28304;?#25918;100个学生的数据。

a数组的每个元素又是一个结构体变量。

■结构体数组的初始化 在定义结构体数组的同时指定初值。

struct student { int num; char name[20]; int score; };

struct student a[2]= {{1001,”LiLi”,85},{1002,”wang”,90}};

或: struct student { int num; char name[20]; int score; } 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个学生的学号、姓名和考试成绩,

然后按从高分到低分的顺序排列后输出。

struct student { int num; char name[20]; int score; }; main() { int i, j; struct student a[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((“%5d%15s%5d”,a[i].num,

a[i].name,a[i].score);

}

例:(p266例11.2)

对候选?#35828;?#31080;的统计程序。

设有三个候选人, 每次输入一个得票候选?#35828;?#21517;字,要求最后输 出各候选?#35828;?#24471;票结果。

#include “string.h” struct person { char int name[20]; count;

}leader[3]={“Li”,0,”zhang”,0,”wang”,0};

main()

{ int i, j ; char leader_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(“”);

for(i=0;i<3;i++)

printf(“%15s%5d”,

leader[i].name,leader[i].count);

}

11.6 指向结构体类型数据的指针

■指向结构体类型变量的指针 struct student st, st1;

struct student *p;

p=&st;

定义指向结构 体类型数据的 指针变量p

通过指针变量引用结构体变量: ①成员引用

(*p).num=1001;

(*p).score=85;

或 p->num=1001;

或 p->score=85;

strcpy((*p).name,”wang”);

或 strcpy(p->name,”wang”);

②整体引用

st1=*p; 等效于 st1=st;

■指向结构体数组的指针 struct student a[100];

struct student *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)).score=85; 或 (p+i)->num=1001; 或 (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() { struct student st={1001,”LiLi”,70}; f(st); printf(“ %5d%10s%5d”, st.num,st.name,st.score); } f(struct student a) { a.score=90; printf(“ %5d%10s%5d”, a.num,a.name,a.score); }

st 1001 LiLi 70

a 1001 LiLi 70 90

main() 2000 { struct student st={1001,”LiLi”,70}; f(&st); } f(struct student *a) { a->score=90; }

st 1001 LiLi 70 90

printf(“ %5d%10s%5d”,st.num,st.name,st.score);

a 2000

printf(“%5d%10s%5d”,a->num,a->name,a>score);

通过指针变量a可以访问它所指向的结构体。

11.7 用指针处理链表

■链表概述 链表是一种重要的数据结构─动态数据结构。

以具体例子来说明链表的概念及其应用:

例:选择合?#23454;?#25968;据结构来存放一批学生的学号 及考试成绩,以便进一步处理。

由于学生人数未知,用静态数据结构不合适。

用链表处理较恰当。

用链表处理该问题的基本思路: 将各学生的数据进行离散存放,来一个学生 就分配一小块内存(结点)。

并将各结点用指针 ?#26469;?#36830;接起来─链表。

head 学号 成绩 指针 学号 成绩 指针 学号 成绩 指针 学号 成绩 指针 学号 成绩

NULL

每结点应包含下一结点的开始地址。

最后一个结点中的指针为空。

链?#20998;?#38024;指向第一个结点,是访问链表的重要依据。

这样的链表称单向链表。

一个结点可用如下结构体描述: typedef struct student { int num; 学号 int score; 成绩 struct student *next; 下一结点的首地址 } STU;

typedef : 自定义类型符(见11.10)

■单向链表的建立 ①输入一个学生的数据。

②分配结点空间,数据存入。

③将该结点的首地址赋给上一结点的next,若 该结点是第一个结点,则赋给?#20998;?#38024;。

④将该结点的next臵为空,表示该结点为当前 的最后结点。

head 学号 成绩 next 学号 成绩 next 学号 成绩 next 学号 成绩 next

学号 成绩

NULL

STU *creat() { STU st,*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; 学号 学号 head 学号 } 成绩 成绩 成绩 NULL return head; next next }

■单向链表的访问

以输出为例 ①通过?#20998;?#38024;找到第一个结点. ②输出当前结点的内容,并通过next找到后 继结点,┄┄,直到next为空.

void output(STU *head) { STU *p=head; while(p) { printf(" %d %d",(*p).num,(*p).score); p=(*p).next; } }

head 学号 成绩 next 学号 成绩 next 学号 成绩 next 学号 成绩

NULL

■删除结点操作 ①按链表的访?#21490;?#27861;找到相应结点。

②若该结点是第一个结点,则将后继结点指针 赋给?#20998;?#38024;。

若该结点是最后一个结点,则将前缀结点的 next臵为空。

若该结点是中间结点,则将后继结点指针赋 给前缀结点的next。

③释放该结点所占的内存单元。

head 学号 成绩 next 学号 成绩 next 学号 成绩

NULL

STU *delete(STU *head,int number) { STU *p =head,*p0=NULL; 假定要删除某一 指定学号的结点 while(p) { if((*p).num==number) { if(p==head) head=(*p).next; else if((*p).next==NULL) (*p0).next=NULL; else (*p0).next=(*p).next; free(p); break; }else {p0=p; p=(*p).next;} } return head; }

■插入操作

head 学号 成绩 next 学号 成绩 next 学号 成绩

NULL

学号 成绩 next

假定将结点p 插入到结点p0的后面, 则插入操作 的关键为: p->next=p0->next; p0->next=p;

第十三章

文件

3.1 文件概述 ■文件概念 所谓文件就是:存储在外部介质上 的信息集合。

根据存储的介质不同可分为: ?#25490;?#25991;件、磁带文件等。

根据内容的不同可分为: 程序文件、数据文件等。

■使用文件输入输出的必要性

这里主要?#33268;?#25968;据文件的输入输出,即 如何将文件中的数据“输入”到程序的数据 结构中,如何将程序的数据结构中的数据 “输出”到文件?#23567;?p> 以往的输入输出方法: 键盘输入 ,屏幕输出。

这种方法不适用于数据量大的情况。

键盘输入?#25512;?#24149;输出例: main() { int i, a[1000]; for(i=0;i<1000;i++) scanf(“%d”,a+i); ┊ for(i=0;i<1000;i++) printf(“%5d”,a[i]); }

缺 点: ①可能出现重 复输入。

②输出的数据 不能保存,不 便于进一步使 用。

}

采用文件输入输出可以克服这些缺点。

main() { int i, a[1000]; for(i=0;i<1000;i++) scanf(“%d”,a+i); ┊ for(i=0;i<1000;i++) printf(“%5d”,a[i]); }

文件

文件

■ C文件分类 按在?#25490;?#19978;存储的形式不同,可分为: 文本文件: 以ASCII字符存放—可见、可编辑、占 空间大。

二进制文件: 以二进制形式存放—不可见、不可编辑、 占空间小。

使用时可根据需要选择。

13.2 文件类型指针 每个被使用的文件都在内存中开辟一 个区,用来存放文件的有关信息。

这些信 息保存在一个FILE类型的结构体变量?#23567;?p> 若 FILE *fp; 则fp就称为指向文件类 型的指针变量。

访问文件通过文件指针进 行。

FILE结构体类型是?#19978;低?#23450;义的。

具体定义如下:

typedef struct { short level; 程度 unsigned flags; char fd; unsigned char hold; short bsize; unsigned char *buffer; unsigned char *curp; unsigned istemp; short token; }FILE;

缓冲区“满”或“空”的

文件状态标志 文件描述符 如无缓冲区不读取字符 缓冲区的大小 缓冲区的位臵 当前读写指针 临时文件,指示器 用于?#34892;?#24615;检验

13.3 文件的打开与关闭 对文件的读写之前应?#25353;?#24320;?#22791;?#25991;件。

使用结束后“关闭”此文件。

■文件的打开(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” 按只写方式打开一个二进制文

“r+” “w+” “a+”

按读写方式打开一个文本文件 按读写方式建立一个新的文本文件 按读写方式打开一个文本文件

“rb+” 按读写方式打开一个二进制文件

“wb+” 按读写方式建立一个新的二进制文

“ab+” 按读写方式打开一个二进制文件

说明: (1)不能用”r”方式打开一个不存在 的文 件,”r”方式只读不能写。

(2)“w” 方式只写不能读,具有建立 和 覆盖功能。

(3)调用fopen函数时,如果返回NULL 则 表?#25964;?#24320;不成功。

■文件的关闭(fclose 函数)

在使用完一个文件后应用fclose 函数关 闭文件,形式为: fclose(文件指针);

如: fclose(fp);

关闭后fp不再指向该文件。

13.4 文件的读写 文件打开后,就可以对它进行读写了。

■文本文件的读写 即如何将以文本方式存放的文件输入到程 序的数据结构?#23567;?p>如何将程序的数据结构中 的数据以文本方式输出到文件?#23567;?p> 用于对文本文件读写的函数有: fscanf

fgetc, getc fgets

fprintf

fputc, putc fputs

以例子说明fscanf和fprintf的使用。

例 : 已 知 文 本 文 件 f1.txt 中 存 放 有 100个学生的分数,要求读入这些数据, 并按从高到低的顺序排序后输出到另一 文件?#23567;?p> #include “stdio.h” void sort(int *a,int n) { ……} main() { int i,a[100]; FILE *fp; fp=fopen(“f1.txt”, “r”); if(fp==NULL) exit(0);

定义一个指 向文件的指 针变量

打开文件, 使fp指向文 件f1.txt

for(i=0;i<100;i++) fscanf(fp,”%d”,a+i);

从fp所指 的文件中 读数据

fclose(fp);

sort(a,100); fp=fopen(“f2.txt”, “w”); for(i=0;i<100;i++) fprintf(fp,”%4d”,a[i]); fclose(fp); }

注意:文本文件的输入格式要与 文件中的数据格式匹配。

关闭fp所 指的文件

■二进制文件的读写 即如何将以二进制方式存放的文件输入 到程序的数据结构?#23567;?p> 如何将数据结构中的数据以二进制方式 输出到文件?#23567;?p>读写函数: fread getw

fwrite putw

例:将前例中的排序结果改用二进制方式 输出到文件f3.dat?#23567;?p> #include “stdio.h” void sort (int *a,int n) { ……} main() { int i,a[100]; FILE *fp; fp= f open(“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() { int a[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() { int i,a,n=0; float aver=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(“ %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中每?#24418;?#19968;个学生的数据,按定 长格式存放,?#26469;?#20026;:学号(整数,占5格)、姓名 (占10格)、成绩(整数,占4格)。

(2)按学号从小到大的顺序连号存放,起始学号 为1001。

#include “stdio.h” typedef struct { int num; char name[20]; int score; }STU; main() { int no; STU st; FILE *fp;

fp=fopen ( “f5.txt” , ”r” ); scanf ( “%d” , &no ); fseek ( fp, (no-1001)*19, 0 );

1001 LiLi 90 1002 WangPing 100 1003 HuHeng 75 ┊

fscanf ( fp, ”%5d%10s%4d” ,&st.num ,st.name, &st.score );

printf (“%5d%10s%4d” , st.num ,

st.name, st.score ) ;

fclose ( fp ) ;

}

如果是二进制 文 件呢?

上例的检索方法称为“定位检索”。

如果是非定长格式,则需要用“遍历检索” 。

while ( !feof ( fp ) ) { fscanf ( fp, ”%d%s%d”, &st.num, st.name, &st.score ); if ( st.num==no ) { printf ( “%5d%10s%4d”, st.num, st.name, st.score ); break; } } 速度慢,但不受限制

综合例: 已知文本文件f1.txt中存放?#24418;?#27721;市所有 公民的有关性别和年龄的数据,请编写程序分 别?#39029;?#20854;中10名男寿星和10名女寿星,并将20

名寿星的数据以文本文件的方式存入到文件

f2.txt中(先男后女)。

说明:

① 文件f1.txt中每?#24418;?#19968;个公民的数据,共有3项 ,?#26469;?#20026;:姓名(不超过10个字符)、性别(0表示 男,1表示女)和年龄(整数),项间以空格分隔。

② 未给出公民个数,将文件中的数据读完为止。

算法思想: 开辟一个存放20名寿星数据的结果表 a(结构体数组),然后逐个读取公民 数据,每读取一个就向a?#23567;?#21028;断插入 ”一个,?#34892;?#20844;民往前?#23614;澹?#22899;性公民 往后?#23614;濉?p> 寿星表a

读一个公民 的数据到p

?#34892;圆?#20837;

女性插入 N 读 完 否 ?

Wanghao 0 100 Liming 0 98 ┊ wudan 1 99 xiaofang 1 95 ┊

Y

#include <stdio.h> typedef struct { char name[10]; int sex; int age; } PEP;

插入函数,将一个公民的数据插入到寿星表

void insert (PEP *a, int n, PEP t ) { int i,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() { int j; PEP p,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,”%15s%2d%5d”, a[j].name, a[j].sex,a[j].age ); fclose ( fp ); }

C语言学习入门视频教程网址.doc

C语言学习入门视频教程网址 - C 语言学习视频教程 九江 新起点 c 语言 习题 1 和 2.mp4 九江 新起点 c 语言 习题 3 九江 新起点 c 语言 第四章 选择结构 ......

?#35835;?#22522;础入门学习C语言》视频教程完全免费.doc

?#35835;?#22522;础入门学习C语言》视频教程完全免费 - ?#35835;?#22522;础入门学习 C 语言》视频教程(小?#23376;?#20027;讲全套共 65 节) 同时按 ctrl+要下载的地址既?#19978;略?#23545;应的视频 教材:......

C语言入门自学教程[傲梦].doc

C语言入门自学教程[傲梦] - C 语言入门自学教程 C 语言是一种通用的、面向...

C语言入门教程 by shuax原创教程~强烈推荐新手学习.doc

C语言入门教程 by shuax原创教程~强烈推荐新手学习 - 本文由 caoc...

C语言入门课程安排.doc

C语言入门课程安排 - 开班人数:2-5 人 第一课: 年级:3 年级以上 教学目标:了解什么 C 语言编程。学习第一个 C 语言程序。(让计算机开口说话)。学习简单的......

(1小时学会C语言51单片机)C语言入门教程.doc

(1小时学会C语言51单片机)C语言入门教程 - 相信很多爱好电子的朋友,对单片...

C语言程序设计视频教程免费学习_C/C++_教学视频大全.doc

视频教程,自学吧全套教学,在线学习C/C++课程,C语言程序设计视频教程视频下载... 欢迎访问尚观免费C语言入门教程,可能你会有很多疑问,我没学过C语言,学C语言难吗?他......

《C语言开发入门教程》—习题答案.doc

《C语言开发入门教程》—习题答案 - 博学?#21462;?#35753; IT 教学更简单,让 IT 学习更?#34892;?《C 语言开发入门教程》习题答案 第 1 章 初识 C 语言 一、填空题 1、......

吕鑫:0基础C语言教程(最博大精深的C语言视频教程)共75集.doc

这是C++教育行业最经典最流行的是网络教程,?#21344;?#21644;扩展的脚步势不可挡,请让你最亲的人先知道! 想一想你身边哪些人需要学C语言的,想学C++和数据结构的,想学MFC......

C语言编程:vc++6.0入门教程及习题.doc

C语言编程:vc++6.0入门教程及习题 - vc++6.0 入门教程 步骤是:...

(1小时学会C语言51单片机)C语言入门教程1.doc

(1小时学会C语言51单片机)C语言入门教程1 - 我们在单片机最小?#20302;成?#25509;个 ...

单片机C语言入门教程.doc

单片机 C 语言入门教程来源:21ic 关键字:单片机 C 语言 作者: 入门教...

C语言学习教程.doc

C语言学习教程 - C 语言学习教程.txt43 风帆,不挂在桅杆上,是一块无用...

零基础入门嵌入式——最完整嵌入式C语言基础教程_基础_....doc

嵌入式入门学员学生应掌握C语言的基本语法,还应掌握程序设计的基本思想、并通过?#31350;?..

最好的单片机C语言快速入门教程.doc

最好的单片机C语言快速入门教程 - 单片机 C 语言快速入门教程 相信很多爱好电...

C语言学习基本教程.doc

C语言学习基本教程 - c语言考试基本教程 ,计算机等级考试c语言考试内容,看过...

C语言入门教程 (三) 运算符.doc

C语言入门教程 (三) 运算符 - 无论是加减?#39034;?#36824;是大于小于, 都需要用到运算...

C语言入门教程:表达式和语句.doc

C语言入门教程:表达式和语句 - 一、表达式 前面已经提到过表达式,相信大家对表...

(1小时学会C语言51单片机)C语言入门教程.doc

(1小时学会C语言51单片机)C语言入门教程 - 相信很多爱好电子的朋友,对单片...

C语言编程:vc++6.0入门教程及习题.doc

C语言编程:vc++6.0入门教程及习题 - vc++6.0 入门教程 步骤是:...

C语言入门例题.txt

C语言入门例题 - 本文由iloveumam贡献 doc文档可能在WAP端浏览体...

c语言入门必做的题2.txt

c语言入门必做的题2_IT/计算机_专业资料。c语言入门必做的题2入门必做的题2...

C语言堆栈入门——堆和栈的区别.txt

C语言堆栈入门——堆和栈的区别 - 2010年1月29日 C语言堆栈入门——堆和...

C语言入门第4讲 基本运算与表达式.txt

C语言入门第4讲 基本运算与表达式 - 标题:第4讲 基本运算与表达式 11网络...

C语言指针入门.txt

C语言指针入门 - 指针 C语言编程入门(十三) ...... C语言指针入门_IT?#29616;资格考试/?#29616;教育专区。 ...基础知识:C语言和指针 5页 免费 c语言基础教程_第......

c语言入门程序(学生成绩信息)(dev_cpp编译).txt

c语言入门程序(学生成绩信息)(dev_cpp编译) - #include<...

C语言入门之指针的慨念(2).txt

C语言入门之指针的慨念(2) - 对于指向数组的指针变量,可以加上或减去一个整数...

C语言网络编程快速入门2.txt

C语言网络编程快速入门2 - Windows下C语言网络编程快速入门 2004-...

Windows下C语言网络编程快速入门.txt

Windows下C语言网络编程快速入门 C语言的学习,一般的方式是,先学C,然后是C++,...而在学校教学中,也没有时间深入学习Windows编程的实用技术了。 其实,具有了C......

谭浩强C语言教材源代码第五章.txt

谭浩强C语言教材源代码第五章 - 将两个数从小到大输出 #include<...

C语言学习入门视频教程网址.doc

C语言学习入门视频教程网址 - C 语言学习视频教程 九江 新起点 c 语言 习题 1 和 2.mp4 九江 新起点 c 语言 习题 3 九江 新起点 c 语言 第四章 选择结构 ......

?#35835;?#22522;础入门学习C语言》视频教程完全免费.doc

?#35835;?#22522;础入门学习C语言》视频教程完全免费 - ?#35835;?#22522;础入门学习 C 语言》视频教程(小?#23376;?#20027;讲全套共 65 节) 同时按 ctrl+要下载的地址既?#19978;略?#23545;应的视频 教材:......

C语言入门自学教程[傲梦].doc

C语言入门自学教程[傲梦] - C 语言入门自学教程 C 语言是一种通用的、面向...

C语言入门教程 by shuax原创教程~强烈推荐新手学习.doc

C语言入门教程 by shuax原创教程~强烈推荐新手学习 - 本文由 caoc...

C语言入门课程安排.doc

C语言入门课程安排 - 开班人数:2-5 人 第一课: 年级:3 年级以上 教学目标:了解什么 C 语言编程。学习第一个 C 语言程序。(让计算机开口说话)。学习简单的......

(1小时学会C语言51单片机)C语言入门教程.doc

(1小时学会C语言51单片机)C语言入门教程 - 相信很多爱好电子的朋友,对单片...

C语言程序设计视频教程免费学习_C/C++_教学视频大全.doc

视频教程,自学吧全套教学,在线学习C/C++课程,C语言程序设计视频教程视频下载... 欢迎访问尚观免费C语言入门教程,可能你会有很多疑问,我没学过C语言,学C语言难吗?他......

《C语言开发入门教程》—习题答案.doc

《C语言开发入门教程》—习题答案 - 博学?#21462;?#35753; IT 教学更简单,让 IT 学习更?#34892;?《C 语言开发入门教程》习题答案 第 1 章 初识 C 语言 一、填空题 1、......

吕鑫:0基础C语言教程(最博大精深的C语言视频教程)共75集.doc

这是C++教育行业最经典最流行的是网络教程,?#21344;?#21644;扩展的脚步势不可挡,请让你最亲的人先知道! 想一想你身边哪些人需要学C语言的,想学C++和数据结构的,想学MFC......

C语言编程:vc++6.0入门教程及习题.doc

C语言编程:vc++6.0入门教程及习题 - vc++6.0 入门教程 步骤是:...

(1小时学会C语言51单片机)C语言入门教程1.doc

(1小时学会C语言51单片机)C语言入门教程1 - 我们在单片机最小?#20302;成?#25509;个 ...

单片机C语言入门教程.doc

单片机 C 语言入门教程来源:21ic 关键字:单片机 C 语言 作者: 入门教...

C语言学习教程.doc

C语言学习教程 - C 语言学习教程.txt43 风帆,不挂在桅杆上,是一块无用...

零基础入门嵌入式——最完整嵌入式C语言基础教程_基础_....doc

嵌入式入门学员学生应掌握C语言的基本语法,还应掌握程序设计的基本思想、并通过?#31350;?..

最好的单片机C语言快速入门教程.doc

最好的单片机C语言快速入门教程 - 单片机 C 语言快速入门教程 相信很多爱好电...

C语言学习基本教程.doc

C语言学习基本教程 - c语言考试基本教程 ,计算机等级考试c语言考试内容,看过...

C语言入门教程 (三) 运算符.doc

C语言入门教程 (三) 运算符 - 无论是加减?#39034;?#36824;是大于小于, 都需要用到运算...

C语言入门教程:表达式和语句.doc

C语言入门教程:表达式和语句 - 一、表达式 前面已经提到过表达式,相信大家对表...

(1小时学会C语言51单片机)C语言入门教程.doc

(1小时学会C语言51单片机)C语言入门教程 - 相信很多爱好电子的朋友,对单片...

C语言入门例题.txt

C语言入门例题 - 本文由iloveumam贡献 doc文档可能在WAP端浏览体...

c语言入门必做的题2.txt

c语言入门必做的题2_IT/计算机_专业资料。c语言入门必做的题2入门必做的题2...

C语言堆栈入门——堆和栈的区别.txt

C语言堆栈入门——堆和栈的区别 - 2010年1月29日 C语言堆栈入门——堆和...

C语言入门第4讲 基本运算与表达式.txt

C语言入门第4讲 基本运算与表达式 - 标题:第4讲 基本运算与表达式 11网络...

C语言指针入门.txt

C语言指针入门 - 指针 C语言编程入门(十三) ...... C语言指针入门_IT?#29616;资格考试/?#29616;教育专区。 ...基础知识:C语言和指针 5页 免费 c语言基础教程_第......

c语言入门程序(学生成绩信息)(dev_cpp编译).txt

c语言入门程序(学生成绩信息)(dev_cpp编译) - #include<...

C语言入门之指针的慨念(2).txt

C语言入门之指针的慨念(2) - 对于指向数组的指针变量,可以加上或减去一个整数...

C语言网络编程快速入门2.txt

C语言网络编程快速入门2 - Windows下C语言网络编程快速入门 2004-...

Windows下C语言网络编程快速入门.txt

Windows下C语言网络编程快速入门 C语言的学习,一般的方式是,先学C,然后是C++,...而在学校教学中,也没有时间深入学习Windows编程的实用技术了。 其实,具有了C......

  • 本文相关:
  • C语言入门教程基础
  • C语言编程入门教程
  • C语言入门教程概述图文
  • C语言入门教程——第2章_算法
  • C语言编程入门教程精简版
  • (1小时学会C语言51单片机)C语言入门教程
  • c语言基础入门
  • C语言入门教程——第1章_概述_图文.ppt
  • C语言c语言入门
  • C语言入门及教学详解1
  • www.uvof.tw true http://www.uvof.tw/wendangku/z3s/f3bg/j3dc2265901v/k020206409c06l.html report 102130 y) z=x; c=max(a,b); else z=y; printf(“\\nmax is:%d”,c); return(z); } }\na b c\n3 5 5\n\nx y z\n\n3 5 5\n\n(两个函数组成)\n\n\f总结上例可知: (1) C程序由函数构成。 (2) 函数由两部分组成: 函数说明部分:函数名、函数类型、形 参名、形参类型。 函数体:实现函数的具体操作;由语句 构成。 (3) 程序总是从main函数开始执行。
    • 猜你?#19981;?/li>
    • 24小时热文
    • 本周?#32469;?/li>
    图文推荐
    • 最新添加
    • 最热文章
    精彩推荐
    读过此文的还读过
    琼崖海南麻将安卓版
    <ins id="h3npf"><span id="h3npf"></span></ins>
    <cite id="h3npf"><span id="h3npf"></span></cite><progress id="h3npf"></progress>
    <cite id="h3npf"></cite>
    <listing id="h3npf"><dl id="h3npf"><progress id="h3npf"></progress></dl></listing>
    <cite id="h3npf"><video id="h3npf"></video></cite>
    <cite id="h3npf"><video id="h3npf"><menuitem id="h3npf"></menuitem></video></cite>
    <ins id="h3npf"></ins><var id="h3npf"><video id="h3npf"></video></var><cite id="h3npf"></cite><cite id="h3npf"></cite>
    <ins id="h3npf"><span id="h3npf"></span></ins>
    <cite id="h3npf"><span id="h3npf"></span></cite><progress id="h3npf"></progress>
    <cite id="h3npf"></cite>
    <listing id="h3npf"><dl id="h3npf"><progress id="h3npf"></progress></dl></listing>
    <cite id="h3npf"><video id="h3npf"></video></cite>
    <cite id="h3npf"><video id="h3npf"><menuitem id="h3npf"></menuitem></video></cite>
    <ins id="h3npf"></ins><var id="h3npf"><video id="h3npf"></video></var><cite id="h3npf"></cite><cite id="h3npf"></cite>
    35选7开奖 3的乐透乐彩票论坛 北京赛车龙虎软件 重庆时时彩投注技巧 明星斗地主单机版 新疆福彩网18选7 超准一尾中特规律 印尼五分彩怎么玩 3d如何判断出组三 酷玩三张牌354版本 搜国家体彩排列三排列五走势图 福建时时彩平台官网下载 江苏十一选五兑奖时间 中啦彩票网站 北京pk10开奖视频直播