99网
您的当前位置:首页C语言第四周_函数

C语言第四周_函数

来源:99网
C语言重要资料范浩

函数

一。函数基本概念

函数其实就是一段代码

这段代码一般逻辑上具有一定的联系:用来实现一个特定的功能

这段代码我们一般会封装起来,并给它取一个名字,这就构成了一个函数 函数最终是为了“重用”

函数其实是C语言模块化的体现,

比如:程序要接收用户从键盘输入的两个整数m和n,然后求 1+2+3+…+m 1+2+3+…+n

这两个步骤的运算方法是相同的,只有参数不同,如果不定义函数,我们需要在主函数中把两段几乎相同的代码写两遍 代码:

#include main() { intm,n; int k,sum1=0,sum2=0; scanf(\"%d,%d\for(k=1;k<=m;k++) { sum1 += k; } for(k=1;k<=n;k++) { sum2 += k; } printf(\"%d,%d\\n\}

这段代码的核心代码是两个for循环,这两个for循环结构完全相同,只是参数不同,运算结果不同,而在这里我们就要把这段几乎相同的代码写两遍 这里就提出了“函数”,函数就是把一些实现一定功能的代码封装起来,一次封装,可以多次调用——重用

二。函数的定义

把实现一定功能的代码封装起来 1).要能描述代码结构

1

C语言重要资料范浩

2).接收外面给它的参数 3).把运算结果返回 4).要给封装起一个名字 1. 函数定义的格式:

返回值类型函数名(形式参数列表) {

函数体 }

标红色的部分叫:函数头

 返回值类型:描述函数要返回的运算结果的数据类型

如果函数不需要返回值,返回值类型描述可以用void,也可以直接省略

如果函数有返回值,函数体中就要用return语句,return语句后面要有返回的实际数据(return **;)

Return语句后面返回的实际数据的类型要与描述类型兼容(实际返回的数据可以直接转换成返回值类型描述的类型)

如果函数没有返回值,return语句后面可以什么都不加,直接return;,或者连return语句直接省略

 函数名:符合标识符的命名规则  形式参数列表:

形式参数是用来说明函数的参数的形式:参数的类型,参数的个数 格式:参数1的类型参数1的名称,参数2的类型参数2的名称,… 如果函数不需要形式参数,可以用void,也可以直接省略 三。函数调用 1.格式:

函数名(实际参数)

函数名:就是要调用的封装起来的代码所起的名字 实际参数:要传递给函数的实际的数据

可以是变量、常量、表达式、可以是一个函数的调用 实参的个数要和形参的个数一致 类型要兼容(后面解释) 2.调用方式

1)直接作为语句调用,(一般用来调用么有返回值的函数) 2)把函数放入表达式

3)把函数作为另外要给函数的实际参数 函数的定义要放在被调用之前,否则要声明

四。函数声明

样式同函数头,后面直接加分号

作用:告诉编译器,程序中有这么一个函数的定义,但是不在这里 案例:

#include /*

2

C语言重要资料范浩

函数声明 */ Print(); /*

函数定义 */

int Add(inta,int b) {

returna+b; } /*

定义函数,求1+2+...+某个整数

某个整数:是需要外界给定的,这就是参数 形式:1个参数,int类型 返回结果:运算结果 什么类型:int */

