• 数组、指针和字符串


    刚刚结束了第六章的学习,这里结合一下老师发的ppt和大纲外加教材来小小的自我总结一下

    第六章 数组、指针和字符串

     

    6.1数组

    •  数组的初始化时,第一维的下标个数可以不用显式说明:

    int a[2][3]={1,2,3,4,5,6};

    int a[][3]={1,2,3,4,5,6};

      上面两种等价。

    • 数组作为函数参数

     

    1 void test(int a[][4],int r){
    2        a[0][0]=10;      
    3 }
    4 int main(){
    5        int b[3][4]={1};
    6        test(b,3);
    7 }

     

      与普通的函数参数不一样,这个时候是传递了数组的地址,所以函数中进行的改变,实际数组的元素也会发生改变

    • 对象数组

      声明和访问形式

    类名 数组名[下标表达式];

    数组名[下标表达式].成员名

       例如:

     

    location a[2]={location(1,2),location(3,4)};
    cout
    <<a[1].x<<","<<a[1].y;

     


     

     

    6.2指针

       指针这里越过基本概念,大概知道指针是通过地址指向目标就行,通过实敲代码来理解最好.

      我把几乎所有知识点都敲到了一个代码里面,下面的各段代码有时候需要结合起来看。

    6.2.3 * &

      * 是指针运算符,也是解析 

      &是取地址运算符

    6.2.4.1 指针的赋值

     1     int a;
     2     int b[]={99};
     3 /*    int *ptr;
     4     ptr=&a;
     5 */
     6     int *ptr=&a;//这两种定义的效果相同,
     7     //ptr是储存的地址,只有定义的时候可以这样定义,改变的时候要把地址给ptr,值给*ptr 
     8     
     9     int *p=b;//数组名称实际上是一个指针常量,所以可以直接给
    10     //这种方式也可以 
    11 /*    int *p;    p=b;     */
    12 
    13     a=10;
    14     cout<<"a="<<a<<endl;
    15     //*ptr++;//这样得出来的指针所指的值不对,a的值也没有改变 
    16     *ptr+=1;//这样以后指针对应的a的值改变了 
    17     cout<<"a="<<a<<endl;
    18     cout<<"*ptr="<<*ptr<<endl;//输出的是地址上的那个值 
    19     cout<<"ptr="<<ptr<<endl;//输出的只是地址 
    20     cout<<"*p="<<*p<<endl;
    21     cout<<"p="<<p<<endl;

     

    6.2.4.2 const相关的指针

        /*
        -----------------------------------------------------------------------------------
        */
        cout<<endl<<"----------常指针知识点:------------"<<""<<endl;
        /*注意区分指向常量的指针 和 指针类型的常量*/ 
        const int *p1=&a;//指向常量的指针,代表地址的p1本身可以改变,而指向的值不能改变 ;弱常指针 
        int *const p2=&a;//指针类型的常量,代表地址的p2本身是常量不能改变,而指向的值依然是变量; 强常指针
        int c=108;
        cout<<"*p1="<<*p1<<"  a="<<a<<endl;
        p1=&c;
        cout<<"*p1="<<*p1<<"  a="<<a<<"   c="<<c<<endl;
    /*    *p1=110;    此句话会出错,因为这是指向常量的指针*/
    /*    p2=&c;此句话也会出错,这是指针类型的常量,指针本身所指向的地址不能改变,此时地址还是a的地址*/
        cout<<"*p2="<<*p2<<"  a="<<a<<endl;
        *p2=19;
        cout<<"*p2="<<*p2<<"  a="<<a<<endl;

     

    6.2.4.3 void类型的指针

     1 /*
     2     -----------------------------------------------------------------------------------
     3     */
     4     cout<<endl<<"----------void类型指针------------"<<""<<endl;
     5     void *pv;//但是可以声明void类型的指针 
     6     //void voidobject  不能声明void类型的变量 
     7     int i=5;
     8     pv=&i;
     9     int *pi=static_cast<int *>(pv);
    10     //这是强制转换类型,把void指针转换为int指针赋值给pi 
    11     cout<<"*pi="<<*pi<<endl;
    12     cout<<" pi="<<pi<<endl;
    13     cout<<" pv="<<pv<<endl;//pi pv地址一样,只是指针类型不一样 
    14     //cout<<"*pv="<<*pv<<endl;
    15     //任何类型的指针都可以赋值给void类型的指针变量
    16     //void类型指针一般只在指针指向的数据类型不确定时候使用

     

    6.2.5指针运算

     1   /*
     2     -----------------------------------------------------------------------------------
     3     */
     4     cout<<endl<<"----------指针的运算------------"<<""<<endl;    
     5     int *pp;
     6 /*    pp+n; 指针pp后方第n个数的地址 
     7     pp++;指针pp后方第1个数的地址 
     8     pp--; 指针pp前方第1个数的地址 
     9 */
    10     //*(pp+1)这是pp指向位置后第一个数的内容
    11     //等同于 pp[1]        *(pp-1)  =   pp[-1]
    12     //空指针
    13     pp=0;
    14     pp=NULL; //空指针不指向任何地址
    15     /*
    16     同类型的指针可以做关系运算 > < >= <= == !=
    17     可以与空指针(0 NULL )做关系运算
    18     多个关系运算可以构成逻辑运算    
    19     */ 
    20     int ap[5]={0,1,2,3,4};
    21     pp=ap;int *qq=(ap+3);
    22     cout<<"qq-pp="<<qq-pp<<endl;//指针做减法运算,qq到pp相隔了三个整型数据 
    23     //cout<<"qq+pp="<<qq+pp<<endl;没法做加法运算 
    24     cout<<"ap[0]=*pp="<<*pp<<endl;
    25     (*pp)++;
    26     cout<<"ap[0]=*pp="<<*pp<<endl;
    27     
    28     ap[1]==*pp++;
    29     ap[2]==*(pp++);//*pp++ *(pp++)等效,
    30     //因为++后置优先级更高,都是先pp++ ,地址变化,再取指针
    31     ap[2]==*qq--;
    32     cout<<"pp="<<pp<<"  qq="<<qq<<" (ap+2)=&ap[2]="<<&ap[2]<<endl; 
    33     cout<<"*pp="<<*pp<<"  *qq="<<*qq<<" ap[2]="<<ap[2]<<endl; 
    34     

     

     

    • 举例子例如定义了*p=&a;

      p只是储存了a的地址,*p才是a所代表的值,p++或者对p进行运算都不能改变a,只是改变*p所指向的值。

      这个地址的运算在数组里面有大用处,因为数组元素的地址是连续的。

    • 空指针的地址是0或者NULL

    6.2.6 用指针处理数组元素

     1     /*
     2     -----------------------------------------------------------------------------------
     3     */
     4     cout<<endl<<"----------指针处理数组元素------------"<<""<<endl;     
     5     int array[5]={0,1,2,3,4};
     6     //array == &array[0] == &array  数组名其实就是一个指针变量
     7     //array+3 == &array[3]
     8     *array==array[0];
     9     *(array+1)==array[1]; 
    10     for(int *pa=array;pa<(array+5);pa++){
    11 //    for(int *pa=&array[0];pa<&array[5];pa++)与上一行等价
    12 /*  pa指向了数组每个元素的地址,数组的地址是连续的,
    13     所以是小于array【5】的地址,pa++是依次后移一个位置 */ 
    14         cout<<*pa<<' ';    
    15     }cout<<endl;

     

    • 教材在6.2.4就讲过,数组的名称实际上就是一个不能被赋值的指针,即指针常量,为上文提到的强常指针(不能改变地址,但是可以通过指针改变所指向的值)

      array=&array=&array[0]  数组名这个指针指向了第一个元素(挺重要的,之后运用挺多)

      array+i=&array[i]  数组的运算

    6.2.7指针数组

     1     /*
     2     -----------------------------------------------------------------------------------
     3     */
     4     cout<<endl<<"----------指针数组------------"<<""<<endl;
     5     int l1[]={1,0,0};
     6     int l2[]={0,1,0};
     7     int l3[]={0,0,1};
     8     int *ps[3]={l1,l2}; 
     9     ps[2]=l3;
    10     cout<<"ps[0]="<<ps[0]<<"  *ps[0]="<<*ps[0]<<endl; 
    11     cout<<"l1="<<l1<<"  &l1="<<&l1<<endl;
    12     cout<<"ps[0][0]="<<ps[0][0]<<"  l1[0]="<<l1[0]<<endl;
    13     cout<<"&ps[0][0]="<<&ps[0][0]<<"  &l1[0]="<<&l1[0]<<endl;
    14     //ps[0]=l1=&l1   ps[1]=l2=&l2;
    15     cout<<"*(ps[0]+1)="<<*(ps[0]+1)<<" l1[0+1]="<<l1[1]<<endl; 
    16     //ps[i][j]  ==  *(ps[i]+j) 
    17     int array2[3][3]={{11,12,13},{21,22,23},{31,32,33}};
    18     //*(*(array2+i)+j)  ==  array2[i][j] 

     

    数组指针并不是很难,

    实际就是一个数组,只不过每一个元素都是指针。

    语法形式为:

    数据类型 *数组名[下标表达式]

    只不过要注意区分数组指针和指针数组的概念(此知识点之后补上)

     

    6.2.8 用指针作为函数参数

     

    1     /*
    2     void fun1(int a,int b);
    3     void fun2(int *c,int *d);
    4     int p,q,e[],f[];
    5     fun1(p,q);
    6     fun2(&p,&q);
    7     fun2(e,f);
    8     //fun1不会改变变量本来的值,变的只是形参,fun2的形参是指针,会改变变量。 
    9     */ 

     

    6.2.9 指针型函数

    语法形式

    数据类型 *函数名(参数表){
    函数体;
    }

    基本没有深入讲相关知识点,只是提了一下,所以这里也一笔带过

    6.2.10 指向函数的指针

     1 void print(double ){
     2     cout<<"A test"<<endl;
     3 }
     4 void write(double data){
     5     cout<<"this test is "<<data<<endl;
     6 }
     7 double message(double data){
     8     return data;
     9 }
    10 class node{
    11     public:
    12         int n,m;
    13         node(int n1){
    14             n=n1;
    15         };
    16         void print();
    17     private:
    18         int b;
    19 };
    20 void node:: print(){
    21     cout<<"6666"<<endl;
    22 } 
    23 int main(){
    24     cout<<endl<<"----------指向函数的指针-----------"<<""<<endl;
    25     //数据类型 (*函数指针名)(形参表)
    26     //函数指针名=函数名;   函数指针名=&函数名   两种用法相同 
    27     void(*pf1)(double);
    28     double(*pf2)(double);
    29     print(3.14);
    30     pf1=&print;
    31     pf1(3.14);
    32     pf1=&write;
    33     pf1(3.14);
    34     //pf1=&message;  有错误,这是void类型的函数指针 
    35     pf2=message;
    36     cout<<pf2(3.14)<<endl;

     

    语法形式:

    数据类型 (*函数指针名)(形参表)

    这里还涉及到了typedef 这个好像在之前章节讲过,还没看,先放这,一会复习前面章节再补上

    6.2.11.1对象指针

      感觉和数据指针函数指针这些都大同小异

      用途:多态的实现

      Ps:定义对象的时候会调用类的构造函数,而指针不会。

      可以通过指针来调用对象的成员,不过有特殊形式

    对象指针名->成员名

      Or

    (*对象指针名).成员名

     

    6.2.11.2this 指针

    这个指针是直接隐藏于类的每一个非静态成员函数里面的

    主要是知识点,教材上也没有实际运用

    据说函数形参名称于类的数据成员名称一样,可以用这个区分

    大概是

    Class node{

           Public:

                  Int n;

                  Void print(int n){

                         This->n=n;}

    }

    6.2.11.3指向类的非静态成员指针(指向成员的指针)

           不考这个知识点,暂时空出来以后再说。

     


     

    6.3动态内存

     1 class node{
     2     public:
     3         node(){
     4             cout<<"调用了默认构造函数"<<endl; 
     5         }
     6         node(int x,int y){
     7             this->x=x;
     8             this->y=y;
     9             cout<<"调用了构造函数"<<endl;
    10         }
    11         ~node(){
    12             cout<<"调用了析构函数"<<endl; 
    13         }
    14         void move(int newx,int newy);
    15     private:
    16         int x,y;
    17 };
    18 
    19 inline void node::move(int newx,int newy){
    20     x=newx;y=newy;
    21 }
    22 
    23 int main(){
    24     int *p1=new int(6);
    25     int *p2=new int();//int *p2=new int;
    26     cout<<"p1="<<p1<<" *p1="<<*p1<<endl;
    27     delete p1;
    28     delete p2;
    29     *p1=1;//delete删除了指向的内存空间,指针本身还在 
    30     node *pn;
    31     pn=new node;
    32     delete pn;
    33     pn=new node(1,1);
    34     delete pn;
    35     cout<<"----------申请多个--------"<<endl;
    36     //申请多个动态对象数据
    37     node *p=new node[2];
    38     p[0].move(1,2);
    39     p[1].move(3,4); 
    40     delete []p;
    41     return 0;
    42 }

    建立和删除堆对象使用运算符 new 和 delete

    (在程序里面用了一下this指针,没有出错,真好)

     


     

    6.5深复制和浅复制

    啊这部分文字好多(巨懒)

    咕咕咕

     


     

    6.6 字符串

    • string是c++库黎明预定义的类,可以直接使用
    • 字符串是一个字符型的数组,以 结尾
    • 字符串之间的大小比较:字典序
    • 读入:cin getline

      cin读入字符串会以空格 tab制表符 回车作为分隔符

      getline读入一整行,以回车作为分隔符

    getline(cin,字符串名);
    
    getline(cin,字符串名,分隔符);   getline(cin,s1,',');

      还有gets get cin.get cin.getline getchar scanf等很多读入方式,之后来做个整合。

     


     

    #6.4 vector(老师未讲)

    定义形式:

    vector<元素类型>数组对象名(数组长度);

    调用方式和数组一样的 a[i],比较有用的是里面的size

    a.size()就是数组a的大小

    课本没有讲太多的用法

    诸如此类还有 string pair vector map 等,也等以后一同梳理(咕咕咕

  • 相关阅读:
    codefoeces problem 671D——贪心+启发式合并+平衡树
    bzoj 1598: [Usaco2008 Mar]牛跑步
    bzoj 1050: [HAOI2006]旅行comf&&【codevs1001】
    codefoeces 671 problem D
    利用FFMPEG以及EasyRTMP实现读取H.264文件推RTMP视频流的两种方式
    视频流拉转推工具对比:EasyRTSPLive和FFMPEG拉转推效果对比
    TSINGSEE青犀视频Webrtc实时通信的构建流程:PeerConnection对等通信的实现方式
    TSINGSEE青犀视频云边端架构产品编译Intel Media SDK 编译报错error"SSE4.1 instruction set not enabled"
    H.265编码视频在web网页实现无插件播放,应该通过软解码还是硬解码?
    【案例分析】EasyDSS+EasyCVR融合共享解决方案
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/12845724.html
Copyright © 2020-2023  润新知