第一章 概述
★ 内容提要:
C 语言概貌
程序设计思想和程序结构
程序设计方法与要点
算法描述应用
基本输入输出
程序方式
? 绪论
? C语言的特点
? 库函数应用
? 自定义函数
? C程序的组成
? C编程方式
C 语言是目前世界上最流行和实用的一种计算机高级
程序设计语言。最初的 C 语言只是为描述和实现 UNIX
操作系统提供一种工作语言而设计的,后随其宿 主系
统 UNIX 的普及而被引起注意,又因其本身的高效、灵
活、功能丰富、表达力强、移植性好等特出优点 受到
广泛的重视并普及应用。
? 编写应用软件,数据处理,科学工程数值计算等领域。
? 编写系统软件, 操作系统,编译系统,系统实用程序。
? 高校开设程序设计课程的必修首选语言。
1.1 绪论
(1) C 语言在软件、硬件系统与用户中所处的位置
汇编语言
机器语言
低级语言:具有面 向硬件系统便于
直接访问硬件的特 点功能,但没有
数据类型,不易阅读、记忆,推广。
……
FORTRAN 语言
pascal 语言
BASIC 语言
高级语言:具有丰富的数据类型
和运算符,便于描述数据结构,
既具有强有力的表达力,可加快
开发 速度,提高工作效率,面 向
用户、便于记忆、书写和阅读等。用户、便于记忆、书写和阅读等。
系统
软
件
硬
件
用户
1.2 C 语言的特点
C 语言 吸取了高低级语言优点,兼而有之。
( 2 ) C 语言是一种结构化程序设计语言便于模块化软
件设计。结构化程序设计思想和目的是使程序具有结
构合理,正确性高易验证。而且规定总结了一套程序
设计准则。可以简单归纳为以下几点:
? 基于自顶向下,逐步求精的设计方法;
? 程序书写遵循一定的格式,使结构清晰;
? 程序中只包含三种基本的结构:顺序、分支、循环。
? 程序由模块构成,每个模块具有独力的功能。模 块
之间的数据联系要简单,每个模块只能有一个入口和
一个出口;
三种最基本的结构:顺序、分支、循环。
语句组
顺序结构
语句 1
Y N
条件
语句 2
分支结构
N
条件
语句组
循环结构
Y
程序 = 数据结构 + 算法
数据结构:
? 逻辑结构,计算机外部的数据及其数据之间的关系。
? 存储结构,外部数据及其数据之间的关系在计算机
内部的实现。(一般通过类型来表达)
? 运算,定义在逻辑结构之上的操作,通过算法描述
算法,是对问题求解过程的一种描述,是为解决一个
或一类问题给出的一个确定的有限长的操作序列。
? 有输入,算法加工的对象;
? 有穷性,对于任意一组合法的输入值,在执行有穷
步骤之后一定能结束;
? 确定性,对于每种情况下所应执行的操作,在算法
中都有确切的规定(不存在二义性);
? 可行性,算法中的所有操作都必须足够基本,都可
以通过已经实现的基本操作运算有限次实现之;
? 有输出,它是一组与, 输入, 有确定关系的量值,是
算法进行信息加工后得到的结果。
(3) 用函数作为程序模块以实现程序的模块化结构
# include <stdio.h>
# include <math.h>
# define PI 3.14159
main(){
d o u b l e a r e a ( d o u b l e x ) ;
double r,a;
scanf("%lf",&r);
r=pow(r,2.0);
a=area(r);
printf("area=%f \ n",a);
return(0);
}
? 以 ? # ? 打头的预处理命
令用以包含相关文件,
及定义符号常数。
以
令用以包含相关文件,
求解园面积的编程示例
? C 程序中的函数、
变量、符号常数必须
先定义后使用,否则
应作预先声明。
程序中的函数、
变量、符号常数必须
先定义后使用,否则
(3) 用函数作为程序模块以实现程序的模块化结构
# include <stdio.h>
# include <math.h>
# define PI 3.14159
main(){
d o u b l e a r e a ( d o u b l e x ) ;
double r,a;
scanf("%lf",&r);
r=pow(r,2.0);
a=area(r);
printf("area=%f \ n",a);
return(0);
}
? 以 mai n() 标识的主函数
是 C 程序运行开始时由系
统调用的一个特殊 函数,
不管其所在位置是 程序中
的前或后,执行总 是从它
开始。
? C 程序可由一个或多个函
数构成,但必须存 在一个
主函数,执行语句 中可以
调用其它函数,但 它不能
被其它函数调用,也不能
自己调用自己。
? 其它函数指,C 编译系统
提供的库函数;用 户自定
义函数。
求解园面积的编程示例
? 函数的基本形式:
函数类型 函数名(形参表 列 ) {
数据说明部分;
执行语句部分;
}
说明:
? 如果没有参数,则可以
省略形参表列和形参说明,
但括号不能省略;
规定有序
求解园面积的编程
示例
void main(){
d o u b l e a r e a ( d o u b l e x ) ;
double r,a;
scanf("%lf",&r);
r=pow(r,2.0);
a=area(r);
printf("area=%f \ n",a);
}
double area(double x){
double y;
y=PI*x;
return(y);
}
void main(){
d o u b l e a r e a ( d o u b l e x ) ;
double r,a;
scanf("%lf",&r);
r=pow(r,2.0);
a=area(r);
printf("area=%f \ n",a);
}
double area(double x){
double y;
y=PI*x;
return(y);
}
求解园面积的编程示例
? 如果函数不需要返回
值,则可将该函数 定义为
void 类型函数,并去除
return 语句。
? 分号是语句的结束标志,
是语句必要的组成 部分,
不可少,因此可以 一行写
几个语句。
void main(){
d o u b l e a r e a ( d o u b l e x ) ;
double r,a;
scanf("%lf",&r);
r=pow(r,2.0);
a=area(r);
printf("area=%f \ n",a);
}
double area(double x){
double y;
y=PI*x;
return(y);
}
求解园面积的编程示例
? 函数:函数在程序设
计中,是指有一定 结构形
式构成的,能完成 某种特
定运算功能的程序 模块,
被调用时根据自变 量(形
参)的值,作运算 后,返
回相应的结果(数 据)或
实现某项特定的功能操作。
预处理命令、外部变量定义等
函数类型 main( ){
数据说明部分;
执行语句部分;
}
函数类型 fun_1( 形参表 ){
数据说明部分;
执行语句部分;
}
……
函数类型 fun_n( 形参表 ){
数据说明部分;
执行语句部分;
}
C
程
序
的
一
般
形
式:
1.3 库函数应用简介
C 的两个基本系统函数库及其相配套的说明
性预处理文件。
? 库函数的说明性预处理文件,, stdio.h,,
,math.h, 它们是系统与用户的接口文件,称
,头文件,,其中包含库函数原型的说明、类型
和全局变量及符号常数等的说明。
? 数值计算函数库
sqrt(X) 求平方根函数;
sin(x) 返回以弧度表示的 x 的正弦值;
cos(x) 返回以弧度表示的 x 的余弦值;
pow(x,y) 返回 x
y
的值的幂指数函数
exp(x) 返回 e
x
的指数函数
……
用户程序要调用这些函数,必须在有关函数
前用以下预处理命令把, math.h, 标头文件包
含进来。
1.3 用库函数 组装 C 程序
# include, math.h,
或
# include <math.h >
? 双引号定界表示以当前
目录为起点寻找包含文件,
若不在,再按系统规定的
标准路径找
? 尖括号定界表示按系统
规定的标准路径设置检索
包含文件。
预处理命令包含, math.h, 标头文件 格式如下:
因为 ma th,h 中包含提供了数值计算函数库中
的每一个函数原型的说明。
………
double sqrt( double x );
double sin( double x );
double pow( double x,double y ); ……
函数原型中提供了函数类型、函数名称、形参表中
形参的个数、形参的类型、形参的顺序等信息,它们
将在程序中作为 C 编译程序编译用户程序时检验用户调
用库函数准确性的判断依据。
函数类型 函数名称 形参的个数、类型、顺序等信息
所以,调用库函数时必须注意,函数参
数的个数、类型,顺序及返回值的类型。
对于三角函数还应注意自变量的单位是
弧度。
? 基本 I/O ( 输入 / 输出)库, 用户程序若要
使用其中的函数,必 须用预处理命令将
,stdio.h, 标头文件包含进来。 意义同上!
# includ e, std io.h, 或 # includ e <std io.h>
常用字符输入输出函数:
getchar( )
putchar(C )
gets( 字符数组 )
puts ( 字符串地址 )
? 从标准输入文件 stdin( 键盘 ) 读入一个
字符。
? 把字符串输出到标准输出文件,并加
上换行符。
? 从标准输入文件读入一个字符串到字
符数组中。
? 将字符 c 写到标准输出文件 stdout( 显
示屏 ) 中去。
格式输入输出函数:
sc anf(, 格式字符串,,输入参数表列 ) ;
printf(, 格式字符串,,输出参数表列 ) ;
特例, 最常用的输入输出函数, 因此可省略
stdio.h文件包含
例 [2] 计算一个正弦值。
# include < math.h >
void main(){
doub le x ; //dec lare variable
x =sin(0.19 199);
printf("s in0.19199=% f \ n",x );
}
/*
运行结果:
sin0.19199=0.190813
*/
? ? // ? 注释本行其后的
内容为注释信息;
? ? /* … */ ? 表示两符号
之间为注释信息;
? 注释信息对程序运
行不发生影响,也不被
编译,合理地使用注释
可以提高程序的可阅读
性。
例 [2] 计算一个正弦值。
? C 规定每一个语句以
分号结束,分号是语句
不可缺少的部分,是语
句的结束标志。因此,
一行可以写多个语句,
一个语句也可以分多行
书写。
# include < math.h >
void main(){
doub le x ; //dec lare variable
x =sin(0.19 199);
printf("s in0.19199=% f \ n",x );
}
/*
运行结果:
sin0.19199=0.190813
*/
函数调用时, 必须注意
实参与形参在参数的个
数, 类型, 顺序及单位
上一一对应匹配 !
? C的文件包含和编译过程。
目标模块
可执行程序
库函数其它
目标程序
模块 A
模块 B
模块 A
# incl ude <math.h>
模块 B
math.h
fi le1.c
预编译
编译
链接
运行
执行结果
? 格式输出函数 p r i n tf ( ),
一般形式:
print f(, 输出格式串,,输出参数项表列 ) ;
输出格式串中可以使用三种不同的字符成分,
? 格式符
? 转义字符
? 一般字符
功能,按规定的格式把输出项输出到显示屏上
格式符的基本形式:
% [< 域宽 >]< 格式字符 >
如,%6 d,% 1 0.2f,% 1 6s,…
? 格式符,? % ? 打头
后跟一个字母部分,
组成特定格式以规定
相应输出项的输出形
式。
? 转义字符, ? \ ? 打头后跟一个字母或数字部分,作用
是输出控制代码和特殊字母。如 ? \ n ? 为回车换行控制
代码。
? 一般字符, 除了格式符和转义字符以外的其它字符,
原样输出,以增加运行结果的可读性。
% d 按十进制整数形式输出
% x 按十六进制整数形式输出
% f 按浮点数 ( 实数 ) 形式输出
% c 按单一字符形式输出
% s 按字符串形式输出
# include < math.h >
void main(){
doub le x ; //dec lare variable
x =sin(0.19 199);
printf("s in0.19199=% f \ n",x );
}
/*
运行结果:
sin0.19199=0.190813
*/
三种字符成分可
在输出格式串中不
同位置上配合使用,
以实现不同的显示
效果。
例 [2] 计算一个正弦值。
? 输出参数可以由一个以上的输出项组成
print f(,… %d … %x … %f …”,a,b,c );
? printf() 亦可以没有输出项,利用它可输
出提示信息。如:
print f(, test!, );
要求,输出格式中的格式符与输出项的个数必须相同,
它们按各自的先后顺序一一对应,且符合类型匹配的
要求。
整
型
整
型
实
型
# include < math.h >
void main(){
printf( "s in0.19199=% f \ n",sin( 0.19199) );
}
? C 语言允许函数嵌套调用
函数间的调用关系及其称
main( )
printf( )
sin( )
主调程序
被调程序
主调程序
被调程序
1.4 自定义函数的编写
例 [3] 计算
???????
!7!5!3
)si n (
753
xxx
xx
直到最后一项的绝对值小于 时,停止
计算。 x 键盘输入。
7
10
?
? 讨论,
计算 sin(x) 本来可以利用系统提供的库函数直接
求出。但是库函数是如何计算 sin(x) 的呢?如计算公
式所指出的那样,这是一个级数求和的问题。其项数
决定于最后一项的绝对值是否小于 。如果它大
于,继续求下一项,累加到和上,否则结束求和。
7
10
?
7
10
?
:
求出。但是库函数是如何计算
决定于最后一项的绝对值是否小于
于,继续求下一项,累加到和上,否则结束求和。
???????
!7!5!3
)si n (
753
xxx
xx
设变量为 x, 和为 sum, 每一项为 term, 其类型都说
明为双精度 double 。 另外定义一符号常量 EPS 表示误差,
其值为 。
7
10
?
,, 每一项为,
。 另外定义一符号常量
。
? 算法描述, ( 一级算法 )
1 累加器 sum, term 的初值为 x, n=1;
2 w hile(fab s(term)>EP S){
3 计算下一项 term;
4 将下一项加到 sum 中。
}
5 输出和 sum 。
? 数据描述,
其中第 3步需要继续
求精 。 每一项单独计
算较麻烦, 也浪费机
时, 可以利用前一项
求下一项的办法 ( 称
递推计算方法 ) 计算 。
由计算公式 。可知???????
!7!5!3
)s i n (
753
xxx
xx 。可知??
这对于所有的 n ( n>1 ) 都是成立的。
第 n 项为:
)!12(
)1(
)12(
1
?
?
?
?
n
x
n
n
第
第 n - 1 项为:
)!32(
)1(
)32(
?
?
?
n
x
n
n
第
前一项与后一项之间差一个因子:
)12)(22(
2
??
?
nn
x
? 二级求精,
第 3 步,计算下一项 term
3 - 1, n=n+1;
3 - 2, term= term*( - x * x)/((2*n - 2)*(2*n - 1))
1 累加器 sum, term 的初值为 x, n =1;
2 w hile(fab s(term)>EP S){
3 计算下一项 term;
4 将下一项加到 sum 中。
}
5 输出和 sum 。
? 较完整的算法
3-1 n=n+1;
3-2 term=term*(-x*x)
/((2*n-2)*(2*n-1))
计算 udf_s in(x ) 函数和完整的程序如下,
# include < stdio.h>
#include < math.h >
#define EPS 1e - 7
void main(){
doub le udf_sin( dou ble x ); // 用户自定义函数原型说明
doub le a;
scanf(" % lf",&a );
printf("% f % f \ n",udf_s in(a),sin(a) );
}
doub le udf_sin( dou ble x ){ // 用户自定义函数
doub le sum,term,n=1;
sum =te rm=x ;
w hile( fab s(term) > EP S ){
n=n+1;
term= term*( - x * x )/( (2*n - 2)*(2*n - 1));
sum =sum+ter m;
}
return(sum);
}
运行结果:
input,0.19199
output,0.190813 0.190813
说明:
? C 规定变量、符号常数、函数必须先定义后
使用:
* 给变量定义就是为变量在内存中分配存储
空间,确定其存储形式和规定可 执行的操作
(运算);
* 给函数定义就是确定函数求解问题的功能
和过程,及其数据传递的方式等。
说明:
? 数据传递是程序设计中重要的概念,C 中的
数据传递方法可归纳为:
* 参数传递:传值方式和传地址方式;
* 外部变量(全局变量)传递;
* 由 re tu rn( 表达式 ) 语句将表达式的值返回
到主调函数的调用处。
? 本程序的数据传递形态:
采用传值方式,
可理解为简单的将实
参 a 的值复制给形参 x
udf_s in() 0.19199 0.19199 0.19199 1
2000 2004 2008 2012
x sum term n
main() 0.19199
3000
参
a
doub le udf_sin(dou ble x){
doub le sum,term,n=1; sum=ter m=x ; …… }
void main(){
doub le a; … printf(, % f % f \ n",udf_s in( a ),sin( a ));}
? scanf( ) 格式函数的形式与使用,格式为:
scanf(, 输入格式串,,输入项地址表列);
* 输入格式串的组成同 printf(), 一般只使用格式符;
* C 规定输入项必须由地址构成,项与项之间逗号分隔 ;
* ? & ? 为地址运算符或称取地址符; & a 表示取 a 变量的
地址,为地址表达式,运算结果为 3000 。
,
为地址运算符或称取地址符;
。
0.19199
3000 a
……
……
scanf() ; 语句的含义为,按指定的
格式,将由键盘输入的数据存放到相应
地址的存储单元之中去。
scanf( "%lf",&a );
? 输入格式符的 常 用 方式 与注意事项:
1,三种形式说明,设有 float a,b,c;
? scanf(, %f%f%f,,&a,&b,&c );
紧凑无其他字符,按系统规定需 用一个或多个空格
分隔输入数据项,亦可用回车键分隔。
输入形式,3.5 4.6 7.9 ↙ 或
分行输入,3.5 ↙
4.6 ↙
7.9 ↙
? scanf(, %f,%f,%f,,&a,&b,&c );
逗号作为一般字符,原样输入,且可作为数据项之
间的分隔符使用;
输入形式,3.5,4.6,7.9 ↙
? scanf(, %f%f%f \ n,,&a,&b,&c );
输入形式,3.5 4.6 7.9 \ n ↙
注意,不恰当得使用 ? \ n ? 符,多余。 scanf() 格式串
除, %, 带头的格式符外,其余字符都要求原样输入,
因为其操作的对象为键盘。
? 输入 scanf() 函数的格式符必须与输入参 数
项的类型一一对应,否则将引起计算 结果的错
误。 可参照下表,
shotchar
字符
数组
dou blefl oatLon g intint
参
数
类
型
% h% c% s
% l f
% l e
% f % e% ld
% d
% o
%x
格
式
符
参
数
类
型
格
式
符
1.5 C 程序的组成方式:
C 程序组成方式一
一个 C 程序由一个源文件组成,运行前只需一次
编译,即可生成可执行程序。
C 程序
……
函数 1 函数 n标头文件
C 程序
file.c
一个 C 程序由若干源文件组成,运行前必须分别编译,
并经链接组装后方可运行。 main() 函数只能一个。
C 程序
……
源程序文件 2 源程序文件 n源程序文件 1
函数 2 函数 n函数 1
……
……
……
file1.c file2.c filen.c
C 程序组成方式二
1.6 程序的现代方式与传统方式
#incl ude <math.h> // 现代方式编程示例
#define EP S 1e - 7
void mai n(){
dou ble udf_si n(dou ble x ); // 现代方式的函数原型说明
dou ble a; scanf(" % lf ",&a); printf(" % f % f \ n",udf_sin (a),si n(a));
}
dou ble udf_si n(dou ble x ){ // 现代方式的函数定义与形参说明形式
dou ble s um,term,n=1; sum=t erm=x ;
w hil e(fabs(t e rm)>EPS){
n=n+1; term=term *( - x * x)/( (2*n - 2)*(2*n - 1)); s um=sum+ term;
}
return(sum);
}
#incl ude <math.h> // 传统方式 编程示例
#define EP S 1e - 7
void mai n()
{ dou ble a,udf_si n(); // 传统方式的函数原型说明
scanf(" % lf ",&a); pri ntf("% f % f \ n",udf _si n(a),si n(a));
}
dou ble udf_si n( x ) // 传统方式的函数定义与形参说明形式
dou ble x ;
{ doub le s um,term,n=1; sum=t erm=x ;
w hil e(fabs(t e rm)>EPS)
{ n=n+1; term=t erm*( - x * x)/( (2*n - 2)*(2*n - 1)); s um=sum+ term; }
return(sum);
}
# include <stdio.h>
#include <math.h>
#define EPS 1e - 7
void main(){
double udf_sin(double x); // 用户自定义函数原型说明
double a; scanf("%lf",&a);
printf("%f %f \ n",udf_sin(a),sin(a));
}
double udf_sin( double x ){ // 用户自定义函数
double sum,term,n=1; sum=term=x;
while( fabs(term) > EPS ){
n=n+1;
term=term*( - x*x)/((2*n - 2)*(2*n - 1));Th e end
培 育 英 才 钻 研 科 学
书山有径勤为路
学海无边苦作舟
书山有径勤为路书山有径勤为路
学海无边苦作舟学海无边苦作舟