当前位置:   article > 正文

c++基础三 (数组——指针)_c++ 数组指针

c++ 数组指针

数组:是一种数据结构,存放固定大小(类型相同)的数据,组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素

一维数组:

数组的声明:

数据类型  数组名 [数组大小];

  1. int a[5];
  2. double b[10];
  3. float c[30];

数组的初始化:

  • 初始化数据个数不能超过数组长度,不然数组越界
  • 可以省略数组长度
  • 为某个元素赋值,数组是从0开始计算 所以 不能大于 数组长度-1
  • 数据不够,系统会自动补零

数组的赋值: 

单个赋值:a[索引值]=数值;

多个赋值:用for循环

  1. int a[5]={1,2,3,4,5}//个数不能超过数组长度,不然数组越界
  2. int a[ ]={1,2,3,4,5} //可以省略数组长度
  3. //初始化全部为0
  4. int a[5]={00000};
  5. int a[5]={0};
  6. int a[5]={0*5};
  7. 赋值:
  8. a[2]=30;//单个赋值
  9. //用循环进行多个赋值
  10. int a[10];
  11. for(int i = 0; i < 10; i++)
  12. {
  13. a[i] = i + 10;
  14. cout << a[i] << endl;
  15. }

二维数组:

二维数组的声明:

数据类型  数组名 [行的数量][列的数量];  

  1. int a[5][10];
  2. double b[10][20];
  3. float c[30][40];

二维数组的初始化:

  • int a[5][5]={1,2,3,4,5}           个数不能超过 行数×列数,不然数组越界
  • int a[5][5]={{1,2},{3,4},{5,6}}  可以一行一行给出,更加直观
  • int a[ ][5]={1,2,3,4,5}              可以省略行数但不能省略列数

二维数组的赋值:

  • 单个赋值:a[2][4]=30
  • 多个赋值:for循环

数组的遍历:

  1. 正常的循环语句 for(;;)
  2. c++11新添加的遍历语句 for( :)

格式为:

for (auto i : 数组名)//用  i  来接收数组的数据
    {
        内容
    } 

  1. int a[10];
  2. for(int i = 0; i < 10; i++)
  3. {
  4. a[i] = i + 10;
  5. }
  6. //第一种
  7. for(int i = 0; i < 10; i++)
  8. {
  9. cout<<a[i]<<endl;
  10. }
  11. //第二种
  12. for (auto i : a)
  13. {
  14. cout << i << endl;
  15. }

字符串:

字符串有两种表达方式:

  1. 用字符数组表示
  2. string表示

字符数组:

字符串的结束标志为'\0',所以数组要多开一个空间存放'\0'

