00[VC++].04数组字符串指针.md

第四章 数组字符串指针

基于范围的for 循环

int a[]={1, 14, 4 ,4 ,78};
for(auto i:a)
{
 
}

字符数组

字符串数组的特殊性

    char str[45]="this is a string";
    char* str2="this is a string too";
    int a[45]={1,1,2,4,4,3};
    cout<<hex<<str<<endl;//this is a string
    cout<<hex<<&str[0]<<endl;//this is a string
    cout<<hex<<str2<<endl;//this is a string too
    cout<<hex<<&str[3]<<endl;//s is a string
    cout<<hex<<str2+3<<endl;//s is a string too
    cout<<hex<<a<<endl;//0041FD34
    cout<<hex<<&a[0]<<endl;//0041FD34
    cout<<hex<<&a[3]<<endl;//0041FD40
    cout<<dec<<sizeof a<<endl;//180----a包含了数组大小
    cout<<dec<<sizeof a[0]<<endl;//4

获取数组中元素个数

_countof( )

字符串输入

const int MAX=80;
char name[MAX];
cin.getline(name,MAX,'\n');//以最大量MAX(MAX-1)结束或者字符'\n'结束
//或者
cin.getline (name,MAX);//以最大量控制
cin>>name;//不控制,实际以'/n'控制

多维数组

数组在内存中的存储方式是使最右边的索引值快速的变化,二维数组实际上是一维数组的一维数组.例如夏利中的data[0],data[1]都是一维数组.
初始化:

double beans[12][10]={0.0};
int data[2][4]={
                                  {1,2       },
 
                                  {2,5,67,4}
 
                             };
 

指针

指针声明
long * pnumber;\\指向`long`类型的指针
long number=99;
pnumber=&number;
 
 
int * a,b;
int* a,b;
\\等同
int *a;
int b;
指针初始化
int number=0;
int * pnum=&number;
\\或者
int * pnum=nullptr;
\\增加检查
if(pnum==nullptr)
    cout<<"pnumber does not point to anything"<<endl;
 
if(!pnum)
    cout<<"pnumber does not point to anything"<<endl;

nullptr可以隐式转换为任何指针类型和bool类型

指向char类型的指针与字符数组区别

char*可以用字符串字面值初始化.将其视为字符串,以\0终止,(实际上是const char类型的数组)

char* proverb ="a miss is as good as a mile.";
const char p[]= "a miss is as good as a mile.";
cout<<proverb<<endl;

指向char类型的指针:本身是指针

字符数组:本身是数组,可以用_countof来确定长度,也可以用sizeof/sizeof

    char *pstr="sdfOIUYjndasdfJU Idfksde.";
    char astr[]="sdfOIUYjndasdfJU Idfksde.";
    cout<<"*pstr=\"sdfOIUYjndasdfJU Idfksde.\""<<endl;
    cout<<"astr[]=\"sdfOIUYjndasdfJU Idfksde.\""<<endl<<endl;
 
    cout<<"sizeof(pstr):"<<sizeof(pstr)<<"        "
        <<"sizeof(astr):"<<sizeof(astr)<<endl<<endl;
 
    cout<<"pstr hex: "<<hex<<pstr<<endl;
    cout<<"astr hex: "<<hex<<astr<<endl<<endl;
 
    cout<<"*pstr: "<<*pstr<<"        "
        <<"astr[0]: "<<astr[0]<<endl;
    cout<<"sizeof(*pstr):"<<sizeof(*pstr)<<"        "
        <<"sizeof(astr[0]):"<<sizeof(astr[0])<<endl<<endl;
 
    cout<<"*(pstr+0): "<<*(pstr+0)<<"        "
        <<"astr[0]: "<<astr[0]<<endl;
    cout<<"sizeof(*(pstr+0)):"<<sizeof(*(pstr+0))<<"        "
        <<"sizeof(astr[0]):"<<sizeof(astr[0])<<endl<<endl;
 
    cout<<"*(pstr+2): "<<*(pstr+2)<<"        "
        <<"astr[2]: "<<astr[2]<<endl;
    cout<<"sizeof(*(pstr+2)):"<<sizeof(*(pstr+0))<<"        "
        <<"sizeof(astr[2]):"<<sizeof(astr[0])<<endl<<endl;
 
    cout<<"(sizeof(pstr)/sizeof(*(pstr+3))): "<<dec<<(sizeof(pstr)/sizeof(*(pstr+3)))<<endl;
    cout<<"(sizeof(astr)/sizeof(astr[3])):   "<<dec<<(sizeof(astr)/sizeof(astr[3]))<<endl;
         cout<<"strlen(pstr): "<<strlen(pstr)<<"        "
        <<"strlen(astr): "<<strlen(astr)<<endl;
 