int Sum(int n) { int k;

int *p=&k; /*定义验证返回值*/ int sum=0;

for(k=1;k<=n;k++) {

sum += k; }

/*如果返回的是char,会直接返回,因为可以直接进行类型转换

如果返回的是一个浮点数,会提示有数据丢失,也可以返回,因为类型兼容*/ return sum; /*会报错

返回的是一个指针int *,无法直接转换成int*/ //return p; }

void main(void) { intm,n; int k,sum1=0,sum2=0,sum3; scanf(\"%d,%d\ /* 调用函数: 调用形式:表达式 把函数的运算结果(返回值)按照表达式完成运算,再赋值给变量

3

C语言重要资料范浩

*/ sum1 = Sum(m); sum2 = Sum(n); sum3 = 2*Sum(n); printf(\"%d,%d,%d,%d\\n\ /* 调用无返回值的方法,直接作为一个语句,后面要加上; */ Print(); } /*

定义无参数的函数 */ Print() {

printf(\"abcd-----------\"); //return; }

练习:课后练习8 #include /*

如果题目规定在主函数中显示转换的结果 我们需要把字符数组返回

但是,函数一般不会把在函数内定义的数组以指针的形式返回 函数一般不返回指针或者数组 */

voidPrintStr(int k) {

char s[10]; s[0] = k/1000+0x30; s[1] = ' '; s[2] = k%1000/100+0x30; s[3] = ' '; s[4] = k%100/10+0x30; s[5] = ' '; s[6] = k%10+0x30; s[7] = '\\0'; /* --> s[7] = 0,'\\0'的值就是0*/ printf(\"%s\\n\ }

void main(void) {

4

C语言重要资料范浩

int k; char *p;

scanf(\"%d\PrintStr(k); }

五。函数调用过程中的参数传递

实参传递给形参

函数定义:

Intfun1(inta,intb,int c) 调用的时候: fun1(a1,b1,c1);

实参是按照顺序,逐个传递给形参的

A1的值传递给了a: a1实参要能直接转换成形参a的类型,或者可以兼容 B1的值传递给了b: b1的类型要能转换成形参b的类型,或者可以兼容 C1的值传递给了c:。。。

六。函数的调用过程

函数的调用过程其实是代码的跳转

5

C语言重要资料范浩

当代码中调用一个函数的时候,就是跳转(步骤2,5)到这个函数的第一条语句开始执行,

当函数执行完毕(碰到了return语句,执行到函数的最后一条语句(即使没有return))函数会返回(步骤4,7)调用主调函数,继续执行 函数的内部定义的变量和函数的形参变量,都是在函数被调用的时候分配存储空间。

七、变量的作用域

案例:

#include /*

定义全局变量

变量不属于任何函数

全局变量位于程序的全局区域

程序的全局区,是任何函数都可以访问的 全局变量的声明周期:

从程序开始运行开始,到程序运行结束终止 */

int m=10,n=20; /*

函数内定义的变量是局部变量 函数的形参是作为局部变量

6

C语言重要资料范浩

形参的名称可以与实参变量相同,但是不能与函数局部变量名称相同 局部变量的生命周期:

从函数被调用开始,到函数执行结束终止 */

int Sum(intnum) { int k;

int sum=0;

for(k=0;k<=num;k++) { sum+=k; } /*

打印的全局变量*/

printf(\"Sum: %d,%d\\n\return sum; }

intMul(intnum) { int k; intmul=1; for(k=1;k<=num;k++) { mul *= k; } returnmul; }

main() { /* 局部变量与全局变量重名,局部变量在函数内会覆盖全局变量 */ intnum,m,n; scanf(\"%d\ m = Sum(num); n = Mul(num); /*这里输出的是main的局部变量m和n的值,也就是求阶乘和连续加的值,而不是全局变量的值*/ printf(\"main: %d,%d\\n\}

1. 主函数运行到调用Sum之前

7

C语言重要资料范浩

蓝色的区域为Main函数的空间 2.调用Sum期间存储分配

蓝色的区域是main的存储空间,绿色的区域是Sum的存储空间,他们彼此是不能互相访问的,因此变量即使重名,也没有关系,不冲突

主函数中有两个变量与全局变量重名了,在函数内部定义的变量(局部变量)与

8

C语言重要资料范浩

全局变量重名时,会覆盖全局变量

3.调用Sum结束,返回主函数时,存储空间变为:

调用Sum之前的存储空间,Sum所占的绿色的区域被释放了 4. 调用Mul期间的存储

橙色的空间实Mul的存储空间,其实覆盖了刚才Sum的存储空间,这时main的存储空间不变

5.Mul执行结束,回到

6.主函数执行结束

9

C语言重要资料范浩

整个存储空间,包括代码区、常量区、全局区、栈、堆,都被释放掉。

八、函数的参数传递

参数的传递其实是把实参的值复制到形式参数(变量)的空间里 实参传递给形参,函数的返回值的传递 函数能否返回多个值?不行

1.执行完scanf后,用户输入了5;main函数空间内的变量num里面存储了5;

2. 调用Sum函数时,为sum分配存储空间,图中紫色的部分,这时,会把主函数的num的值复制到sum函数的num变量空间中

3.Sum函数执行完毕,还没返回的时候

10

C语言重要资料范浩

4. Sum返回,因为Sum里面有return sum语句

所以程序会在一个临时的存储空间里面存储sum的值(绿色的区域),然后释放Sum的存储空间,根据主函数的语句,把临时空间里面的值赋值给变量m。

九、指针做函数参数

案例:

#include /*

指针做函数参数 */

void fun1(int *p,int length) { int k;

for(k=0;k*p = (*p)*2; p++; /*下面的代码也是可行的 */ //p[k] = p[k]*2; } }

11

C语言重要资料范浩

/*

用数组做函数形参,也需要传送一个地址过来 但是其实这里的a也是一个变量,也可以做运算, */

void fun2(int a[],int length) { int k;

for(k=0;ka[k] = a[k]*2; /*下面的代码也是可行的*/ //*a = (*a)*2; //a++; } }

main() { int a[5] = {1,2,3,4,5}; int k; for(k=0;k<5;k++) { printf(\"%d,\ } printf(\"\\n\"); fun1(a,5); for(k=0;k<5;k++) { printf(\"%d,\ } printf(\"\\n\"); fun2(&a[0],5); for(k=0;k<5;k++) { printf(\"%d,\ } printf(\"\\n\"); }

12

C语言重要资料范浩

十。返回值为指针的函数:

案例: /*

函数返回值为指针的时候,不要试图用指针返回一个局部变量的值 函数一旦执行完毕,局部变量都释放了

即使返回了地址,也已经无法访问这块存储区域 */

int *fun1(int k) {

int b[5] = {8,4,6,8,10}; int m; for(m=0;m<5;m++) { b[m] = b[m]+k; } return b; }

main() { int *p; int k; p = fun1(2); /* 调用函数之后打印结果, */ for(k=0;k<5;k++)

13

C语言重要资料范浩

}

{

printf(\"%d,\}

练习:

统计字符串长度和统计字符串中字母和数字的个数 #include

intnumC=0,numN=0; /*

定义一个函数,统计字符串的长度 */

intstrLen(char *ch) {

int length=0; while(*ch !='\\0') {

length++; ch++; } return length; } /*

统计字符串中字母和数组的个数

函数要给出两个结果:字母的个数、数字的个数 因此不能用函数的返回值给出

把主函数的变量以地址的形式传递给函数 在函数中改变变量的值 */

voidstrNandC(char *ch,int *n1,int *n2) {

*n1 = 0; *n2 = 0; while(*ch !='\\0') { if(*ch>='0'&&*ch<='9') { (*n1)++; } else { (*n2)++;

14

C语言重要资料范浩

} ch++; } } /*

当函数需要给出多个结果的时候 还可以使用全局变量 */

voidstrLL(char *ch) {

while(*ch !='\\0') { if(*ch>='0'&&*ch<='9') { numN++; } else { numC++; } ch++; } }

main() {

char c[20]; int l;

int num1,num2; scanf(\"%s\ //gets(c); l = strLen(c); printf(\"%d\\n\

strNandC(c,&num1,&num2); printf(\"%d,%d\\n\strLL(c);

printf(\"%d,%d\\n\}

15

因篇幅问题不能全部显示,请点此查看更多更全内容