初始化:

  • char a[10]="asdfghj"
  • char a[]="asdfghj"   //系统计算大小   为8
  • char a[10]={'a','s',d','f',g',h','j'}
  • 以上3种都是初始化方式,后面都会添加'\0'

赋值: 

//错误的赋值,不能用数组名赋值

char a[10]; a="pppppppp";

char a[10];  a={'a','s',d','f',g',h','j'}

//用下表赋值

a[0]=10; a[1]='a';

常用的字符串函数:

strcpy(s1, s2) 复制字符串 s2 到字符串 s1
strcat(s1, s2) 连接字符串 s2 到字符串 s1 的末尾
strlen(s1)返回字符串 s1 的长度
strcmp(s1, s2)如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0(通过ASII码值比较大小)
strchr(s1, ch)返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置
strstr(s1, s2)返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置

 字符数组取长度符号对比:

  • sizeof(b)/sizeof(b[0])  这样会计算包括'\0'的长度
  • strlen()  只会计算真实数据的长度  所以   长度为 sizeof()-1

字符串的3种拷贝:

  1. strcpy(A,B):用B的字符串复制给A的
  2. memcpy(A,B,Size)把数组B中的Size个字符复制到A
  3. sprintf(A,输入格式)

注意事项:以上的A的容量都要>=B的容量,要能存的下B

  1. int main() {
  2. char a[10];
  3. char b[] = "bnmzx";
  4. strcpy(a, b);//strcpy的用法
  5. cout << a << endl;
  6. char c[10];
  7. memcpy(c, b, 6);//memcpy的用法
  8. cout << c << endl;
  9. char d[10];
  10. sprintf(d, "%c,%c,%c,%c,%c", b[0], b[1],b[2],b[3],b[4]);//sprintf的用法
  11. cout << d << endl;
  12. return 0;
  13. }

  1. int main() {
  2. char a[5];
  3. char b[] = "bnmzx";
  4. strcpy(a, b);//a的容量小于b的容量会报错
  5. cout << a << endl;
  6. char c[5];
  7. memcpy(c, b, 6);//c的容量小于b的容量会报错
  8. cout << c << endl;
  9. char d[4];
  10. sprintf(d, "%c,%c,%c,%c,%c", b[0], b[1], b[2], b[3], b[4]);//d的容量小于b的容量会报错
  11. cout << d << endl;
  12. return 0;
  13. }

 

在这里需要注意一个输出问题,cout是遇到'\0'结束的 ,当使用mempy时需要注意的事项,

  1. memcpy中的A容量要大于等于B容量大小
  2. SIze的大小最好和sizeof(B)的大小一致,不一致的话会导致乱码
  1. int main() {
  2. char c[10];
  3. char b[] = "bnmzx";//b的容量为6
  4. memcpy(c, b, 5);//5小于b的容量
  5. cout << c << endl;//cout要再到'\0'才会停止,会出现乱码
  6. return 0;
  7. }

 

  1. int main() {
  2. char c[10];
  3. char b[] = "bnmzx";
  4. memcpy(c, b, 6);//6等于b的大小
  5. cout << c << endl;//正常输出
  6. return 0;
  7. }

 

string:

 string是一个类,固定占用28个字节,string没有'\0'

初始化:

string  p="asdsafasfasf";

下面链接有详细用法

c++ string_旷工锁的博客-CSDN博客

指针:

 指针是一个变量,其值为另一个变量的地址,通过地址来访问数据

地址:都是一个十六进制表示的数

指针的格式:

类型  * 指针名 ; int *p;

  • *p代表数据
  •  p代表地址

初始化方式:

int a=20;

  •  int *p=&a;
  •  int *p; p=&a;
  1. int a = 20;
  2. int *p;
  3. p = &a;//把p指向a的地址
  4. cout<<p<<endl;//输出p的地址
  5. cout<<*p<<endl;//输出p的值

空指针

空指针的作用:防止指针指向随机的、不正确的、没有明确限制的地址,防止指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的(也就是野指针)

处理野指针的方法:

把指针变量赋为空指针:

  • 旧的方式  int *p=NULL;
  • 新的方式  int *p=nullper (最好使用这种方式)

指针的算术运算:

 指针可以使用++、--、+、-      数组名是常指针  不可修改

指针和数组之间的替换 

一维数组和指针:

  1. 数组名是数组的首地址
  2. 数组名是一个常指针 不可修改
  3. 可以对指针操作来访问元素

数组地址表示方法:

  1. 用数组名:  a==&a[0]     a+1==&a[1]      a+2==&a[2]......
  2. 用取地址符:&a[0]    &a[1]
  1. int a[10] = {0};
  2. int *p;
  3. p = a;p = &a[0];//这两种是等价的指针指向数组首地址
  4. 访问数组的方式:
  5. 1.直接访问数组
  6. a[5];
  7. 2.使用指针
  8. *p ==a[0]
  9. *(p+1)==a[1]
  10. 3.修改数组的值
  11. a[5]=10;
  12. *(p+5)=10;

const修饰的指针:

  • const int *p  ,int const *p2   指向常量的指针  (的值不能变,指向可以变)

  • int *const p3    指针常量  (值能变,指向不可以变)(&的本质)

判别方法:看const 位于 * 的位置

  1. const *  左边  常量指针
  2. * const  右边  指针常量

const int *p:int const *p2 :指向常量的指针

  1. int a[10] = { 0 };
  2. int b[10] = { 1 * 10 };
  3. const int *p = a;
  4. cout << *p << endl;
  5. *p = 20; // *p值不能改变(报错)
  6. a[0] = 2; //数组可以修改
  7. p = b; // 指向可以改变
  8. int const* p = a;
  9. *p = 20;//常量指针 值不能改变(报错)
  10. p = b; //常量指针 指向可以改变
  11. a[0] = 2; //数组可以修改

int *const p2 :( 指针常量 )

  1. int a[10] = { 0 };
  2. int b[10] = { 1 * 10 };
  3. int * const p = a;
  4. cout << *p << endl;
  5. *p = 20;//指针常量 值可以改变
  6. a[0] = 30;//数组的值可以修改
  7. p = b; //指针常量 指向不可以改变(报错)

指针数组和数组指针: 

1.指针数组: int  *p[10]== int *(p[10])  因为[ ]的优先级大于 * 所以p和[ ]结合

        指向:10个int 型的指针

2.数组指针: int (*p)[10]    相当于 int p[][10]  二维数组就是数组指针

        指向:数组为10个int型的元素 

3.二维数组拆解:

       a[i][j] =*(a[i]+j) = *(*(a+i)+j) =(*(a+i))[j] 

指针数组的使用:

  1. int a[10] = { 1,2,3,4,5,6,7,8,9 };
  2. int* p[10];//指针数组 含有 10个 int型指针
  3. p[0] = &a[0]; //p[0]指向a[0]的地址
  4. p[1] = &a[1]; //p[1]指向a[1]的地址
  5. cout << *(p[0]) << endl;//输出a[0]的值
  6. cout << *(p[0] + 1) << endl;//输出a[2]的值
  7. cout << *(p[1]) << endl;//输出a[2]的值
  8. 存储一个字符串列表
  9. const char *p[4] = { "aaaa","bbbb","cccc","dddd" };
  10. for (int i = 0; i < 4; i++)
  11. {
  12. cout << p[i] << endl;//输出字符串
  13. cout<<*(p[i])<< endl;//输出单个字符
  14. }

 数组指针的使用:

  1. a+i == p+i       
  2. a[i] == p[i] == *(a+i) == *(p+i)
  3. a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)

地址表:

  1. int main()
  2. {
  3. int a[5][5] = {0,1,2,3,4,5,6,7,8,9};
  4. int(*pa)[5];//数组指针
  5. pa = a;
  6. cout << pa << endl; //代表a[0][0]的地址
  7. cout << *pa << endl; //代表a[0][0]的地址
  8. cout << pa[0]+1 << endl; //代表a[0][1]的地址
  9. cout << pa +1<< endl; //代表a[1][0]的地址
  10. cout << **pa << endl; //代表a[0][0]的值
  11. cout << a[0][0] << endl; //代表a[0][0]的值
  12. cout << *(pa[0]) << endl;//代表a[0][0]的值
  13. cout << *(pa[0] +1) << endl;//代表 a[0][1]的值
  14. cout << pa[0][1] << endl; //代表 a[0][1]的值
  15. cout << a[0][1] << endl; //代表 a[0][1]的值
  16. system("pause");
  17. return 0;
  18. }

多级指针:

int a=10;    int *p= &a;   int **q=&p;

指向同一块区域

字符数组和字符指针:

  • 字符数组:和普通数组用法一样,char a[]="zxcvbnm";
  • 字符指针:  指向字符串的指针,      char* p="sdasdasda"'

两者的区别:

  1. 存储位置不同,字符串指针放在常量区
  2. 字符数组 :可读可修改       字符指针:只能读不能修改

char数组名,char指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。

所以可以用指针名l

  1. //对这两个进行赋值
  2. char a[5], *p=a;
  3. 1.因为a是数组名,所以不能用a来赋值,可以用a的下标赋值
  4. a[1] = 10;
  5. for (int i = 0; i < 10; i++)
  6. {
  7. a[i] = i;
  8. }
  9. 2.可以用p来赋值
  10. *p = 'p';//单个赋值
  11. p = "pppppp";//因为字符串返回的是首地址,所以用p来接收

数组做形参:

  1. 用指针 
  2. 用已定义大小的数组
  3. 用未定义大小的数组

注意:给函数传递数组,数组会自动地退化为一个指向改数组首地址元素的指针。因此要同时传递数组的位置进入函数,比如起始位置或者终止位置。

  1. void text(int *a)
  2. {
  3. cout << a << endl;
  4. }
  5. void text(int a[])
  6. {
  7. cout << a << endl;
  8. }
  9. void text(int a[10])
  10. {
  11. cout << a << endl;
  12. }
  13. int a[10] = {1,2,3,4,5,6,7,8,9};
  14. text(a);

数组退化成指针:

  1.  数组作函数参数时,会把数组退化为指针
  2.  数组下标转换时会退化成 指针
  1. //做函数形参时
  2. void tect(char a[], char p[5])
  3. {
  4. cout << sizeof(a) << endl;
  5. cout << sizeof(p) << endl;
  6. }
  7. char a[5];
  8. char p[5];
  9. tect(a, p);// 结果为 4 4 把数组转化为指针
  10. //数组下标转换
  11. p[1] = *(p + 1);//当元素为p[1]时 编译器会转化为*(p + 1)
  • 任何指针都可以转化为 void *
  • void* 可以转化为任何指针

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

闽ICP备14008679号