C补习--------->第六天,二级指针、指针和数组的关系、位置排序

本文详细介绍了二级指针的概念,包括其定义格式和作用,强调了二级指针用于获取一级指针的值。接着,探讨了指针和数组的关系,特别是指针的算术运算,如加减操作以及指针增量。通过实例展示了如何使用指针遍历数组。最后,给出了两个编程练习,分别涉及字符串中空格计数和使用指针对数组进行冒泡排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,二级指针:


二维数组?---》数组的数组
二级指针?---》指针的指针

概念:二级指针存储的是一级指针的地址
(定义意味着有空间
  有空间就会有地址)
  
  格式:
       定义一级指针的格式:
       存储类型  数据类型 * 指针变量名;
       
       定义二级指针的格式:
       存储类型  数据类型 **指针变量名;
       分析:
            存储类型:二级指针自身的存储类型
            数据类型**:二级指针的数据类型
            数据类型*:二级指针所指向的类型
            指针变量名:见名知义
            
--------------------------------------------------------
总结:
(1)什么时候需要定义一个二级指针出来?----》当需要该一级指针的值时
(2)如何确定指针的类型?
-----》去掉[变量名] ,剩余的就是该指针自身的类型
     eg:
         int *p; int *
         int **pp; int **
(3)如何确定指针所指向的类型?
----》去掉[* 指针变量名] ,剩余的就是该指针所指向的类型
(4)如何分析一个指针一次性访问空间的大小?
----》依赖于所指向的类型
    char **pp; pp一次性访问空间的大小为4个
    char *p; p一次性访问的空间为1个
    int ****pppp;pppp一次性可以访问空间为4个
    

 
  1. #include <stdio.h>

  2. int main(int argc, const char *argv[])

  3. {

  4. int a = 90;

  5. int b = 78;

  6. int *p = &a;

  7. printf("*p = %d\n",*p);

  8. //*p = 56;

  9. //p = &b;

  10. int **pp = &p;

  11. *pp = &b;

  12. printf("*p = %d\n",*p);

  13. return 0;

  14. }


-----------------------------------------------------------------------------------------------------

指针和数组的结合:
指针和一维数组的关系:

指针的算术运算:(+ - * / % ++ --)

假设以p和q为例(注意:p和q是同类型的指针变量)
p + N:代表p向地址增大方向移动N个数据类型的大小(p + sizeof(数据类型) * N)
p - N:代表p向地址减小方向移动N个数据类型的大小(p - sizeof(数据类型) * N)
p++:代表p向地址增大方向移动1个数据类型的大小(p + sizeof(数据类型) * 1)
p--:代表p向地址减小方向移动1个数据类型的大小(p - sizeof(数据类型) * 1)
p-q:代表两个指针之间相隔元素的个数( p - q / sizeof(数据类型))

 
  1. #include <stdio.h>

  2. int main(int argc, const char *argv[])

  3. {

  4. //定义三个指针变量

  5. int *p;

  6. short *q;

  7. char *s;

  8. int *r = p+4;

  9. printf("r-p = %d\n",r-p);

  10. /*

  11. p++;

  12. printf("p = %p\n",p);

  13. printf("p = %p\t p + 1 = %p\n",p,p+3);

  14. printf("q = %p\t s + 1 = %p\n",q,q+1);

  15. printf("s = %p\t s + 1 = %p\n",s,s+1);

  16. */

  17. return 0;

  18. }


p++和p+1的区别:
p++《===》 p = p+1;因此,p++会引起指针指向的改变
p+1不会引起指针指向的改变

数组名:
(1)作为数组名,可以代表整个数组
(2)也可以代表数组的首地址


打印输出数组元素的方式:
arr[i]  <===> *(arr+i)  <===> *(p+i) <===> *(p++)  <===> p[i] <===> i[arr]  <===> i[p]

 
  1. #include <stdio.h>

  2. int main(int argc, const char *argv[])

  3. {

  4. int arr[5] = {1,2,3,4,5};

  5. printf("sizeof(arr) = %d\n",sizeof(arr));

  6. //定义一个指针,指向该一维数组的首元素

  7. int *p = arr;

  8. //printf("arr = %p\n",arr);

  9. //printf("&arr[0] = %p\n",&arr[0]);

  10. int i;

  11. for(i=0;i<5;i++)

  12. {

  13. //printf("%d ",arr[i]);

  14. //printf("%d ",*(arr+i));

  15. //printf("%d ",*(p+i));

  16. //printf("%d ",*(p++));

  17. //printf("%d ",p[i]);

  18. //printf("%d ",i[arr]);

  19. printf("%d ",i[p]);

  20. }

  21. printf("\n");

  22. return 0;

  23. }


分析:可以使用p[i]这种方式来遍历数组的原因是:编译器会自动将p[i]编译成*(p+i)  

总结:
对于数组名:arr[i] 
对于指针:*(p+i) / *(p++)  


练习: 
(1)从键盘获得一个字符串,利用指针实现求该字符串中空格的个数

 
  1. #include <stdio.h>

  2. #define N 20

  3. int main(int argc, const char *argv[])

  4. {

  5. //定义一个字符数组

  6. char str[N] = {'\0'};

  7. //定义一个字符指针指向该数组的首元素

  8. char *p = str;

  9. printf("请输入一个字符串:\n");

  10. gets(p);

  11. int count = 0;

  12. //遍历该字符串

  13. while(*p != '\0')

  14. {

  15. if(' ' == *p)

  16. {

  17. count++;

  18. }

  19. p++;

  20. }

  21. printf("count = %d\n",count);

  22. return 0;

  23. }


