C进阶习题(上)

简介: C进阶习题(上)

一、指针进阶

1.1 知识点

(1)指针的数据类型,声明的是指针实际指向内容的数据类型;free释放后,并不会自动置为NULL;野指针指向的是未分配或者已经释放的内存地址

(2)int类型的指针数组,就是一个数组,里面存放的是int*

(3)函数return返回值,不能返回两个(可以通过地址传址),可以一个,可以没有

(4)定义一个函数指针,指向的函数有两个int形参并且返回一个函数指针,返回的指针指向一个有一个int形参且返回int的函数  int (*(*F)(int, int))(int)

(5)声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,(int (*(*p)[10])(int *)  【4 5要求会写】

(6)一个地址是否能放到指针里面,要看指针指向内容的类型是否是该地址指向内容的类型

(7)函数的声明:int Add(int a, int b)  或者是 int Add(int, int);

(8) 做选择题,要注意是单选题还是多选题

(9)int arr[3][5]; int (*arr)[5] 指的是,一个指针指向的是二维数组第一行

1.2 实现一个函数,左旋字符串中的K个字符(旋转字符串)可以类比右旋)

方法一:

1. #include <stdio.h>
2. #include <string.h>
3. //思路:字符串的第一个元素,拿出来放在一个空间里面,再把字符串向前移一位,
4. //再把新的空间里面的元素放在字符串所在空间的最后一个位置
5. void left_move(char* str, int k)
6. {
7.  int i = 0;
8.  for (i = 0; i < k; i++)
9.  {
10.     //每次一个字符
11.     char tmp = *str;
12.     int len = 0;
13.     len = strlen(str);
14.     int j = 0;
15.     for (j = 0; j < len - 1; j++)
16.     {
17.       *(str + j) = *(str + j + 1);
18.     } 
19.     *(str + len - 1) = tmp;
20.   }
21. }
22. 
23. int main()
24. {
25.   char arr[] = "abcdef";//一般用数组存放字符串
26.   int k = 0;
27.   scanf("%d", &k);
28.   left_move(arr, k);
29.   printf("%s\n", arr);
30.   return 0;
31. }

方法二:

1. #include <stdio.h>
2. #include <string.h>
3. //思路:三步反转法,首先需要左移的字符进行逆序进行逆序,
4. //然后字符串不需要进行左移的字符进行逆转,最后整个字符串的元素进行逆序
5. //逆序函数
6. void reverse(char* left, char* right)
7. //学习完指针之后,用指针,不需要用数组下标
8. {
9.  while (left < right)
10.   {
11.     char tmp = *left;
12.     *left = *right;
13.     *right = tmp;
14.     left++;
15.     right--;
16.   }
17. }
18. 
19. //左移函数
20. void left_move(char* str, int k)
21. {
22.   int len = strlen(str);
23.   k = k % len;//这个点要注意,容易忽略
24.   reverse(str, str + k - 1);
25.   reverse(str + k, str + len - 1);
26.   reverse(str, str + len - 1);
27. }
28. 
29. int main()
30. {
31.   char arr[] = "abcdef";//一般用数组存放字符串
32.   int k = 0;
33.   scanf("%d", &k);
34.   left_move(arr, k);
35.   printf("%s\n", arr);
36.   return 0;
37. }

1.3 有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在,时间复杂度小于O(N)[说明,不可以遍历整个数组]。(杨氏矩阵)

代码一:(这种写法不是特别的好)

