1 指针的使用
1.1 问题
写一个程序,回顾指针的基本应用,然后测试空指针和野指针,再加上条件判断进行避免。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:指针的使用
代码如下所示:
- #include <stdio.h>
- void swap(int *a, int *b)
- {
- int tmp = *a;
- *a = *b;
- *b = tmp;
- }
- int main()
- {
- int a = 10;
- int *p = &a;
- printf("a = %d\n", *p);
- printf("p = %p\n", p);
- p = p + 1;
- printf("p + 1 = %p\n", p);
- p = p - 1;
- printf("p - 1 = %p\n", p);
- int b = 20;
- printf("a = %d, b = %d\n", a, b);
- swap(&a, &b);
- printf("a = %d, b = %d\n", a, b);
- const int *p1 = &a;
- //*p1 = 30;
- p1 = &b;
- int *const p2 = &a;
- *p2 = 40;
- //p2 = &b;
- p = NULL;
- if (p)
- printf("p = %p\n", p);
- return 0;
- }
上述代码中,以下代码:
- void swap(int *a, int *b)
- {
- int tmp = *a;
- *a = *b;
- *b = tmp;
- }
定义了一个函数swap1,该函数有两个参数,为整型指针变量a和b。在该函数中,以下语句:
- int tmp = *a;
- *a = *b;
- *b = tmp;
通过第三个变量tmp,将整型指针变量a和b指向的地址的值进行交换。
上述代码中,以下代码:
- int a = 10;
- int *p = &a;
- printf("a = %d\n", *p);
首先,定义一个整型变量a,并初始化为10。
然后,定义一个整型指针变量p,并初始化为变量a的地址。
最后,输出指针变量p指向的地址的内容。
上述代码中,以下代码:
- printf("p = %p\n", p);
- p = p + 1;
- printf("p + 1 = %p\n", p);
首先,输出指针变量加1前的地址值。
然后,将指针变量p加1。
最后,输出指针变量加1后的地址值。
上述代码中,以下代码:
- p = p - 1;
- printf("p - 1 = %p\n", p);
首先,将指针变量p减1。
然后,输出指针变量减1后的地址值。
上述代码中,以下代码:
- int b = 20;
- printf("a = %d, b = %d\n", a, b);
- swap(&a, &b);
- printf("a = %d, b = %d\n", a, b);
首先,定义一个整型变量b,并初始化为20。
然后,输出变量a和b在调用swap函数前的值。
下一步,调用函数swap。
最后,输出变量a和b在调用swap函数后的值。
上述代码中,以下代码:
- const int *p1 = &a;
- //*p1 = 30;
- p1 = &b;
在*号左边加const关键字,锁定的是指针p1指向的地址的内容,所以第2行是错误的而第3行是正确的。
上述代码中,以下代码:
- int *const p2 = &a;
- *p2 = 40;
- //p2 = &b;
在*号右边加const关键字,锁定的是指针p1本身,所以第2行是正确的而第3行是错误的。
上述代码中,以下代码:
- p = NULL;
- if (p)
- printf("p = %p\n", p);
为防止野指针的出现,在不再使用指针p后,应将其置空,这样可以通过条件p是否为空来判断指针是否有效。
1.3 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- void swap(int *a, int *b)
- {
- int tmp = *a;
- *a = *b;
- *b = tmp;
- }
- int main()
- {
- int a = 10;
- int *p = &a;
- printf("a = %d\n", *p);
- printf("p = %p\n", p);
- p = p + 1;
- printf("p + 1 = %p\n", p);
- p = p - 1;
- printf("p - 1 = %p\n", p);
- int b = 20;
- printf("a = %d, b = %d\n", a, b);
- swap(&a, &b);
- printf("a = %d, b = %d\n", a, b);
- const int *p1 = &a;
- //*p1 = 30;
- p1 = &b;
- int *const p2 = &a;
- *p2 = 40;
- //p2 = &b;
- p = NULL;
- if (p)
- printf("p = %p\n", p);
- return 0;
- }
2 二级指针的应用
2.1 问题
使用二级指针操作字符串数组。
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:二级指针的应用(指针数组:本质为数组,存放的是指针)
代码如下所示:
- #include <stdio.h>
- int main()
- {
- char *name[] = {"zhangsan", "lisi", "wangwu", "zhaoliu"};
- char **p = name;
- for (int i = 0; i < 4; i++)
- printf("%s\n", p[i]);
- return 0;
- }
上述代码中,以下代码:
- char *name[] = {"zhangsan", "lisi", "wangwu", "zhaoliu"};
定义一个指针数组name,并初始化为四个字符串。
上述代码中,以下代码:
- char **p = name;
定义一个二级指针p,并初始化为指针数组名name。
上述代码中,以下代码:
- for (int i = 0; i < 4; i++)
- printf("%s\n", p[i]);
设置循环,将二级指针p指向的字符指针数组内的内容输出。其中,p等效于name,p[i]等效于name[i]。
2.3 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int main()
- {
- char *name[] = {"zhangsan", "lisi", "wangwu", "zhaoliu"};
- char **p = name;
- for (int i = 0; i < 4; i++)
- printf("%s\n", p[i]);
- return 0;
- }
3 二级指针的应用(续1)
3.1 问题
定义一个函数,要求实现字符串转换成int,要求一个字符一个字符的转换,如果遇到不是数字字符的就返回前面的整数和后面的字符串。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:二级指针的应用(续1)
代码如下所示:
- #include <stdio.h>
- int convert(char **str)
- {
- int num = 0;
- while (**str)
- {
- if (**str >= ‘0‘ && **str <= ‘9‘)
- num = num * 10 + **str - ‘0‘;
- else
- break;
- (*str)++;
- }
- return num;
- }
- int main()
- {
- char str[] = "1234abc";
- char *p = str;
- printf("%d\n", convert(&p));
- printf("%s\n", p);
- return 0;
- }
上述代码中,以下代码:
- int convert(char **str)
- {
- int num = 0;
- while (**str)
- {
- if (**str >= ‘0‘ && **str <= ‘9‘)
- num = num * 10 + **str - ‘0‘;
- else
- break;
- (*str)++;
- }
- return num;
- }
定义一个函数convert,用于将字符串中的前面数字字符转换成数字并输出后面的字符串。在该函数中,以下代码:
- int num = 0;
定义一个整型变量num,用于存储转换后的数字。在该函数中,以下代码:
- if (**str >= ‘0‘ && **str <= ‘9‘)
- num = num * 10 + **str - ‘0‘;
判断字符**str是否是数字字符,若是,则将其进行转换。在该函数中,以下代码:
- while (**str)
- {
- if (**str >= ‘0‘ && **str <= ‘9‘)
- num = num * 10 + **str - ‘0‘;
- else
- break;
- (*str)++;
- }
设置循环,逐个检查字符串*str中的每个字符,如果是数字字符,则将其进行转换。否则,退出循环。在该函数中,以下代码:
- return num;
返回,转换后的数字。
上述代码中,以下代码:
- int main()
- {
- char str[] = "1234abc";
- char *p = str;
- printf("%d\n", convert(&p));
- printf("%s\n", p);
- return 0;
- }
首先定义一个字符数组str,并初始化一个字符串。
然后,定义一个字符指针p,并初始化为字符数组str。
下一步,打印转换后的数字。
最后,打印剩余的字符。
3.3 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int convert(char **str)
- {
- int num = 0;
- while (**str)
- {
- if (**str >= ‘0‘ && **str <= ‘9‘)
- num = num * 10 + **str - ‘0‘;
- else
- break;
- (*str)++;
- }
- return num;
- }
- int main()
- {
- char str[] = "1234abc";
- char *p = str;
- printf("%d\n", convert(&p));
- printf("%s\n", p);
- return 0;
- }
4 void*的基本用法
4.1 问题
定义一个int*,然后赋值给void*,并对void*的基本用法进行测试。
4.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:void*的基本用法
代码如下所示:
- #include <stdio.h>
- int main()
- {
- int a = 10;
- int *p = &a;
- void *p1 = p;
- //*p1 = 20;
- *(int*)p1 = 20;
- printf("a = %d\n", *(int*)p1);
- return 0;
- }
上述代码中,以下代码:
- int a = 10;
定义一个整型变量a,并初始化为10。
上述代码中,以下代码:
- int *p = &a;
定义一个整型指针变量p,并初始化为整型变量a的地址。
上述代码中,以下代码:
- void *p1 = p;
定义一个万能指针p1,并初始化为整型指针p的值。万能指针是可以指向任意数据类型的变量的指针。
上述代码中,以下代码:
- //*p1 = 20;
万能指针不能直接用*访问指针所指向的地址的内容。
上述代码中,以下代码:
- *(int*)p1 = 20;
- printf("a = %d\n", *(int*)p1);
万能指针必须先转换成其指向的数据类型后,才能用*访问指针所指向的地址的内容。
4.3 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int main()
- {
- int a = 10;
- int *p = &a;
- void *p1 = p;
- //*p1 = 20;
- *(int*)p1 = 20;
- printf("a = %d\n", *(int*)p1);
- return 0;
- }
5 函数指针的使用
5.1 问题
使用函数指针实现对一组数据实现不同的处理方式。
5.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:函数指针的使用
代码如下所示:
- #include <stdio.h>
- int min(int *buf, int size)
- {
- int min = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] < min)
- min = buf[i];
- return min;
- }
- int max(int *buf, int size)
- {
- int max = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] > max)
- max = buf[i];
- return max;
- }
- int main()
- {
- int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
- int (*p)(int*, int);
- p = min;
- printf("data中的最小值是%d\n", p(data, 10));
- p = max;
- printf("data中的最大值是%d\n", p(data, 10));
- return 0;
- }
上述代码中,以下代码:
- int min(int *buf, int size)
- {
- int min = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] < min)
- min = buf[i];
- return min;
- }
定义一个函数min,用于求一组数中的最小值。该函数有两个参数,说明如下:
第一个参数为包含一组数的数组。
第二个参数为数组的个数。
该函数中,以下语句:
- int min = buf[0];
定义一个整型变量min,用于保存一组数中的最小值。该函数中,以下语句:
- for (int i = 0; i < size; i++)
- if (buf[i] < min)
- min = buf[i];
遍历数组,找出最小值。该函数中,以下语句:
- return min;
返回最小值。
上述代码中,以下代码:
- int max(int *buf, int size)
- {
- int max = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] > max)
- max = buf[i];
- return max;
- }
定义一个函数max,用于求一组数中的最大值。该函数有两个参数,说明如下:
第一个参数为包含一组数的数组。
第二个参数为数组的个数。
该函数中,以下语句:
- int max = buf[0];
定义一个整型变量max,用于保存一组数中的最大值。该函数中,以下语句:
- for (int i = 0; i < size; i++)
- if (buf[i] > max)
- max = buf[i];
遍历数组,找出最大值。该函数中,以下语句:
- return max;
返回最大值。
上述代码中,以下代码:
- int main()
- {
- int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
在主函数中,定义一个整型数组data,并初始化为10个整数。
上述代码中,以下代码:
- int (*p)(int*, int);
定义一个函数指针,该指针指向的函数必须返回整型数,并且包含两个参数,一个是整型指针变量,另一个是整型变量。
上述代码中,以下代码:
- p = min;
将函数名min赋值给函数指针p。
注意:赋值时,函数名所对应的函数的返回值和参数类型必须与函数指针要求的一致。
上述代码中,以下代码:
- printf("data中的最小值是%d\n", p(data, 10));
使用函数指针p调用函数min。
上述代码中,以下代码:
- p = max;
将函数名max赋值给函数指针p。
上述代码中,以下代码:
- printf("data中的最大值是%d\n", p(data, 10));
使用函数指针p调用函数max。
5.3 完整代码
本案例的完整代码如下所示:
- #include <stdio.h>
- int min(int *buf, int size)
- {
- int min = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] < min)
- min = buf[i];
- return min;
- }
- int max(int *buf, int size)
- {
- int max = buf[0];
- for (int i = 0; i < size; i++)
- if (buf[i] > max)
- max = buf[i];
- return max;
- }
- int main()
- {
- int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
- int (*p)(int*, int);
- p = min;
- printf("data中的最小值是%d\n", p(data, 10));
- p = max;
- printf("data中的最大值是%d\n", p(data, 10));
- return 0;
- }
6 函数指针的使用(续1)
6.1 问题
利用不同的排序规则排序。
6.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:在主程序中,定义一个数组
代码如下:
- #include <stdio.h>
- int main()
- {
- int a[10] = {1,2,3,4,5,6,7,8,9,0};
- return 0;
- }
步骤二:定义数组打印函数
代码如下:
- #include <stdio.h>
- void print(int* a, int n)
- {
- for (int i=0; i<n; i++) {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
- int main()
- {
- int a[10] = {1,2,3,4,5,6,7,8,9,0};
- print(a, 10);
- return 0;
- }
步骤三:定义带排序规则的排序函数
排序方法采用冒泡方法。
代码如下:
- #include <stdio.h>
- void print(int* a, int n)
- {
- for (int i=0; i<n; i++) {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
- int rule1(int x, int y)
- {
- return x - y;
- }
- void sort(int* a, int n, int (*f)(int, int))
- {
- for (int i=0; i<n-1; i++) {
- for (int j=0; j<n-i-1; j++) {
- if (f(a[j], a[j+1])>0) {
- int t = a[j];
- a[j] = a[j+1];
- a[j+1] = t;
- }
- }
- }
- }
- int main()
- {
- int a[10] = {1,2,3,4,5,6,7,8,9,0};
- print(a, 10);
- sort(a, 10, rule1);
- print(a, 10);
- return 0;
- }
上述代码中,以下代码:
- int rule1(int x, int y)
- {
- return x - y;
- }
是排序规则,该函数返回形参x与y的差,如果返回值大于0,代表x大于y;如果返回值等于0,代表x等于y;如果返回值小于0,代表x小于y。
上述代码中,以下代码:
- void sort(int* a, int n, int (*f)(int, int))
是排序函数的函数头,该函数是一个无返回值的函数,函数名为sort,函数带有三个形参,第一个形参是一个整型指针变量,它用于接收需要排序的数据;第二个形参是一个整型变量,它用于接收需要排序的数据的个数;第三个形参是一个函数的指针变量,int表示该函数指针变量指向的函数的返回值为整型,f为函数指针变量的变量名,(int,int)代表该函数指针变量指向的函数有两个形参。
在主函数中,使用以下代码调用sort函数:
- sort(a, 10, rule1);
其中,第一个实参a为数组a的数组名,第二个实参10为数组a的数组长度,第三个实参rule1为函数名,该函数为排序规则。
上述代码中,以下代码:
- if (f(a[j], a[j+1])>0) {
- int t = a[j];
- a[j] = a[j+1];
- a[j+1] = t;
- }
是使用函数指针调用函数,指针变量f作为形参,接收实参传递过来的函数的入口地址,即rule1函数,使用f(a[j],a[j+1])调用rule1函数,其中,a[j]和a[j+1]是函数指针变量f指向的函数的两个实参,即函数rule1的两个实参。
步骤四:定义其它排序规则函数
代码如下:
- #include <stdio.h>
- void print(int* a, int n)
- {
- for (int i=0; i<n; i++) {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
- int rule1(int x, int y)
- {
- return x - y;
- }
- int rule2(int x, int y)
- {
- return y - x;
- }
- int rule3(int x, int y)
- {
- return x%3 - y%3;
- }
- void sort(int* a, int n, int (*f)(int, int))
- {
- for (int i=0; i<n-1; i++) {
- for (int j=0; j<n-i-1; j++) {
- if (f(a[j], a[j+1])>0) {
- int t = a[j];
- a[j] = a[j+1];
- a[j+1] = t;
- }
- }
- }
- }
- int main()
- {
- int a[10] = {1,2,3,4,5,6,7,8,9,0};
- print(a, 10);
- sort(a, 10, rule1);
- print(a, 10);
- sort(a, 10, rule2);
- print(a, 10);
- sort(a, 10, rule3);
- print(a, 10);
- return 0;
- }
6.3 完整代码
- #include <stdio.h>
- void print(int* a, int n)
- {
- for (int i=0; i<n; i++) {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
- int rule1(int x, int y)
- {
- return x - y;
- }
- int rule2(int x, int y)
- {
- return y - x;
- }
- int rule3(int x, int y)
- {
- return x%3 - y%3;
- }
- void sort(int* a, int n, int (*f)(int, int))
- {
- for (int i=0; i<n-1; i++) {
- for (int j=0; j<n-i-1; j++) {
- if (f(a[j], a[j+1])>0) {
- int t = a[j];
- a[j] = a[j+1];
- a[j+1] = t;
- }
- }
- }
- }
- int main()
- {
- int a[10] = {1,2,3,4,5,6,7,8,9,0};
- print(a, 10);
- sort(a, 10, rule1);
- print(a, 10);
- sort(a, 10, rule2);
- print(a, 10);
- sort(a, 10, rule3);
- print(a, 10);
- return 0;
- }