(2)利用指针实现冒泡(改变指针指向/ 不改变指针指向)

 
  1. #include <stdio.h>

  2. #define N 5

  3. int main(int argc, const char *argv[])

  4. {

  5. //利用指针实现排序

  6. int arr[N] = {0};

  7. //定义一个整形指针变量指向该数组首元素

  8. int *p = arr;

  9. printf("请输入:\n");

  10. int i,j;

  11. for(i=0;i<N;i++)

  12. {

  13. //scanf("%d",&arr[i]);

  14. scanf("%d",p+i);

  15. }

  16. printf("排序之前为: \n");

  17. for(i=0;i<N;i++)

  18. {

  19. //printf("% ",arr[i]);

  20. printf("%d ",*(p+i));

  21. }

  22. printf("\n");

  23. for(i=0;i<N-1;i++)

  24. {

  25. p = arr;//让p重新指向首元素

  26. for(j=0;j<N-1-i;j++)

  27. {

  28. if(*p > *(p+1))

  29. {

  30. int temp;

  31. temp = *p;

  32. *p = *(p+1);

  33. *(p+1) = temp;

  34. }

  35. p++;

  36. }

  37. }

  38. printf("排序之后为: \n");

  39. p = arr;

  40. for(i=0;i<N;i++)

  41. {

  42. //printf("% ",arr[i]);

  43. printf("%d ",*(p+i));

  44. }

  45. printf("\n");

  46. return 0;

  47. }

冒泡排序:从左至右,两两依次进行比较  

          注意:冒泡按照数据找位置
选择排序:
         假设有N个数:
         第一趟:找出最大的数,将该数与位置为0的数字进行交换
         第二趟:从总个数减1的人数中,再找出最大的时钟与位置为1的数字进行交换。。
         。。。。。。。。。。。。
         


         注意:选择按照位置找数据

 
  1. #include <stdio.h>

  2. #define M 5

  3. int main(int argc, const char *argv[])

  4. {

  5. int arr[M] = {0};

  6. int i;

  7. for(i=0;i<M;i++)

  8. {

  9. scanf("%d",&arr[i]);

  10. }

  11. int j;

  12. //int index;

  13. //选择排序

  14. for(i=0;i<M-1;i++)

  15. {

  16. //index = i;

  17. for(j=i+1;j<M;j++)

  18. {

  19. /*if(arr[index] > arr[j])

  20. {

  21. index = j;

  22. }

  23. */

  24. if(arr[i] > arr[j])

  25. {

  26. int temp;

  27. temp = arr[i];

  28. arr[i] = arr[j];

  29. arr[j] = temp;

  30. }

  31. }

  32. /*

  33. //交换

  34. int temp;

  35. temp = arr[i];

  36. arr[i] = arr[index];

  37. arr[index] = temp;

  38. */

  39. }

  40. printf("排序之后为:\n");

  41. for(i=0;i<M;i++)

  42. {

  43. printf("%d ",arr[i]);

  44. }

  45. putchar('\n');

  46. return 0;

  47. }


作业:
1,指针实现,定义一个字符串,实现字符串的倒置  "break" ---> "kaerb"

 
  1. #include<stdio.h>

  2. #include<string.h>

  3. #define M 5

  4. int main(int argc, const char *argv[])

  5. {

  6. //指针实现,字符串的倒置

  7. char arr[M] = {'\0'};

  8. printf("请输入字符串:\n");

  9. //定义指针

  10. char *p = arr; // p = &arr[0]

  11. gets(p);

  12. //使用strlen来测出arr数组的有效字节

  13. int l;

  14. l = strlen(arr);

  15. //p(首地址) + l -1 就是末地址

  16. p = p + l - 1;

  17. int i;

  18. for(i = 0;i < M;i++)

  19. {

  20. printf("%c",*(p-i));

  21. }

  22. putchar('\n');

  23. return 0;

  24. }


2,利用指针实现strcat功能

 
  1. #include<stdio.h>

  2. #include<string.h>

  3. #define M 15

  4. #define N 20

  5. char *mystrcat(char *p,char*q,int n)

  6. {

  7. if(NULL == p || NULL == q)

  8. {

  9. printf("NULL_ERROR!\n");

  10. return NULL;

  11. }

  12. while(*p)

  13. {

  14. p++;

  15. }

  16. //n代表连接arr2的n位

  17. while(n--)

  18. {

  19. *p++ = *q++;

  20. }

  21. *p = '\0';

  22. return q;

  23. }

  24. int main(int argc, const char *argv[])

  25. {

  26. //使用指针实现strcat的前n位

  27. char arr1[M] = {'\0'};

  28. char arr2[N] = {'\0'};

  29. printf("请输入两个字符串:\n");

  30. //gets输入字符串

  31. gets(arr1);

  32. gets(arr2);

  33. /*定义指针,指向数组的首地址

  34. char *p= &arr1[d];

  35. char *q= &arr2[0];*/

  36. //定义数组arr1和arr2的有效字符长度

  37. int l1,l2;

  38. l1 = strlen(arr1);

  39. l2 = strlen(arr2);

  40. if( M < l1 + l2 + 1)

  41. {

  42. printf("error!!!\n");

  43. return -1;

  44. }

  45. /*while(*p)

  46. {

  47. p++;

  48. }*/

  49. /*遍历arr2

  50. while(*q)

  51. {

  52. *p++ = *q++;

  53. }*/

  54. char *s;

  55. s = mystrcat(arr1,arr2,2);

  56. printf("连接之后:%s\n",arr1);

  57. return 0;

  58. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值