1. #include <stdio.h>
2. //思路:因为每一行每一列都是递增的,所以需要查找的数字,
3. //只需要和每一行的最后一个元素进行比较(不能和第一个元素进行比较)【可以从右上角以及左下角开始】,如果大于
4. //就可以对下一行进行比较。小于后,找到相应的行,
5. //然后对该行的元素进行比较,从后向前比较,如果该行遍历完之后还是没有,
6. //就说明没有这个数字
7. void find_int_arr(int arr[3][3], int r, int c, int k)
8. {
9.  int x = 0;
10.   int y = c - 1;
11.   while (x <= r - 1 && y >= 0)
12.   {
13.     if (arr[x][y] < k)
14.     {
15.       x++;
16.     }
17.     else if (arr[x][y] > k)
18.     {
19.       y--;
20.     }
21.     else
22.     {
23.       printf("找到了,下标是:x = %d y = %d\n", x, y);
24.       return;
25.     }
26.   }
27.   printf("找不到\n");
28. }
29. 
30. 
31. int main()
32. {
33.   int arr[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
34.   int k = 0;
35.   scanf("%d", &k);
36.   find_int_arr(arr, 3, 3, k);
37.   return 0;
38. }

代码2:(优化后的代码)

1. #include <stdio.h>
2. //区别:函数返回下标的值,以及找不到的内容,
3. //通过地址传址
4. void find_int_arr(int arr[3][3], int* px, int* py, int k)
5. {
6.  int x = 0;
7.  int y = *py -1; 
8.  while (x <= *px - 1 && y >= 0)
9.  {
10.     if (arr[x][y] < k)
11.     {
12.       x++;
13.     }
14.     else if (arr[x][y] > k)
15.     {
16.       y--;
17.     }
18.     else
19.     {
20.       *px = x;
21.       *py = y;
22.       return;
23.     }
24.   }
25.   *px = -1;
26.   *py = -1;
27. }
28. 
29. int main()
30. {
31.   int arr[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
32.   int x = 3;
33.   int y = 3;
34.   int k = 0;
35.   scanf("%d", &k);
36.   //参数是返回型参数
37.   find_int_arr(arr, &x, &y, k);
38.   if (x == -1 && y == -1)
39.   {
40.     printf("找不到\n");
41.   }
42.   else
43.   {
44.     printf("找到了,下标是:%d %d", x, y);
45.   }
46.   return 0;
47. }

1.4  写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。是的话,返回1,否返回0

方法一:

1. //判断是一个字符串的旋转字符
2. //思路:旋转判断旋转判断
3. #include <stdio.h>
4. #include <string.h>
5. void reverse(char* left, char* right)
6. {
7.  while (left < right)
8.  {
9.    char tmp = *left;
10.     *left = *right;
11.     *right = tmp;
12.     left++;
13.     right--;
14.   }
15. }
16. //左移函数
17. void left_move(char* str, int k)
18. {
19.   int len = strlen(str);
20.   k = k % len;//这个点要注意,容易忽略
21.   reverse(str, str + k - 1);
22.   reverse(str + k, str + len - 1);
23.   reverse(str, str + len - 1);
24. }
25. int is_left_move(char* arr1, char* arr2)
26. {
27.   int len = strlen(arr1);
28.   int i = 0;
29.   for (i = 0; i < len; i++)
30.   {
31.     left_move(arr1, 1);
32.     if (strcmp(arr1, arr2) == 0)
33.       return 1;
34.   }
35.   return 0;
36. }
37. 
38. int main()
39. {
40.   char arr1[] = "AABCD";
41.   char arr2[] = "BCDAA";
42.   int ret = is_left_move(arr1, arr2);
43.   printf("%d\n", ret);
44.   return 0;
45. }

方法二:

1. // 判断是一个字符串的旋转字符
2. //思路:字符串追加本身,再判断是否包含里面,包含就是旋转字符
3. #include <stdio.h>
4. #include <string.h>
5. 
6. int is_left_move(char* arr1, char* arr2)
7. {
8.  int len1 = strlen(arr1);
9.  int len2 = strlen(arr2);
10.   if (len1 != len2)
11.     return 0;
12.   strncat(arr1, arr1, len1);
13.   if (strstr(arr1, arr2))
14.     return 1;
15.   else
16.     return 0; 
17. }
18. 
19. int main()
20. {
21.   char arr1[20] = "AABCD";
22.   char arr2[] = "BCDAA";
23.   int ret = is_left_move(arr1, arr2);
24.   printf("%d\n", ret);
25.   return 0;
26. }

动态内存分配

2.1 知识点

(1)枚举,打印出来,依次加一,相较于上一个(除了,定义时候就赋值的)

(2)define定义的标识符常量,是替换内容。需要带进去,而不是计算完再代入(易错点)

2.2代码结果

1. int main()
2. {
3.   unsigned char puc[4];
4. struct tagPIM
5.   {
6.     unsigned char ucPim1;
7.     unsigned char ucData0 : 1;
8.     unsigned char ucData1 : 2;
9.     unsigned char ucData2 : 3;
10.   }*pstPimData;
11.   pstPimData = (struct tagPIM*)puc;
12.   memset(puc,0,4);
13.   pstPimData->ucPim1 = 2; 
14.   pstPimData->ucData0 = 3;
15.   pstPimData->ucData1 = 4;
16.   pstPimData->ucData2 = 5;
17.   printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]);
18. return 0;
19. }