输出:

*pstr="sdfOIUYjndasdfJU Idfksde."
astr[]="sdfOIUYjndasdfJU Idfksde."
 
sizeof(pstr):4          sizeof(astr):26
 
pstr hex: sdfOIUYjndasdfJU Idfksde.
astr hex: sdfOIUYjndasdfJU Idfksde.
 
*pstr: s                astr[0]: s
sizeof(*pstr):1         sizeof(astr[0]):1
 
*(pstr+0): s            astr[0]: s
sizeof(*(pstr+0)):1             sizeof(astr[0]):1
 
*(pstr+2): f            astr[2]: f
sizeof(*(pstr+2)):1             sizeof(astr[2]):1
 
(sizeof(pstr)/sizeof(*(pstr+3))): 4
(sizeof(astr)/sizeof(astr[3])):   26
 
 
strlen(pstr): 25                strlen(astr): 25
 
 
 
请按任意键继续. . .
 
指针数组 常量指针 指向常量的指针
char * pstr[]= {"tan tanghua",
        "guo dinghua",
        "zhao lixiu",
        "zhang jingjing",
        "huo guorong",
        "li yuanyuan"  };

数组中各个指针初始化为li yuanyuan等字符串字面值的地址,字符串字面值的类型是const char数组

*pstr[0]="little finger";\\无法编译:无法从"const char [7]"转换为"char",不能将 "const char *" 类型的值分配到 "char" 类型的实体
*pstr[0]='x';\\可以编译,运行时崩溃

为了避免以上通过指针改内容,改进声明方法

const char * pstr[]= {"tan tanghua",
        "guo dinghua",
        "zhao lixiu",
        "zhang jingjing",
        "huo guorong",
        "li yuanyuan"      };

但是仍然可以合法的编写
pstr[0]=pstr[1];
上面两个指针指向同一个姓名,并没有改变指针数组元素指向对象的值,改变的是pstr[0]中存储的指针的值
为了避免修改指针中的地址,改进声明,注意const位置

const char * const pstr[]= {"tan tanghua",
        "guo dinghua",
        "zhao lixiu",
        "zhang jingjing",
        "huo guorong",
        "li yuanyuan"      };

1 指向常量对象的指针
不能修改被指向的对象,但是可以使指针指向其他对象

const char* pstring="some string";//看作一个整体,const ( ),也就是说 *psting无法修改
char a='A';
pstring=&a;//可以
*pstring="another";//不可以
*pstring='x';//不可以

2 指向某个对象的常量指针
不能修改指针中的地址,但是可以修改指针指向的对象

char* const pstring="some string";
char a='A';
pstring=&a;//不可以
*pstring="another";//不可以,因为char*+字符串自带 const 属性
*pstring='x';//不可以

3 指向常量对象的常量指针
指针和被指向对象都定义成常量,都不能修改

const char* const pstring="some string";
char a='A';
pstring=&a;//不可以
*pstring="another";//不可以
*pstring='x';//不可以

const char*是一个指向字符的指针,且这些字符是const
char* const是一个指向字符的const指针

sizeof操作符

cout<<(sizeof pstr)/(sizeof pstr[0]) 对于指针数组
cout<<(sizeof a)/(sizeof a[0])对于普通数组a[]={1,2,32,3};
cout<<sizeof b对于变量int b=4;
size_t long_size=sizeof(long);作用于类型名称,该类型占用的字节数量,圆括号

注意一下现象,sizeof用来统计元素个数时尽量连用(sizeof a)/(sizeof a[0])

int a[]={1,1,4,58,58,98,41,15};
cout<<"&a="<<hex<<a<<"   "<<sizeof a<<endl;//&a=0025FA14   20
cout<<"&a[0]="<<hex<<&a[0]<<"   "<<sizeof a[0]<<endl;//&a[0]=0025FA14   4
cout<<"sizeof a="<<sizeof a<<endl;//sizeof a=20
cout<<"sizeof a[0]="<<sizeof a[0]<<endl;//sizeof a[0]=4
cout<<"sizeof a/sizeof a[0]="<<(sizeof a)/(sizeof a[0])<<endl;//sizeof a/sizeof a[0]=8
cout<<typeid(sizeof a).name()<<endl;//unsigned int
 

指针和数组

