当前位置:   article > 正文

嵌入式学习笔记十四——指针操作一维字符型数组

嵌入式学习笔记十四——指针操作一维字符型数组

1.const的作用

puts函数为例,函数原型是int puts(const char *s);

我们写一个自己的Puts函数,从键盘输入字符串,结构大概是

  1. int Puts(const char *s)
  2. {
  3. while (*s != '\0')
  4. {
  5. putchar(*s);
  6. ++s;
  7. }
  8. putchar('\n');
  9. return 0;
  10. }

在这段代码中++s这个操作是指向下一个元素,如果我们误操作将它写成了++(*s)或是*s++,结果就是改变了指针指向地址的内容。但要求我们输出一个字符串,并不希望误操作导致数组内容被改变,这时候const就发挥作用了。

int puts(const char *s),const表示只读,下面是const的一些用法:

  1. const int a; //a 此时是一个只读的变量
  2. int a = 10;
  3. //int *p = &a;
  4. const int *p = &a; //const限定是 基类型
  5. //表示不能通过 *p 的方式 修改基类型数据
  6. int const *p = &a; //const限定是 基类型
  7. //表示不能通过 *p 的方式 修改基类型数据
  8. //与const int *p = &a等价
  9. int * const p = &a; //const限定是 指针变量p
  10. //表示将p限定位只读
  11. //表示p不能被修改
  12. const int * const p = &a; //基类型和指针变量 都被限定为只读
  13. // p = &b; //不能修改
  14. //*p = b; //不能修改

2.const限定原则

   就近原则  //const 离谁近 就限定谁 

总结:

1.形参设计为 const char *的目的, 防止函数中的误操作 

2.好处
    (1).提前发现问题 将运行时问题,提前到编译时  
    (2).const char * 可以接收  char *和const char * 提高参数的适用性

注意:形参能写成const的都写const 

应用:

    1.如果 不想 通过*p方式改变基类型对应的数据 可以写成:
      const int *p = &a;  
      int const *p = &a;  

   2.如果 指针变量p 定义好后,不想再指向别的变量则写成
     int * const p = &a;

3.指针操作一维字符数组

练习

用函数和指针,完成

1.Puts/Gets

2.Strlen

3.Strcpy/strncpy

4.strcat /Strncat

5.Strcmp/Strncmp