结果为:02 29 00 00

知识点:%x指的是打印16进制;%02x指的是,打印两位

2.3  

1. #include<stdio.h>
2. int main()
3. {
4.   union
5.   {
6. short k;
7. char i[2];
8.   }*s, a;
9.   s = &a;
10.   s->i[0] = 0x39;
11.   s->i[1] = 0x38;
12.   printf("%x\n", a.k);
13. return 0;
14. }

打印结果:3839

2.4 BC100-有序序列合并

输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。输入描述:输入包含三行,第一行包含两个正整数n, m,用空格分隔。n表示第二行第一个升序序列中数字的个数,m表示第三行第二个升序序列中数字的个数。第二行包含n个整数,用空格分隔。第三行包含m个整数,用空格分隔。输出描述:输出为一行,输出长度为n+m的升序序列,即长度为n的升序序列和长度为m的升序序列中的元素重新进行升序序列排列合并。

1. #include <stdio.h>
2. int main()
3. {
4.  int n = 0;
5.  int m = 0;
6. //输入  
7.  scanf("%d %d", &n, &m);
8.  int arr1[n];//在C99标准就可以,牛客网支持
9.  int arr2[m];
10. //输入两个升序的序列
11. int i = 0;
12. for (i = 0; i < n; i++)
13.     {
14.         scanf("%d ", &arr1[i]);
15.     }
16. for (i = 0; i < m; i++)
17.     {
18.         scanf("%d ", &arr2[i]);
19.     }
20. //输出序列
21. int j = 0;
22.     i = 0;
23. while ((i < n) && (j < m))
24.     {
25. if (arr1[i] < arr2[j])
26.         {
27.             printf("%d ", arr1[i]);
28.             i++;
29.         }
30. else
31.         {
32.             printf("%d ", arr2[j]);
33.             j++;
34.         }
35.     }
36. if (i == n)
37.     {
38. for (; j < m; j++)
39.         {
40.             printf("%d ", arr2[j]);
41.         }
42.     }
43. else
44.     {
45. for (; i < n; i++)
46.         {
47.             printf("%d ", arr1[i]);
48.         }
49.     }
50. 
51.   return 0;
52. }


相关文章
|
6月前
|
安全 人机交互 数据处理
====第一章总结及习题======(1)
内容包括 计算机操作系统第四版学习指导与解题和 计算机操作系统(第四版——汤子瀛) 々计算机操作系统(第4版)学习指导与解题 1.1 基本内容
49 0
|
6月前
|
算法 安全 Linux
====第一章总结及习题======(2)
1.3.2 OS的基本特征和功能中的典型问题分析 【例7】操作系统具有哪几大特征?他们之间有何关系?
89 0
|
存储 算法 C语言
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
|
自然语言处理 C语言 C++
C进阶习题(下)
C进阶习题(下)
C语言知识-学习练习题系列-3
C语言知识-学习练习题系列-3
C语言知识-学习练习题
C语言知识-学习练习题
C语言知识-学习练习题2
C语言知识-学习练习题2
C语言知识-学习练习题系列-5
C语言知识-学习练习题系列-5
C语言知识-学习练习题系列-7
C语言知识-学习练习题系列-7