在c语⾔中函数的作⽤是什么,C语⾔程序中函数的定义
C语⾔程序中函数的定义
C语⾔的函数问题是困扰很多学者的问题的,c程序中什么是函数呢?下⾯啦⼩编为⼤家精⼼推荐的c程序中函数的定义,希望能够对您有所帮助。
C语⾔读书笔记--函数
先来看看函数的⼀般形式,尝试写⼀个加法的函数:
思路是这样的:⾸先得有头⽂件,头⽂件之后就得写主函数,主函数的内部应该就是加法的过程,我们将所有加法的语句都拿出来组成⼀个函数。代码如下:
#include
int add(int a, int b);
int main()
{
int result = add(3,5);
printf("sum is %d
", result);
return 0;
}
int add(int a, int b)
{
int sum;
sum = a+b;
return sum;
}
这是⼀个最简单的函数,描述了⼀个加法函数的定义和调⽤的过程。
int add(int a, int b) 成为函数的⾸部。
有了⾸部之后,就得考虑⼀件事情,将⾸部复制之后,加上⼀个分号,粘贴在主函数之前,作为函数的原型声明。试想,我们在主函数⾥边是不是要先定义变量result才能使⽤result?那么函数的道理也是⼀样的,当程序运⾏到主函数中语句“int result = add(3,5);”的时候,如果向上没有寻到add()的定义,那么编译器⼀定就会报错。所以要不然添加函数的原型声明,要不然就将函数的定义直接写在主函数之前。
函数⾸部int add(int a, int b)中的第⼀个int,即add之前的这个int称为函数的类型。表明这个函数将要返回⼀个整数类型的值。这个类型可以是C语⾔中任何被允许的数据类型,包括void,意为⽆返回值类型,即这个函数不需要返回任何的值。
函数⾸部int add(int a, int b)中的add称为函数的名字,简称函数名。
函数⾸部int add(int a, int b)中int a和int b称为函数的形式参数。这⾥形式参数理论上可以有⽆穷多个,当然,现实情况下3-5个就已经算是很多了;形式参数中,即使a和b都是int类型的,也要分别定义才⾏;形式参数可以在函数中直接使⽤,⽆须再次定义;形式参数是⽤来告诉调⽤者,你应该给我传递来什么样⼦的数据,我好利⽤你给我的数据在函数中进⾏计算。
int add(int a, int b){}中的{}就是函数体的内容了。函数需要进⾏的所有的操作都要放在这对⼤括号中。想必⼤家也看到了函数体中最后有⼀条语句是return,这条语句起到的作⽤就是返回函数计算的结果,在这个程序中就是将加法的结果返回给主函数。需要注意的是,函数的类型和返回值的类型必须严格⼀致!
函数的定义到此为⽌,接下来讲讲函数的调⽤⽅式。只要定义好函数,通过函数名(实际参数1,实际参数2,实际参数n)这种⽅式就可以调⽤函数了。例如主函数中的“int result = add(3,5);”,就是调⽤了add函数。这⾥,3和5称为实际参数,即你究竟想让函数帮你计算哪两个数的加法结果,你就在这个括号⾥边写哪⼏个数字。必须要严格遵守的规定:实际参数和形式参数必须⼀⼀对应,数量应该相同,类型也保持⼀致。
理解了这⼏点之后,⼀个基本的函数就已经可以写出来了。接下来来个题⽬尝试⼀下:
输⼊精度e,使⽤公式求π的近似值,精确到最后⼀项的绝对值⼩于e。公式:π=1-1/3+1/5-1/7+...
代码:
//⾸先得有头⽂件
#include
#include//后边要使⽤到fabs绝对值函数
//然后就是主函数了
int main(void)
{
double pi, e; //定义所需变量
double f_pi(double e); //原型声明。函数名只要符合命名规则即可 //因为要求⼩于e,所以也将这个e传递过去
printf("enter e: "); //输⼊的提⽰
scanf("%lf", &e); // double类型的e对应%lf,记住不要缺少&
printf("pi=%lf
", f_pi(e) ); // 函数返回的是个double类型的值,直接输出
return 0;
}
double f_pi(double e) //函数⾸部,形参和实参⼀定要对应,可以重名
{
int denominator, flag;
double item, sum;
//请注意“先定义,然后赋初值再使⽤”的好习惯
flag = 1; //负责变换正负符号的变量
denominator = 1; //分母初值为1,第⼀项的1为1/1
item=1.0; //存放每⼀项的值
sum=0;
while(fabs(item)>=e) //满⾜条件就循环
{
item=flag*1.0/denominator; //计算每⼀项的值。flag控制符号
//1.0必须写出⼩数位,否则整项就变成⼀个整型值
sum+=item; //累加
flag = -flag; //符号正负切换
denominator = denominator + 2;//分母递增
}
return sum; //sum的类型和函数的类型必须⼀致
}
函数的定义和调⽤其实并不难理解,相信很多⼈困扰在参数的传递上,接下来总结⼀下函数参数传递的⼏种⽅式:
正常的参数调⽤,例如int、float、double等⼀⼀对应的传递。
⽆参数,也⽆返回值。例如下列代码就只是为了输出⼀些语句。这种做法在语法上是被允许的,但是并不推荐这么写。
void printf()
{
printf("hello world!");
}
3. 参数是数组的名字。我们知道数组的名字是个地址,那么如果实参是数组名的.话,我们可以将形参设置成指针,指向实参传递过来的数组的⾸地址。
4. 参数是指针。如果实参是指针,那么形参肯定也得是指针。保持类型⼀致即可,然后在函数内部再对指针进⾏操作。
5. 参数是结构体。如果实参是结构体,⼀般来说我们使⽤结构体指针来做形参⽐较合适。
还是在此分割⼀下吧,说了这么多,可能很多⼈在问问什么函数定义这么⿇烦,还要定义函数,直接都写在main函数中多⽅便?
c语言的冒泡排序算法
⾮也!
C语⾔是⼀个过程化的语⾔,C语⾔中的主函数其实是⽤来主导程序的进程和数据的流动⽅向的。如果将主函数写的过于复杂,我们阅读程序的结构就会⾮常的费⼒。
C语⾔中函数回调
什么是回调函数?
简⽽⾔之,回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤为调⽤它所指向的函数时,我们就说这是回调函数。
为什么要使⽤回调函数?
因为可以把调⽤者与被调⽤者分开。调⽤者不关⼼谁是被调⽤者,所有它需知道的,只是存在⼀个具有某种特定原型、某些限制条件(如返回值为int)的被调⽤函数。
如果想知道回调函数在实际中有什么作⽤,先假设有这样⼀种情况,我们要编写⼀个库,它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通⽤,不想在函数中嵌⼊排序逻辑,⽽让使⽤者来实现相应的逻辑;或者,想让库可⽤于多种数据类型(int、float、string),此时,该怎么办呢?可以使⽤函数指针,并进⾏回调。
回调可⽤于通知机制,例如,有时要在程序中设置⼀个计时器,每到⼀定时间,程序会得到相应的通知,但通知机制的实现者对我们的程序⼀⽆所知。⽽此时,就需有⼀个特定原型的函数指针,⽤这个指针来进⾏回调,来通知我们的程序事件已经发⽣。
下⾯是⾃⼰写的⼀个简单的回调函数,相⽐其他的那些复杂的代码,这个更容易理解:
#include
#include
void perfect(int n)
{
int i=1;
int count=0;
for(i=1;i
{
if(0==n%i)
{
count+=i;
}
}
if(count==n)
printf("%d是完数
",n);
else printf("%d不是完数
",n);
}
void myCallback(void (*perfect)(int ),int n) {
perfect(n);
}
int main()
{
int n;
printf("请输⼊⼀个正整数
");
scanf("%d",&n);
myCallback(perfect,n);
return 0;
}
C语⾔中的刷新和定位函数
⼀.fflush
1.fflush的原型如下:
intfflush(FILE *stream);
2.当需要⽴即把输出缓冲区的数据进⾏物理写⼊时,应该使⽤这个函数。例如调⽤fflush函数保证调试信息实际打印出来,⽽不是保存在缓冲区中直到以后才打印。
⼆.定位函数
1.在正常情况下,数据以线性的⽅式写⼊,这意味着后⾯写⼊的数据在⽂件中的位置是在以前所有写⼊数据的后⾯。C同时⽀持随机访问
I/O,也就是以任意顺序访问⽂件的不同位置。随机访问是通过在读取或写⼊前,先定位到⽂件中需要的位置来实现的。
2.定位函数原型:
1>long ftell(FILE*stream);
2>intfseek(FILE *steam,long offset,intfrom);
3.ftell函数返回流的当前位置。即:下⼀个读取或写⼊将要开始的位置距离⽂件起始位置的偏移量。该函数允许保存⼀个⽂件的当前位置。
1>在⼆进制流中,这个值就是当前位置距离⽂件起始位置之间的字节数。
2>在⽂本流中,这个值表⽰⼀个位置,但它并不⼀定准确地表⽰当前位置和⽂件起始位置之间的字符数,因为有些系统将对⾏末字符进⾏翻译转换。但是,ftell函数返回的值总是可以⽤于fseek函数中,作为⼀个距离⽂件起始位置的偏移量。
4.fseek函数允许你⼀个流中定位。这个函数将改变下⼀个读取或写⼊操作的位置。它的第 1个参数是需要改变的流。它的第2和第3个参数标识⽂件中需要定位的位置。
1>试图定位到⼀个⽂件的起始位置之前是⼀个错误。定位到⽂件尾并进⾏写⼊将扩展这个⽂件。定位到⽂件尾之后并进⾏读取将导致返回⼀条“到达⽂件尾”的信息。
2>在⼆进制流中,从SEEK_END进⾏定位可能不被⽀持,所以应该避免。
3>在⽂本流中,如果from是SEEK_CUR或SEEK_END,offset必须是零。如果from是SEEK_SET,offset必须是⼀个从同⼀个流中以前调⽤ftell所返回的值。
5.⽤fseek改变⼀个流的位置会带来三个副作⽤。
1>⾸先,⾏末指⽰字符被清除。
2>其次,如果在fseek之前使⽤ungetc把⼀个字符返回到流中,那么这个被退回的字符会被丢弃,因为在定位操作以后,它不再是“下⼀个字符”。
3>最后,定位允许你从写⼊模式切换到读取模式,或者回到打开的流以便更新。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论