1
#include <stdio.h>
#define PI 3.14
float l(float); /*函数 声明 */
float s(float); /*函数 声明 */
float l(float r) /*函数 定义,求周长 */
{ return PI*r*2; }
float s(float r) /*函数 定义,求面积 */
{ return PI*r*r; }
void main()
{ float r,cir,area;
printf("please input r:");
scanf("%f",&r);
cir =l(r); /*函数 调用 */
area =s(r); /*函数 调用 */
printf("circumference=%7.2f\n,area=%7.2f\n",cir,area);
}
作业及问题习惯用符号常量,并注意语法格式
函数声明后有分号
一般都写在前面
return只能返回一个值
暂时还不能用一个函数求两个值。
printf("circumference=%7.2f\n,area=%7.2f\n",l(r),s(r));
/*第二种调用方式,l(r),s(r) 作为 printf()的参数 */
第 4讲多函数程序设计-变量的作用域选择结构程序设计
3
#include <stdio.h>
#define PI 3.14
float l(float); /*函数声明 */
float s(float); /*函数声明 */
float l(float r) /*函数定义:求周长 */
{return PI*r*2; }
float s(float r) /*函数定义:求面积 */
{ return PI*r*r; }
void main()
{ float r,l,s;
printf("please input r:");
scanf("%f",&r);
l=l(r); /*函数调用 */
s=s(r); /*函数调用 */
printf("circumference=%7.2f\n,area=%7.2f\n",l,s);
}
问题若这样起名会怎样?
会有错误提示,
因为相同的名字造成了冲突。
4
#include <stdio.h>
#define PI 3.14
float l(float); /*函数声明 */
float s(float); /*函数声明 */
float l(float r) /*函数定义:求周长 */
{return PI*r*2; }
float s(float r) /*函数定义:求面积 */
{ return PI*r*r; }
void main()
{ float r,cir,area;
printf("please input r:");
scanf("%f",&r);
cir =l(r); /*函数调用 */
area =s(r); /*函数调用 */
printf("circumference=%7.2f\n,area=%7.2f\n",cir,area);
}
问题若这样起名又会怎样?会冲突吗?
不会,它们虽然是不同的 r,但因为它们的 作用域 不同,所以不会产生冲突。
5
涉及的语法
-作用域
作用域:即作用范围
可分为:
局部变量
全局变量
6
局部变量
局部变量
在语句块内 (即 { }内 )定义的变量
形式参数也是局部变量
特点
定义时不会自动初始化,除非程序员指定初值
进入语句块时获得内存,仅能由语句块内语句访问,退出语句块时释放内存,不再有效
并列语句块各自定义的同名变量互不干扰
7
main()
{ int i=1,j=2;
printf(″i=%d,j=%d\n″,i,j);
{int i=3,a=4; printf(″i=%d,a=%d\n″,i,a);
j++;
}
{int i=5; printf(″i=%d\n″,i);
j++;
}
printf(″i=%d,j=%d\n″,i,j);
}
运行结果为:
i=1,j=2
i=3,a=4
i=5
i=1,j=4
例,运行结果? ++是一个 运算符,j++表示将 j变量的值加 1
8
例 3-7,运行结果?
#include <stdio.h>
void swap(int x,int y); /* 函数声明 */
void main( )
{ int a=3,b=5;
printf("11>a=%d,b=%d\n",a,b);/* 调用交换函数之前 */
swap(a,b); /* 调用交换函数 swap */
printf("12>a=%d,b=%d\n",a,b);/* 调用交换函数之后 */
}
/* 函数定义:交换两个变量的值的函数 */
void swap(int a,int b)
{ int temp;
printf("21> a=%d,b=%d\n",a,b); /* 交换变量值之前 */
temp=a; a=b; b=temp; /* 交换器:交换变量 x,y的值 */
printf("22> a=%d,b=%d\n",a,b); /* 交换变量值之后 */
}
3 5
a b
3 5
a b
temp 3
5 3
实参 a,b的值 没发生变化 !
单向值传递 !
即由实参向形参的方向传递数值 !而不会朝相反的方向 !
9
全局变量
全局变量
在所有函数之外定义的变量
特点
默认 作用范围:在源程序,c中,从定义它的位置以后都有效
在定义点之前或在其他,c文件中引用,应该进行如下声明:
extern 类型名 变量名 ;
从程序运行起即占据内存,程序运行过程中可随时访问,程序退出时释放内存
使函数之间的数据交换更容易,也更高效
但是尽量少用,因为谁都可以改写全局变量,所以很难确定是谁改写了它
破坏了函数的独立性 (封装性 )
10
#include <stdio.h>
int global; /*定义全局变量 */
void GlobalPlusPlus(void);
main()
{
global = 1;
printf("Before GlobalPlusPlus(),it is %d\n",global);
GlobalPlusPlus();
printf("After GlobalPlusPlus(),it is %d\n",global);
}
/* 函数功能,对 全局变量 global加 1,并打印加 1之前与之后的值函数入口参数,无函数返回值,无
*/
void GlobalPlusPlus(void)
{
printf("Before ++,it is %d\n",global);
global++;
printf("After ++,it is %d\n",global);
}
例Before GlobalPlusPlus(),it is 1
Before ++,it is 1
After ++,it is 2
After GlobalPlusPlus(),it is 2
注意:全局变量具有,记忆性,。
11
#include <stdio.h>
void GlobalPlusPlus(void);
main()
{
int global = 1;
printf("Before GlobalPlusPlus(),it is %d\n",global);
GlobalPlusPlus();
printf("After GlobalPlusPlus(),it is %d\n",global);
}
/* 函数功能,对 局部变量 global加 1,并打印加 1之前与之后的值函数入口参数,无函数返回值,无
*/
void GlobalPlusPlus(void)
{
int global = 1;
printf("Before ++,it is %d\n",global);
global++;
printf("After ++,it is %d\n",global);
}
例Before GlobalPlusPlus(),it is 1Before ++,it is 1
After ++,it is 2
After GlobalPlusPlus(),it is 1
12
如何用全局变量解决例 3-7
#include <stdio.h>
int a=3,b=5;
void swap(void); /* 函数声明 */
void main( )
{ printf("11> a=%d,b=%d\n",a,b);/* 调用交换函数之前 */
swap(); /* 调用交换函数 swap */
printf("12> a=%d,b=%d\n",a,b);/* 调用交换函数之后 */
}
void swap(void ) /* 函数定义,没有参数 */
{ int temp;
printf("21> a=%d,b=%d\n",a,b); /* 交换变量值之前 */
temp=a; a=b; b=temp; /* 交换变量 a,b的值 */
printf("22> a=%d,b=%d\n",a,b); /* 交换变量值之后 */
}
虽然得以解决,但并不是一个好办法 !
为什么?
因为它破坏了函数的封闭性 !
学指针的时候我们会学另外一种方法 !
即便要用全局变量,一般也是在只读不写的时候才用 !
13
例:使用全局变量解决
#include <stdio.h>
#define PI 3.14
float r;
float l( void ); /*函数声明 */
float s(void); /*函数声明 */
float l(void) /*函数定义:求周长 */
{return PI*r*2; }
float s(void) /*函数定义:求面积 */
{ return PI*r*r; }
void main()
{ float cir,area;
printf("please input r:");
scanf("%f",&r);
cir =l( ); /*函数调用 */
area =s( ); /*函数调用 */
printf("circumference=%7.2f\n,area=%7.2f\n",cir,area);
}
r一旦被赋值,其值不再发生变化,只是拿来用。
14
小结:
分清楚同名变量的作用域。一般情况下用局部变量,极少情况下考虑到数据的一致性时可以用全局变量。
变量的存储类型待第 5章以后再讲。
15
编写函数,求两个整数的最小值、最大值
分析结果(算法)
主函数:
输入 a,b
计算最小值和最大值 (通过函数调用实现 )
输出最小值和最大值
求最大值函数
求最小值函数新的问题:例 3-2:
#include<stdio.h>
int min(int,int);/*函数声明 */
int max(int,int);
int min(int a,int b)/*函数功能:求 a,b的最小值 */
{
int temp;
if(a>b)
temp=b;
else
temp=a;
return temp;
}
int max(int a,int b) /*函数功能:求 a,b的最大值 */
{
int temp;
if(a>b)
temp=b;
else
temp=a;
return temp;
}
void main()
{ int a,b;
printf(" please input two integers,");
scanf("%d%d",&a,&b);
printf(" min=%d\nmax=%d\n",min(a,b),max(a,b));
}
运行过程?
16
例 3-2:编写函数,求两个整数的最小值、最大值另一种写法:
#include<stdio.h>
int min(int,int);/*函数声明 */
int max(int,int);
int min(int a,int b) /*函数功能:求 a,b的最小值 */
{
return (a>b)?b:a;
}
int max(int a,int b) /*函数功能:求 a,b的最大值 */
{
return (a>b)?a:b;
}
void main()
{ int a,b;
printf(" please input two integers,");
scanf("%d%d",&a,&b);
printf(" min=%d\nmax=%d\n",min(a,b),max(a,b));
}
条件运算符__?__:__
C语言中唯一的 三目运算符
含义,若?前边的表达式成立,
则结果为:前边的表达式或数据,
若不成立,结果为:后边的表达式或数据。
简单的 if-else语句可以用条件运算符来替代。
结合性:自右向左
计算,y=x>0?1:(x<0?-1:0)
函数定义的另一种写法请参考书中 48页的解法一
17
例 4- 9
从键盘上输入一个年份,然后判断这个年份是否为闰年。
分析结果(算法)
输入 year
判断 year是否为闰年
输出 yes或 no 如果 year能被 4整除且不能被 100整除,或者 year能被 400整除,
year是闰年,
否则
year不是闰年。
18
分析
year能被 4整除 且 不能被 100整除,或者 year
能被 400整除
(?)或者 (?)
(?且?)或者 (?)
(?&&?)||(?)
(year%4==0&&year%100!=0)||(year%400
==0)
如果 year能被 4整除且不能被 100整除,或者 year能被 400整除,
year是闰年,
否则
year不是闰年。
%求模(余)运算符,优先级与结合性同 /(除法运算符 )
结果的符号与被除数的符号相同
例,printf("10%3=%d,-10%3=%d,10%-
3=%d,-10%-3=%d\n",10%3,-10%3,10%-3,-
10%-3);
结果为,10%3=1,-10%3=-1,10%-3=1,-10%-3=-1
if year%4==0&&year%100!=0)||(year%400==0)
{
printf(“%d is a leap year!”,year);
}
else
{
printf(“%d is not a leap year!”,year);
}
19
结果
#include <stdio.h>
void main()
{ int year;
printf(“please input year:”);
scanf(“%d”,&year);
if((year%4==0&&year%100!=0)||(year%400==0))
{
printf(“%d is a leap year!”,year);/*一般要缩进 */
}
else
{
printf(“%d is not a leap year!”,year); /*缩进与上边一致 */
}
}
20
写成多函数程序
#include <stdio.h>
void leap(int year);/*函数声明 */
void leap(int year)/*判断 year是否为闰年并输出 */
{
if((year%4==0&&year%100!=0)||(year%400==0))
printf(“%d is a leap year!”,year);
else
printf(“%d is not a leap year!”,year);
}
void main()
{ int year;
printf(“please input year:”);
scanf(“%d”,&year);
leap(year); /*调用 leap函数判断 year是否为闰年并输出 */
}
21
涉及的语法
选择结构 语句格式
if(条件表达式 )
{
… …
}
else
{
… …
}
else分支可以省略,此时为单分支结构
22
涉及的语法
- 关系运算符
> < >= <= == !=
大于,小于,大于等于,小于等于,等于,
不等于
运算结果只有两个值,0和 非 0,0表示假,
即该关系不成立;非 0,表示真,即该关系成立
例如,2006%4==0的结果是?
0,表示假(关系不成立)
优先级:在算术运算符和赋值运算符之间。
结合性:自左向右
23
涉及的语法
- 逻辑运算符
逻辑运算也被称为布尔( Boolean)运算,即参与运算的 数据 和运算 结果 都只有两个值,0和 非 0,
0表示假 (条件不成立 );非 0表示真 (条件成立 )
与运算 &&(相当于而且 )
a && b当且仅当两者都为真,则结果为真
( a > b && b > c); a大于 b,并且 b大于 c
或运算 || (相当于或者 )
a || b只要两者中有一个为真,结果就为真
( a > b || b > c); a大于 b,或者 b大于 c
求反 !
单目运算符
( !a );如果 a是 0,结果非 0;如果 a是非 0,结果是 0
并不改变 a的值
24
是字母吗?
输出,是,
NO YES
输入 letter
输出,不是,
结束开始练习:从键盘上输入一个字母,判断它是不是英文字母
#include <stdio.h>
void main()
{ char c;
printf(“please input a character:”);
c=getchar();/*从键盘上输入一个字符并存储到变量 C中 */
if( (c>=?a?&&c<=?z?)||(c>=?A?&&c<=?Z?) )
{
printf(“%d is a letter!”,c);
}
else
{
printf(“%d is not a letter!”,c);
}
}
(letter>=97&&letter< 122)||(letter>=65&&letter<=90)
25
另外两个库函数:
字符输入 /输出函数
#include <stdio.h>
void main()
{
char lower,upper;
printf(“please input an lowercase:”);
lower=getchar(); /*从键盘上输入一个字符,
并赋值给 lower */
upper=lower-32;
putchar(upper); /*将 upper输出 */
}
一般用法:字符型变量 =getchar( );
含义是从键盘上敲入一个字符,然后把它赋给字符型变量。
另一种用法,getchar();功能相当于
,按任意健继续,,一般用于程序最后,
以便查看前边的结果。
格式,putchar( 字符 );
功能,向终端输出一个字符。
参数可以是字符型常 (变 )量或整型常
(变 )量。例如,putchar(c );
putchar(‘a’); putchar( ‘\n’ );
putchar(97);
26
本讲小结
要求
理解函数的 单向值传递
理解变量的 作用域 的概念
能够根据需要设置局部变量或全局变量
选择结构的程序设计
关系运算符 和 逻辑运算符 的相关语法
字符输入输出函数的使用
27
作业
请大家回去复习大学计算机基础关于 程序、算法、结构化程序设计思想 的内容。
P125写出习题 4.1中程序的功能。
编程实现:从键盘上输入一个整数,判断它的奇偶性和正负性。