从零开始学编程---第一步-C语言(二十)
现在说说函数嵌套
除了主函数,每个函数都是平等独立的
并不是只有主函数才可以调用其他函数,其他函数可以互相调用
例如A函数可以调用B函数,B函数可以调用A函数
甚至函数还可以调用自己
最要记住的一点,主函数不能被调用
看下面的程序
#include <stdio.h>
main()
{
int s(int [],int);
int avg(int[] ,int);
int i[5];
puts("请输入5个数字");
for(int x=0;x<5;x++)
scanf("%d",&i[x]);
printf("5个数的和为:%d,平均数为:%d\n",s(i,5),avg(i,5));
}
int s(int i[],int n) //求和
{
int s=0;
for(int x=0;x<n;x++)
s=s+i[x];
return s;
}
int avg(int i[],int n) //求平均数
{
int avg;
avg=s(i,n)/n; //s函数被调用
return avg;
}
定义了两个函数,一个是计算总和,一个是计算平均数
我们知道,计算平均数要先得到总和,所以avg函数没必要在写个求和的算法,直接调用s函数就可以了
s(i,5)中的i其实就是i[0], 数组的第一个元素,把这个元素的地址传递过去
知道第一个数组元素地址即可以得到所有数组元素,指针将了解
另外,函数名内定义的普通变量可以与函数名相同,但是不能和函数形参相同,形参其实就是函数一开始定义的变量(但不占内存,数据传递过来猜才开始占用),只不过放在括号里作为接收数据的作用
主调函数(并非一定是主函数)的实参可以与被调函数形参名字相同
函数的相互调用:
#include <stdio.h>
void a()
{
void b();
puts("aaaa");
b();
}
void b()
{
puts("bbbb");
a();
}
main()
{
a();
b();
}
这个程序可以很好理解两者互相调用,但是这个程序是崩溃的
主函数调用a函数
a函数打印 然后调用b函数
b函数打印,然后调用a函数
a函数打印 然后调用b函数
b函数打印,然后调用a函数
。。。。。。。
会一直重复下去,但不会像死循环那样不停止,为什么会停止那就是以后说的堆和栈的问题了
上面程序的主函数到停止都没有调用过b函数
加上条件就能让它们顺利互相调用了
#include <stdio.h>
void a(int i)
{
void b(int);
puts("aaaa");
if(i<0)
b(i);
}
void b(int i)
{
if(i>0)
a(i);
puts("bbbb");
}
main()
{
int i;
puts("输入一个数");
scanf("%d",&i);
a(i);
b(i);
}
函数可以调用其自身
#include <stdio.h>
void a()
{
puts("aaaa");
a();
}
main()
{
a();
}
这个程序主函数调用a函数
a函数打印,然后自己又调用a函数,等于自己调用自己
调用自己等于重新执行自己函数内的代码
又是打印,又是调用自己,无休止的这样进行下去(不过还是会停)
这种函数就叫做递归函数,递归也是一种算法,待会介绍
下面程序加上条件能阻止它自身调用,不过意义不是很大,呵呵
#include <stdio.h>
void a(int i)
{
puts("aaaa");
if(i<0)
{
puts("崩溃拉");
a(i);
}
}
main()
{
int i;
puts("输入一个数");
scanf("%d",&i);
a(i);
}
现在我们说递归,递归是一种算法,是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象,有时候用递归会比其他方法要高效很多
这里只介绍一个普通的递归程序,让大家理解递归究竟是怎样的
做一道题,输入一个整数(两位以上),实现数字颠倒
例如输入1234,要打印出来4321
这个要有点数学逻辑
1234,我们要首先得到它的末尾数,也就是个数,然后是十位数,百位数依次得到
怎么得到它的个数?用%除以10就可以获得
任何一个2位以上的数除以10,它的余数就是它的个位数
个位数除以10,它的余数就是本身
1234%10 得到它的余数为4
那么再怎么得到3,2,1呢?
这样就可以了
123%10=3
12%10=2
1%10=1
你可能有疑问,怎么让数字变为这样?
1234
123
12
1
很简单,每次除以10就可以了 用/
1234/10=123.4 由于定义的是int型 不会有小数,所以保存的只会是123
然后123/10=12
12/10=1
这样能把一个整数的每一个位数全部得到
怎么把它们整合起来变为1个数
这就需要一个变量每次乘以10再加上得到的单数
a为1234 b初始为0
b=b*10--------b=0
b=b+a%10------b=0+4 b=4
a=a/10-------a=123
然后循环进入下一轮
b=b*10--------b=40
b=b+a%10------b=40+3 b=43
a=a/10-------a=12
。。。。。。
接着就很明了了吧
4*10=40
40+3=43
43*10=430
430+2=432
432*10=4320
4320+1=4321
我们先用普通方法做这道题
程序如下:
#include <stdio.h>
main()
{
int a,b=0;
puts("输入一个数");
scanf("%d",&a);
while(a)
{
b*=10;
b+=a%10;
a/=10;
}
printf("%d\n",b);
}
这里用了while循环
while(a) 只要变量a不为0它就会一直循环下去
因为while括号里变量不为0为真,为0就是假
不清楚的可以把while(a) 改为while(a!=0)
这个程序怎么退出循环的?
当a最后为单数的时候,它除以10也就是零点几了,由于是int类型,a自然也就为0了
下面我们用递归函数做
程序如下
#include <stdio.h>
int dao(int a,int b)
{
if(a==0)
return b;
else
return dao(a/10,b*10+a%10);
}
main()
{
int a, b=0;
puts("输入一个数");
scanf("%d",&a);
printf("%d\n",dao(a,b));
}
假设输入一个数1234,传递给dao函数
dao函数给下面的代码执行
首先判断a为不为0
不为0的话返回 调用dao(a/10,b*10+a%10)后的值
也就是调用dao(123,4)产生的结果
结果产生了吗?没有
123,4又传递给dao函数(自己本身)
然后又是判断,a不为0
返回 dao(12,43)的结果。。
。。。。。。
直到dao(0,4321)
0,4321传递给dao函数
判断a为0 返回b
dao()函数的值为b,递归结束
如果弄糊涂了,可以加个变量c
int dao(int a,int b)
{
int c;
if(a==0)
return b;
else
c=dao(a/10,b*10+a%10);
return c;
}
这个递归可能一时很难弄清楚,这是个逐渐认识的过程,不过初学的话,递归也不是用很多,不用也可以,这个不用担心,理解就好
函数内容暂告一段落,以后还会接触,讲了怎么多,其实我们还有很多没学呢,例如二维数组,全局变量等
那些等我们需要用的时候再学吧,现在来学一个最最重要的内容--------指针
学习指针是学习C语言中最重要的一环,不会指针可以说你没学好C语言,能否正确理解和使用指针是我们是否掌握C语言的一个标志,首先提个醒,指针是C语言最难的部分,想彻底学好C语言,就必须经过指针这一关
指针是C语言中广泛使用的一种数据类型。运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。
在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占4个单元(有的是2个),字符量占1个单元等
为了正确地访问这些内存单元,必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。 既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。 内存单元的指针和内存单元的内容是两个不同的概念。 可以用一个通俗的例子来说明它们之间的关系。我们到银行去存取款时, 银行工作人员将根据我们的帐号去找我们的存款单, 找到之后在存单上写入存款、取款的金额。在这里,帐号就是存单的指针, 存款数是存单的内容。对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
内存地址都是唯一的,没有两个相同的地址
当我们定义变量时,C语言会在内存中寻找未使用的位置并把名字与这个内存位置相关联,也就是说,假设你定义变量name,而这个变量的内存地址是12233(假设而已),你就只需要记住变量名name,而不用管它的内存地址是多少
最新内容
热点内容
- QQ群
-
微信
- 返回首页
- 返回顶部