1、数组指针声明的时候不用初始化,声明以后就指向数组的首地址了,以后不允许改变,所以,数组指针可以认为是一个常量,一旦赋值就不能改变
2、char数组
(1)打印char数组的名字即打印数组的内容
(2)对于字符数组,'\0'是结束标志
字符 '\0' = 数组0 可以认为字符'\0'的ASCII码就是0
要保存5个字符,就要把字符数组长度声明为6
(3)strcpy()和memset()
给一个字符串数组赋值 strcpy(),自动为字符串补 '\0'
在使用strcpy之前,要调用memset(str,0,sizeof(str));初始化一片内存
str -> 初始化内存的起始位置
0 -> 初始化的值 (初始化为0,清除垃圾数字)
sizeof(str) -> 初始化空间的大小
(4)strlen(str)
计算实际存储的字符个数,不包括'\0'
(5)strcmp(str1,str2)
比较2个字符串是否相等
实际比较的两个字符串的ASCII码的大小,返回0则内容一样
(6)字符串的拆分 strtok(a,b);
a、被拆分的字符串名字,当此处是NULL时,表示要拆分的不是新串
b、分隔符号
此函数调用一次,拆分一次
当此函数返回NULL时,则表明拆分完毕
"Hello World"叫字符串常量,存储在data数据区里,类型就是char*
其值是一个地址,指向数据区里的一块空间
数据区里的空间保存的内容就是"Hello World"
char line[50]; strcpy(line,"1:liucy:20:male"); char *p = strtok(line , ":"); //p指针指向的变量 cout << p << endl; while(p != NULL){ p = strtok ( NULL , ":" ); cout << p << endl; }
(7) strcpy(name,"1234"); //name是个变量,可以改变
strcpy(p,"1234"); //p是个指针,指向一个字符串,是常量,不能改变
p = "1234"; //这样是正确的
指针指向的是常量,不能通过指针改其值,若指向变量,则可以通过指针改变变量的值
(8)字符串连接 strcat(sub,"world");
连接条件:sub字符串数组的剩余长度要大于连接的字符串长度
char *p = "Hello";
strcat(p,""World); //error 指针指向一个常量,不能改变,所以指针后面不能添加东西
3、通过指针传递参数
通过传递地址。改变变量的值
#include <iostream> using namespace std; void fn (int *pa){ *pa = 2 * (*pa); //*pa是指针pa指向的变量的值,在此做的操作,会对变量造成永久的改变 } int main(){ int a = 100; fn(&a); //把a的地址传个fn函数 cout << a << endl; return 0; }
4、课堂练习
字符串 “1:huxinzhe:20:male”
要求:声明一个结构
Person{
int id;
char name[50];
int age;
char gender[10];
}
拆分赋值 提示:atoi可以把字符串转换成int型
#include <iostream> #include <string.h> #include <stdlib.h> using namespace std; struct Person{ int id; char name[20]; int age; char gender[10]; }; int main(){ Person per; char line[50]; while(true){ cout << "enter a string>"; cin>>line; if(strcmp(line,"exit")==0) break; char *p = strtok(line , ":"); per.id = atoi(p); p = strtok(NULL , ":"); strcpy(per.name,p); p = strtok(NULL , ":"); per.age = atoi(p); p = strtok(NULL , ":"); strcpy(per.gender,p); cout <<"per.id = " <<per.id << endl; cout <<"per.name = " <<per.name << endl; cout <<"per.age = " <<per.age << endl; cout <<"per.gender = " <<per.gender << endl; } return 0; }
5、内存管理
堆(heap):动态的内存申请与释放
堆空间不能通过像( 数据区,栈)变量访问空间,要使用指针保存地址
(1)堆空间的管理 new / delete
new int
new Person
new 操作符返回值是地址,用指针保存
int *p = new int; //在堆空间中申请4个字节
*p = 100; //赋值
delete p; //释放空间
(2)动态申请空间,对内存的使用变的方便,能更好的控制对内存的占用
动态内存的指针不能重复赋值,这样会造成内存丢失
释放空间后,还可以通过指针访问原来的数据。
释放空间后,还可以再次通过指针赋值,释放的意思就是表示曾经申请的内存的标记位更改,别人可以使用
这样会造成过期的指针更改重要数据,建议在释放指针以后 ,把指针赋值为NULL ,确保数据安全
delete p ;
p = NULL :
(3)在申请空间的同时初始化
int *p = new int(123); 申请4个字节大小,保存数字“123”
(4)int *p = new int[10]; 一次在堆里申请10个int,并且申请的内存是连续的。
*(p+1) , p[1] 都能取到下一个数据
此时的*p就是第一个元素的值
在释放的时候 delete[] p; p = NULL; 确保释放的是多个指针
(5)在堆空间里申请结构
Person *p = new Person;
p->id = 1;
// (*p).id = 1;
6、 传递参数
最好传地址,节省内存(因为不用进行入栈,出栈操作,直接用指针访问数据)
在参数前加const,可避免在函数内部对数据进行非法修改
当一个数组做参数时,编译器会自动把数组的首地址传个函数
所以在函数内部对数组的更改,就是通过指针对数组中元素的永久性更改
7、数组,存数据个数不限,通过一个函数insert()存数据,disp()打印数组