第 9讲变量的存储类型带参数的宏定义数组
请大家 及时消化 我课上讲的内容,并举一反三,模仿未讲过的例题多写程序。
如果说学习 C语言有捷径的话:那就是 多读程序,多写程序
2
作业答案- 1
5.6
double S(float x,int n)
{if(n==1L)
return x;
else
return S(x,n-1)+x*x;
}
1、将 #include<conio.h>改为 windows.h;将 clrscr();改为
system(“CLS”);clrscr()是 TC中的清屏函数,VC中没有,但 VC中一般不需要。
2,1L相当于 (long)1
3
习题 5.12
问题的关键是如何 将 n的问题化解为 n-1
的问题 (即 反方向求解问题 )。
根据分析,写出如下的数学函数:

1!),()1,(
1
),(
nnxpo wnxs
nx
nxs
double S(float x,int n)
{if(n==1)
return x;
else
return S(x,n-1)+pow(x,n);
}/*若函数定义为 float,会有类型不一致的警告 */
4
#include<stdio.h>
#include<math.h>
double S(float x,int n);
void main()
{ double x,s; int n;
printf(“please input x,n:\n”);
scanf(“%lf,%d”,&x,&n);
s=S(x,n);
printf(“\nS(%lf,%d)=%lf\n”,x,n,s);
}
double S(double x,int n)
{if(n==1)
return x;
else
return S(x,n-1)+pow(x,n);
/*递归要通过函数的依次调用实现 */
}
习题 5.12程序
#include<stdio.h>
#include<math.h>
double S(float x,int n);
void main()
{ double x,s; int n;
printf(“please input x,n:\n”);
scanf(“%lf,%d”,&x,&n);
s=S(x,n);
printf(“\nS(%lf,%d)=%lf\n”,x,n,s);
}
double S(double x,int n)/*用递推求解 */
{double sum=0;
int i;
for(i=1;i<=n;i++)/*递推要用循环语句实现 */
sum+=pow(x,i);
return sum;
}
切忌,
将递归函数的内容写至主函数中;
将递归中的语句放至循环中;
在递归函数中写 s(x,n)=S(x,n-1)+pow(x,n);
5
另一个具有,记忆性,的变量类型,静态变量( static)
一般的内部变量
在函数退出后失效,再次进入函数,变量值重新初始化
静态变量
在变量类型前面用 static修饰
static int i;
变量存在 静态存储区,当函数结束时,内存空间不被释放,因此,变量的值可以保存到下次进入函数,即变量具有记忆功能
6
涉及的语法
-变量的 存储类型
编译器为变量分配内存的方式
它决定变量的生存期程序存储区静态 存储区动态 存储区 形参、自动变量、函数调用的现场等全局变量、
静态变量
动态存储
根据需要临时分配存储空间,离开即释放
静态存储
在程序运行期间分配固定的存储空间不释放内存分配
7
例 -静态变量
#include <stdio.h>
void Func(void);
main()
{ int i;
for (i=0; i<10; i++)
{ Func();
}
}
/* 函数功能,打印被调用的次数函数入口参数,无函数返回值,无
*/
void Func(void)
{ static int times = 1; /*静态局部变量 函数结束时 times变量仍然占据静态存储区的存储空间,不释放 */
printf("Func() was called %d time(s).\n",times++);
}
Func() was called 1 time(s).
Func() was called 2 time(s).
Func() was called 3 time(s).
Func() was called 4 time(s).
Func() was called 5 time(s).
Func() was called 6 time(s).
Func() was called 7 time(s).
Func() was called 8 time(s).
Func() was called 9 time(s).
Func() was called 10 time(s).
1times 2310
8
例 -非静态变量
#include <stdio.h>
void Func(void);
main()
{ int i;
for (i=0; i<10; i++)
{ Func();
}
}
/* 函数功能,打印被调用的次数函数入口参数,无函数返回值,无
*/
void Func(void)
{ int times = 1;
printf("Func() was called %d time(s).\n",times++);
}
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
Func() was called 1 time(s).
1times 2 1times 2
9
根据存储类型可分为
自动变量 (auto)
静态变量 (static)
寄存器变量 (register)
10
自动变量 ( auto )
我们以前定义的那些变量,都默认是这种类型
,自动,体现在
进入语句块时自动申请内存,退出时自动释放内存
标准定义格式
auto 类型名 变量名 ;
特点:
动态局部变量
缺省的存储类型
不初始化时,值是不确定的
11
寄存器变量( register)
寄存器
CPU的内部容量很有限、但速度极快的存储器
使用频率比较高的变量声明为 register,
可以使程序更小,执行速度更快
register 类型名 变量名 ;
register int i;
现代编译器有能力自动把普通变量优化为寄存器变量,并且可以忽略用户的指定,所以一般无需特别声明变量为 register
12
静态变量和全局变量
相同点:都是静态存储类型
自动初始化为 0
都存储在静态存储区,整个程序运行期间一直占据内存
不同点:作用域不同
全局变量在所有的源程序文件中都可用
静态变量又分为静态局部变量和静态全局变量,作用域分别是所在函数和所在源文件
13
#include<stdio.h>
int square(int i);
void main()
{int i=0;
i=square(i);
for(;i<3;i++)
{static int i=1;
i+=square(i);
printf(“%d,”,i);
}
printf(“%d\n”,i);
}
int square(int i)
{return i*i;}
习题 5.1
0i
1i 2
1
6
2
42
3
输出结果:
2,6,342,
14
带参数的宏定义
#define SQUARE(n) ((n)*(n))
main()
{ int i=1;
for( ;i<=10;i++)
printf("%4d",SQUARE(i) );
}
main()
{ int i=1;
for( ;i<=10;i++)
printf("%4d",((i)*(i)) );
}
替换为:
15
区别使用函数 使用带参数的宏定义
int SQUARE(int n);
{
return(n*n);
}
#define SQUARE(n) ((n)*(n))
main()
{
int i=1;
for( ;i<=10;i++)
printf("%4d",SQUARE(i));
}
main()
{
int i=1;
for( ;i<=10;i++)
printf("%4d",SQUARE(i) );
}
((i)*(i))
当函数功能非常简单时,可以用带参数的宏定义来实现。
16
涉及语法
-带参数的宏定义
一般格式:
#define 宏名 (参数表 ) 字符序列
功能,将程序中出现的前者置换为后者。
其中宏名后面的括号里是参数,类似函数中形参表,只是此处的形参无类型说明。字符序列中应包含括号中所指定的参数,否则参数设置无意义。
17
应注意的问题
使用带参数的宏定义可以实现某些简单函数的功能(注意是某些,而不是全部)。
定义时,宏名和参数表之间不能有空格。
对带参数的宏定义,字符序列及其字符序列中各个形参都应该用圆括号括起来。
例,#define SQUARE(n) ((n)*(n))
#define s (a,b,c) a*b*c
main()
{
printf(“%d”,s( 3+5,5/2,2+3));
}
3+5*5/2*2+3#define f(x,y) (x)+(y)
main()
{int a=4,b=3;
printf("%d",f(a,b)*f(a,b) );
}
)+(b)*(a)+(b)
(a)*(b)*(c)
((a)+(b))
18
函数相关内容总结
为什么定义函数?
模块化程序设计方法
函数的定义、调用、声明
参数传递
变量的作用域和存储类型
函数的嵌套定义和递归定义
19
新的问题:
例:输入全班 60个学生的 C语言成绩并统计不及格的人数。
分析:
输入 60个成绩
统计人数
输出统计结果
1.如何定义变量?
2.在数学中怎样解决这个问题?
score1,score2,……,
scorei,……,score60
20
1定义变量用于存储成绩
int score[60];
数组名
(这一组数的共同名字 )
数组 长度
含义:向系统申请 60*sizeof(int)个字节的连续空间,用于存储 60个成绩,它们共同的名字 score。将来数组中的每一个元素就分别是 score[0],score[1]、
score[2],……,score[59],此时,方括号里的数字不再表示长度,而是 下标 。
它们的名字 score表示这一串内存的起始地址。
21
……
内存地址:
1001
1002
1003
1004
1119
1120
数组的内存分配
scorescore[0]
score[1]
score[59]
score[2]
score[3]
……
注意下标从 0开始
22
涉及的语法
-数组 定义及相关概念
数组:一组具有类型相同、顺序存放的数据
什么时候定义数组?
定义格式:
数据类型 数组名 [数组长度 ];
注:数组长度必须是常量。
例,int score[60];
含义:
23
2、输入 60个成绩
循环 60次输入
for (i=0;i<60;i++)
scanf("%d",&score[i]);
使用数组的每一个元素也称 数组元素的引用 。
24
3、统计人数
从第一个学生起,判断每一个学生的成绩是否小于 60,是的话计数器加 1
for (i=0;i<60;i++)
if(score[I]<60)
counter++;
4、输出:
25
完整程序
#define N 60
main()
{int score[N];
int i,counter=0;
for (i=0;i<N;i++) /*输入 */
scanf("%d",&score[i]);
for (i=0;i<N;i++) /*统计 */
if(score[i]<60)
{ counter++;}
printf(“The number of unpassed students:%d”,counter);
}
有什么好处?
26
P162例 6- 3
求 Fibonacci数列前 40项
算法:
定义数组
求每一项
输出每一项
fib(n)= 1 ( n= 0,1)fib(n-2)+ fib(n-1) ( n>1)
int fib[40]={1,1};
/*为数组的第一、二个元素进行 初始化,
其它自动为 0*/
for(i=2;i<40;i++)
fib[i]=fib[i-2]+fib[i-1];
/*循环求剩余的 38项 */
for(i=0;i<40;i++)
{ if(i%4==0)/*每输出四个数,输出一个回车 */
printf("\n");
printf("%12d",fib[i]);
}
27
P162例 6- 3:完整程序
#include <stdio.h>
void main()
{ int i,fib[40]={1,1};
for(i=2;i<40;i++)
fib [i]=fib [i-2]+fib [i-1];
for(i=0;i<40;i++)
{ if(i%4==0)
printf("\n");
printf("%12d",fib [i]);
}
}
28
本讲小结
变量的存储类型
带参数的宏定义
数组和数组元素的概念
数组的定义、初始化、数组元素的引用
与数组相关的程序设计
下节课继续讲数组,请 一定提前预习例题 6- 1
作业下节课一起留。
29
作业
编程求学生成绩的最大值
编程求学生成绩的平均值