代码如下:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int Puts(const char *s)
  4. {
  5. if (s == NULL)
  6. return -1;
  7. while (*s != '\0')
  8. {
  9. putchar(*s);
  10. ++s;
  11. }
  12. putchar('\n');
  13. return 0;
  14. }
  15. char *Gets(char *s)
  16. {
  17. char *ret = s;
  18. while((*s = getchar()) != '\n')
  19. ++s;
  20. *s = '\0';
  21. return ret;
  22. }
  23. size_t Strlen(const char *s)
  24. {
  25. const char *ret = s;
  26. while (*s != '\0')
  27. {
  28. s++;
  29. }
  30. return s-ret;
  31. }
  32. char *Strcpy(char *dest,const char *src)
  33. {
  34. char *ret = dest;
  35. while (*src != '\0')
  36. {
  37. *dest = *src;
  38. dest++;
  39. src++;
  40. }
  41. *dest = '\0';
  42. return ret;
  43. }
  44. char *Strncpy(char *dest,const char *src,int n)
  45. {
  46. char *ret = dest;
  47. while (*src != '\0' && n > 0)
  48. {
  49. *dest = *src;
  50. ++dest;
  51. ++src;
  52. --n;
  53. }
  54. while (n > 0)
  55. {
  56. *dest = '\0';
  57. ++dest;
  58. --n;
  59. }
  60. return ret;
  61. }
  62. char *strcat(char *dest,const char *src)
  63. {
  64. char *ret = dest;
  65. while (*dest != '\0')
  66. {
  67. ++dest;
  68. }
  69. while(*src != '\0')
  70. {
  71. *dest = *src;
  72. dest++;
  73. src++;
  74. }
  75. *dest = '\0';
  76. return ret;
  77. }
  78. char *Strncat(char *dest,const char *src,size_t n)
  79. {
  80. char *ret = dest;
  81. while (*dest != '\0')
  82. ++dest;
  83. while (*src != '\0' && n != 0)
  84. {
  85. *dest = *src;
  86. ++dest;
  87. ++src;
  88. --n;
  89. }
  90. *dest = '\0';
  91. return ret;
  92. }
  93. int Strcmp(const char *s1,const char *s2)
  94. {
  95. int ret = 0;
  96. while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
  97. {
  98. ++s1;
  99. ++s2;
  100. }
  101. ret = *s1 - *s2;
  102. return ret;
  103. }
  104. int Strncmp(const char *s1,const char *s2,size_t n)
  105. {
  106. int ret = 0;
  107. while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0' && n-1)
  108. {
  109. ++s1;
  110. ++s2;
  111. --n;
  112. }
  113. ret = *s1 - *s2;
  114. return ret;
  115. }
  116. void Memcpy(void *dest,const void *src,size_t n)
  117. {
  118. char *p = dest;
  119. const char *q = src;
  120. while (n > 0)
  121. {
  122. *p = *q;
  123. ++q;
  124. ++p;
  125. --n;
  126. }
  127. }
  128. int main(void)
  129. {
  130. char s[20] = "hello";
  131. char ss[20]= "english";
  132. // Gets(s);
  133. // Puts(s);
  134. // Strncpy(ss,s,5);
  135. // Puts(ss);
  136. // int i = 0;
  137. // for (i = 0;i < 10; ++i)
  138. // {
  139. // printf("s[%d] = %c\n",i,s[i]);
  140. // }
  141. // printf("%ld\n",Strlen(s));
  142. // strcat(ss,s);
  143. // Strncat(ss,s,5);
  144. // Puts(ss);
  145. // printf("%d\n",Strncmp(ss,s,3));
  146. long a[5] = {1,2,3,4,5};
  147. long b[5];
  148. Memcpy(b,a,5*sizeof(a[0]));
  149. int i = 0;
  150. for (i = 0;i < 5;++i)
  151. {
  152. printf ("%ld\n",b[i]);
  153. }
  154. return 0;
  155. }

memcpy函数:

 void *memcpy(void *dest, const void *src, size_t n)
 {
      //一个字节一个字节拷贝 
 }
 void * //NULL 空指针 
        //空类型的指针 --- 万能指针
        //可以接收任意类型的指针  
注意:
    如果用 空类型指针 进行 间接运算,必须 转换成 有明确类型的指针 

总结: 

  1.指针操作一维字符型数组 //字符串
   2.知识点
     //1.指针变量的 类型 是怎么确定的?
     //2.一维字符型数组 字符串 
     //3.处理字符串数据方式
        char s[] = "hello";
        const char *p = "hello"; 
    //4. const 关键字  
         const 关键字使用方法 
         const 形参          
   3.实现字符串相关函数
     gets /puts  
     strlen 
     strcpy /strncpy
     strcat /strncat 
     strcmp /strncmp

4.指针操作二维数组 

int a[2][3];//二维数组 

1.c语言中并不存在,真正的二维数组。
2.二维数组本质 是一维数组的一维数组 
3.二维数组 也 符合数组的特点 //连续性,有序性,单一性 

问题:
1.确定需要定义什么类型的指针?从二维数组的本质出发 
   &a[0]
    //a[0]  --- int[3]
    //&a[0] --- int[3] * 
    //c语言中 不支持 int[3] *  
    //正确写法 int(*)[3]

int(*p)[3] = a; //p指向二维数组 a 
                //p的基类型 int[3]

*p <=> a[0] // 相当于是内部这个一维数组的数组名 
       (*p)[0] 
       *(*p+0) //**p

*(*(p+1)+1) <=> a[1][1]
*(*(p+i)+j) <=> a[i][j]       

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/950702
推荐阅读
相关标签
  

闽ICP备14008679号