Featured image of post C素养提升-函数专题

C素养提升-函数专题

在c语言中,函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。

函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。

一般形式如下:

<数据类型> <函数名称>(<形式参数说明>)

函数的参数传递

函数之间的参数传递方式:

  • 全局变量
  • 复制传递方式
  • 地址传递方式

1.全局变量

全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。

全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。不建议使用

2.复制传递

调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。

形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。

3.地址传递

按地址传递,实参为变量的地址,而形参为同类型的指针。

被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>

int str_fun(char *p);

int main(int argc, char *argv[])
{
    char s[] = "welcome2023Jiangxi";
    int n;
    
    n = str_fun(s);
    printf("n=%d %s\n", n, s);
    
    return 0;
}

// char *p = n		我们需要习惯将形参联想等于实参,两端逻辑需要相通
int str_fun(char *p)
{
    int num = 0;
    while(*p != '\0')
    {
        if(*p <= 'z' && *p >= 'a')
        {
        	num++;
            *p -= ' ';
	    }
        p++;
	}
    return num;
}

image-20230131104155837

函数的传参–数组

  • 全局数组传递方式

  • 复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)

  • 地址传递方式:实参为数组的指针,形参为同类型的指针变量

案例一

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int array_sum(int data[], int n);	//相当于int array_sum(int *data, int n);

int main(int argc, char *argv[])
{
        int a[] = {5, 9, 10, 3, 10};
        int sum = 0;

        sum = array_sum(a,sizeof(a) / sizeof(int));

        printf("sum=%d\n", sum);
        return 0;
}

int array_sum(int data[], int n)   // int data[] = a;-->error
{								
        int ret = 0;
        int i;

        for(i = 0; i < n; i++)
        {
                ret += data[i]; 
        }
        return ret;
}

image-20230202113334614

上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是int data[],此时的int data[]实际就是int *data,使用sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度

案例二

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// try to write a function,which delete the space character of character string.

#include <stdio.h>

void del_space(char *str);

int main(int argc, char *argv[])
{       
        char a[] = "hello world,hello linux!";
        puts(a);
        del_space(a);
        puts(a);

        return 0; 
}
void del_space(char *str)
{       
        char *p;
        p = str;
        while(*str)
        {
                if(*str == ' ')
                {
                        str++;
                }
                else
                {
                        *p = *str;
                        p++;
                        str++;
                }
        }
        *p = '\0';
}

image-20230202121727967

此处是删除一段字符串中的空格字符,在void del_space()函数中,我们采取的是指针地址传递的形式,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位\0时,代表字符串的末尾,因此我们也需要为赋值*p = '\0';代表末位。

指针函数

1.基本概念

指针函数是指一个函数的返回值为地址量的函数。

2.定义形式

函数指针的定义的一般形式如下:

1
2
3
4
5
6
7
<数据类型> * <函数名称>(<参数说明>){

语句序列;

}

`返回值:全局变量的地址 / static变量的地址 / 字符串常量的地址 / 堆的地址`

3.示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 编写一个指针函数,删除一个字符串中的空格

#include <stdio.h>
#include <string.h>

char *del_space(char *s);

int main(int argc, char *argv[])
{
        char * r;
        char str[] = "How   ar e  y ou!";
        
        r = del_space(str);
        printf("----%s---\n",r);
        
        puts(str);
        
        return 0;
}

char *del_space(char *s)
{
        char *p = s;
        char *r = s;
        
        while(*s)
        {
                if(*s == ' ')
                {
                        s++;
                }
                else
                {
                        *p = *s;
                        s++;
                        p++;
                }
        }
        *p = '\0';

        return r;
}

image-20230214135249007

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 编写一个函数,实现两个字符串的连接

#include <stdio.h>

char *mstrcat(char *dest, const char * src);

int main(int argc, char *argv[])
{
	char dest[59] = "welcome";
	char src[] = "makeru";
	
	puts(mstrcat(dest,src));
	puts(dest);
	
	return 0;
}

char *mstrcat(char *dest, const char * src)
{
	char *r = dest;
	while(*dest)
	{
		dest++;
	}
	while(*src)
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = '\0';
	
	return r;
}

image-20230214140618531

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 编写一个函数,将传入的整型转成字符串

#include <stdio.h>

char * itoa(int n);
int main(int argc, char *argv[])
{
        int n;
        char s[50], *r;

        printf("input:");
        scanf("%d",&n);

        r = itoa(s, n);

        puts(r);
        puts(s);

        return 0;
}

char * itoa(char *p, int n)
{
        int r, i = 0, j;
        //static char p[50];

        while(n)
        {
                r = n % 10;
                n /= 10;
                p[i] = r + '0';
                i++;
        }
        p[i] = '\0';

        j = i - 1;
        i = 0;

        while(i < j)
        {
                r = p[i];
                p[i] = p[j];
                p[j] = r;
                j--;
                i++;
        }

        return p;
}

image-20230214143612736

递归函数

1.基本概念

递归函数是指一个函数的函数体中直接或间接调用了该函数自身

递归函数调用的执行过程分为两个阶段:

  • 递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。
  • 回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。

2.示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 计算n!

#include <stdio.h>

int fac(int n);

int main(int argc, char *argv[])
{
	int n;
	
	printf("input:");
	scanf("%d",&n);
	
	printf("%d\n", fac(n));
	
	return 0;
}

int fac(int n)
{
	if(n == 0 || n == 1)
		return 1;
	return n * fac(n-1);
}

image-20230214144903183

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 编写一段程序,计算斐波那契序列

#include <stdio.h>

int fib(int n);

int main(int argc, char *argv[])
{
    int n = 1;
    while(n <= 10)
    {
        printf("%d ",fib(n));
        n++;
	}
    
    printf("\n");
    return 0;
}

int fib(int n)
{
    if(n == 1 || n == 2)
        return 1;
    return fib(n-1)+fib(n-2);
}

image-20230214145721633

函数指针

1.基本概念

函数指针用来存放函数的地址,这个地址是一个函数的入口地址

  • 函数名代表了函数的入口地址

2.定义形式

函数指针变量说明的一般形式如下:

1
2
3
4
<数据类型> (*<函数指针名称>) (<参数说明列表>);

eg:
int (*p)(int a, int b);

3.函数指针数组

定义:函数指针数组是一个保存若干个函数名的数组。

一般形式如下:

1
2
3
4
<数据类型> (*<函数指针数组名称>)(<大小>)(<参数说明列表>);

---<大小>:指函数指针数组元素的个数
---其他等同普通的函数指针

4.示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 编写一段程序,实现qsort()排序的功能

#include <stdio.h>

int compare(const void*, const void *);

int main(int argc, char *argv[])
{
        int s[] = {89, 23, 5, 54, 75}, n, i;
    n = sizeof(s) / sizeof(int);
    qsort(s, n, sizeof(int), compare);

    for(i = 0;i < n; i++)
        printf("%d ",s[i]);
    puts("");

    return 0;
}

int compare(const void* p, const void *q)
{
        return (*(int *)p - *(int *)q);
}

image-20230214173053208

顺颂时祺,秋绥冬禧
Built with Hugo
Theme Stack designed by Jimmy