double * pdata=nullptr;
double data[5];//*data=data[0],*(data+1)=data[1],*(data+2)=data[2]
pdata=data;//与pdata=&data[0]区别
pdata=&data[1];
pdata=pdata+1;//&data[2],*pdata=data[2]
统计字符串字符个数
char buffer[80]="sdfasdfasdfasdfasdfasdf";
char* pbuffer=buffer;
while(*pbuffer)//static_cast<int>('\0')=0
        pbuffer++;
cout<<typeid(pbuffer).name()<<pbuffer<<endl;\\char *
cout<<typeid(pbuffer-buffer).name()<<pbuffer-buffer<<endl;\\int
cout<<pbuffer-buffer<<endl;
 
 
//或者
int i=0;
while(*(pbuffer+i))
 
    i++;
 
cout<<i<<endl;
指针和多维数组

*指针数组是数组元素为指针的数组(例如 int p[3],定义了p[0],p[1],p[2]三个指针),其本质为数组
数组指针是指向数组地址的指针,其本质为指针

double * data[15];//定义一个指针数组,数组中有15个指针
 
 
double beans[6][5];
double *pbeans;
pbeans=&beans[0][0];//第一个元素的地址
pbeans=beans[0];//第一行的地址
pbeans=beans;//错误,类型不同
 
 
int a[4][5];
int (*p)[5]=a;

p是一个指针变量,它指向包含5个int元素的一维数组,此时p的增量以它所指向的一维数组长度为单位;

*p+i是二维数组a[0][i]的地址;

*(p+2)+3表示a[2][3]地址

*(*(p+2)+3)表示a[2][3]的值

等价:
beans[i][j]
*(*(beans+i)+j)
*(beans[i]+j)
(*beans+i)[j]

动态内存分配

一个new一定要对应一个delete

double * pvalue=nullptr;
pvalue=new double;
*pvalue=999.0;
//或者
pvalue=new double(999.0);
//或者
double * pvalue=new double(999.0);
 
 
delete pvalue;
pvalue=nullptr;
为数组动态分配内存

数组动态类型分配最好用size_t类型来分配数组大小

pstr=new char[20];
delete [ ] pstr;
pstr=nullptr;
 
 
long *p=nullptr;
int max;//最好用size_t类型
cin>>max;
p=new long[max];
//而对于数组类型
long data[max];//出错,必须是常量
 
 
//动态的分配
double *value=new double[5];
double *temp=new double[another];
 
for(int i=0;i<another;i++)
{
    *(temp+i)=*(value+i);
}
delete [] value;//删除分配
value=temp;//重新
temp=nullptr
多维数组动态分配
double (*pbeans)[4]=nullptr;
pbeans=new double [3][4];
//销毁
delete [] pbeans;
pbeans=nullptr;

使用引用

引用分为两种:l value引用rvalue引用,lvalue引用是别名而非指针,声明时必须指出对应的变量,与指针不同,我们不能修改引用使其表示另一个变量.

long num=0L;
long & refnum=num;
//对于常量
int & refData=5;//wrong
const int & refData=5;

基于范围for循环中使用引用

//1 t变量没用引用数组元素,只是引用了其值,所以不能用他修改元素
for(auto t:nums)
{
    sum+=t;
 
    ++count;
 
}
//2 使用引用修改元素,避免时间一些成本很高的复制操作
const double F2C=5.0/9.0;
for(auto & t:temperature)
    t=(t-32)*F2C;
//3数组的引用
int a[5]={0,2,3,45,6};
int (&b)[5] = a;
for(int i = 0; i < 5; i++)
     cout<<b[i]<<endl;
cout<<sizeof(b);  //20

字符串的库函数

标准库提供的cstring头文件中包含操作**以空字符结尾的字符串(null-terminated string)**的函数.
strlen(),wcslen()确定以空字符结尾的字符串的长度,size_t类型的返回值,计算空格
strnlen(),wcsnlen()更安全的字符段长度计算,对于外部来源

strcat(),wcscat()拼接以空字符结尾的字符串,第一个参数必须有足够的空间容纳两个字符串
strncat(),wcsncat()增加第三个参数指定附加字符个数,并在末尾加空字符
strcat_s()wcscat_s()安全的字符串链接,不需要输入以空字符结尾

strcpy(),wcscpy()复制以空字符结尾的字符串,将字符串从源位置复制到目标位置
strcpy_s(),wcscpy_s()更安全的复制

strcmp(),wcscmp()比较以空字符结尾的字符串,比较第一对不同的字符代码来确定

strspn(),wcsspn()搜索以空字符结尾的字符串,搜索字符串中不包含在给定集合中的第一个字符的索引
strstr()搜索以 空字符结尾的字符串,返回第一个字符串中第二个字符串的第一个位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值