c佳佳笔记

本文详细介绍了C++编程的基础知识,包括计算机组成原理、程序设计结构如分支和循环,以及数组、指针和函数的使用。特别强调了输入输出操作、算术和赋值运算,还探讨了内存管理和数据类型转换。此外,文章还涵盖了排序算法和查找方法,如顺序查找、二分查找、选择排序和冒泡排序,以及动态内存分配和字符串处理。
摘要由CSDN通过智能技术生成

目录

cap1绪论

1.2  计算机组成

cap2通过例子学习

2.1程序的组成

2.2变量和常量

2.3 输入和输出

2.4 算术和赋值运算

cap3分支程序设计

3.1关系表达式

3.2逻辑表达式

3.3if语句

3.4switch语句

cap4循环程序设计

4.1计数循环

4.2break和continue语句

4.3基于哨兵的循环

4.4枚举法

4.5贪婪法

cap5数组

5.1一维数组存

5.2、排序和查找

顺序查找

二分查找

选择排序法

气泡排序法

5.3二维数组

5.4字符串

cap.6过程封装-函数

6.1  函数的用途与定义

6.2  函数的使用

6.3  变量的作用域与存储类别

6.4函数变量为数组

6.5内联、重载、模板、递归

6.5.1内联函数

6.5.2重载(好用的捏

6.5.3模板(好用的捏

6.5.4递归(简化的捏

cap7指针

7.1指针简介

7.2动态内存分配

7.3字符串再讨论

7.4指针数组 与多级指针

cap1绪论

1.2  计算机组成

  • 计算机=软件+硬件
  • 硬件:输入设备、输出设备、存储器、控制器、运算器。(控制器+运算器=CPU)
  • 存储器:内存的最小单元是bit,一个bit存储一个二进制位。一般8个bit组成一个byte,若干个byte组成一个word。

cap2通过例子学习

2.1程序的组成

  • 注释://   or   /*   */
  • 编译预处理:#include <iostream> (库包含)or #define pi 3.14(宏定义)(以#开头的指令,不需要以分号结尾)#include <cmath>(数学运算)
  • 名字空间:using namespace std;
  • main函数:函数头+函数体
  • 换行:endl or \n
  • 绘表:\t

2.2变量和常量

命名规则

  • 名字必须以字母或下划线开头。
  • 名字中的其它字符必须是字母、数字或下划线,不得使用空格或其它特殊符号
  • 名字不可以是系统的关键字,如:int, double, for, return等保留字,它们在C++语言中有特殊用途

变量初始化方式: int num1 = 1;   int num2(2);   int num3 = {3};  

数据类型

整型

长整型:无符号unsigned long、有符号long int / long

标准整型:无符号unsigned int、有符号int

短整型:无符号unsigned short int、有符号short int / short

实型

123e2=12300(①尾数不能为空 e3 →1e3   ②指数必须为整数   2.5e2.3是非法的)

实型常量都被作为double型处理,如要作为float型数据,可在数值后加F或f,例如,1.23F,1.23f

单精度:float

双精度:double

长双精度:long double

字符型:char   ( ‘a’, ‘S’, ‘2’等用一对单引号括起来的数据称为字符常量。)(双引号括起来的是字符串。)toupper(ch)转大写;a97A65048;

askⅡ表(A65,a97,048)

布尔型:bool

类型转换规则:

bool、char和short这些非标准的整数在运算前都自动转换为int。

int和float运算时,将int转换成float。

int和long运算时,将int转换成long。

int和double运算时,将int转换成double。

float和double运算时,将float转换成double。

数据转换规则:

实型转换成整型时,舍弃小数部分

整型转换成实型时,数值不变,但表示成实数形式

字符型转换成整型时,不同编译器有不同处理方法(无符号或有符号数)

布尔型转换成整型时,true为1,false为0

整型转换成字符型时,直接取整型数据的最低8位

想使4/5的结果是0.8:4.0 / 5或4 / 5.0  or用强制类型转换  z = (double)x / y; 

原码、反码、补码

可以给一个类型重新命名:typedef 原名 现名    →    typedef  int  INTEGER

占用空间:sizeofxx

常数:#define PI 3.14159          const  double  PI = 3.141592;

2.3 输入和输出

cin >> 

用回车(↙)结束

一般用空白字符(空格、制表符和回车)分隔多个输入数据

cin.get(ch)  or   ch= cin.get()

从键盘接收一个字符,可以接收任意的字符,包括空白字符

cout<<

2.4 算术和赋值运算

算术运算符:+     -      *       /    %

优先级:高  *  /  %,低  +  -

结合性:左结合(=是右结合)

复合赋值运算符:+=,-=,*=,/=,%=

自增、自减运算符:

cap3分支程序设计

3.1关系表达式

关系运算符:

<   

<=

>

>=

==易错

!=

tips:

前四个的优先级大于后两个

左结合。(从左向右结合)

关系表达式:表达式 关系运算符 表达式

tip

表达式可以是算术表达式(a+b)、赋值表达式(a=b)or关系表达式(a>b)

优先级算术>关系>赋值

e.g a+b>c-3

3.2逻辑表达式

逻辑运算符:

!非(一元)

&&与(二元)

||或(二元)

tip

优先级!>&&>||

逻辑运算符的运算对象应该是bool型,都会转为0和1

a&&b ab都是真才是真,有一个错就是错

a||b ab有一个真就是真,全错才为错

e.g 0<x<10  0<x&&x<10

短路求值

3.3if语句

if语句的格式

1 if () xx;

2 if () xx;

else xx;

if语句的嵌套

else与最近的if在一起

?:运算符

()?xx:yy  赋值很好用;或者输出的时候使用flag

cout<<(flag?1or2);

3.4switch语句

switch(表达式) {

case 结果1:执行语句; break;

 case 结果2:执行语句; break;

 ...

default:执行语句; break;

 }

!!!!

①switch语句是不见break就会将下面的语句都执行一遍的!!!xXY这样

②switch若是省略了后面的语句,则是跟下面碰到的第一个语句执行。

cap4循环程序设计

4.1计数循环

for语句

for(i=0;i<n;++i){

}

tip

别忘了定义i

for循环的嵌套

范围for循环

for(int i:{1,3,4})

4.2break和continue语句

break直接退出

continua 结束当前循环,进入下个循环

4.3基于哨兵的循环

while语句

while(){

xx

}

do{

xx;

}while ();

4.4枚举法

九九乘法表

4.5贪婪法

cap5数组

5.1一维数组存

1、数组元素是有序的、同类的

2、格式:int myarray[10]

※[]中元素个数必须是数字,不可以是变量,如果想全部更改的话,可以用

const int num=10;

#define num 10

 int n=10;  int myarray[n];是错的

3、数组中的元素

  • 初始化的时候没定义的默认为0
  • 单独使用一个元素用 myarray[0]来,这里的0是下标下标可以是数字也可以是变量注意0指的是第一个元素!
  • 数组的输入和输出--for循环

4、数组的内存

  • 数组名中存放的是该数组的起始地址
  • 定义数组就是定义了一块连续空间
  • 空间的大小=元素数*每个元素所占的空间大小。
  • my[3]的地址=初始地址+4*4
  • 在int x[10]中引用x[10]是正确的,只是会对下一个地址处理。
 for(int i=0;i<10;i++)
    {
        cout<<"请输入第"<<i<<"个数据";
        cin>>myarray[i];
    }

    for(int a=0;a<10;a++)
    {
        cout<<myarray[a]<<" ";
    }

que1、求十个数的最大数

 int allnum[10];
    int max=0;
    for(int i=0;i<10;i++)
    {
        cin>>allnum[i];
        if(allnum[i]>max) max=allnum[i];
    }
    cout<<max;

ques2:输入一串数字,求里面各个字母出现的次数。

  int zimu[26]={0};
    char juzi;
    for (int i=0;;)
   {
    juzi=cin.get();//如果是cin>>juzi;就无法存入回车然后结束循环了
    juzi=toupper(juzi);
    if(juzi<'A'||juzi>'z') break;
    ++zimu[juzi-'A'];
   }
   for(int a=0;a<26;a++)
   {
    cout<<zimu[a]<<" ";

ques3如何探测一个数组的长度?

int a[10];
cout<<sizeof a;

q4如何构建一个不定长度的数组?

5.2、排序和查找

顺序查找

被查找的数存放在一个数组中。   从数组的第一个元素开始,依次往下比较,直到找到要找的
元素为止。如在一整数数组中查找元素x的存储位置。
int zu[]={1,3,4,2,5,1,6,2,4};
    cout<<"input what you want";
    bool flag=1;
    int a;
    cin>>a;
    for(int i=0;i<9;i++)
{
    if(zu[i]==a) cout<<i,flag=0;
}
    if(flag) cout<<"not found!";

二分查找

过程:
设定查找范围的上下界:lh=0, rh=9(left,right)
找出中间元素的位置:mid = ( lh + rh ) / 2
比较中间元素与欲查找的元素 key
key 等于中间元素,则 mid 就是要查找的元素的位置;
如 key > 中间元素, 修正查找范围为 lh = mid + 1到 rh;
key < 中间元素, 修正查找范围为 lh 到 rh = mid - 1
lh > rh,则要查找的元素不存在,否则返回第二步.
 int zu[]={2,3,4,5,6,7,8,9,10,11};
    cout<<"input what you want";
    bool flag=1;
    int a;
    cin>>a;
    int lh=0;
    int rh=9;
    for(int i=1;;)
    {
        int mid=(lh+rh)/2;
        if(a==zu[mid]){ cout<<mid; flag=0;break;}
        if(lh==rh) break;
        if(a>zu[mid]){lh=mid+1;}
        if(a<zu[mid]){rh=mid-1;}

    }
    if (flag) cout<<"not found";
效率:二分查找更棒
顺序搜索的平均时间性能:
1 + 2 + 3 + + n ) / n = ( n + 1 ) / 2次
二分查找的最坏情况的时间性能:
n/2/2/2/2/2/2(/了k次2)=1, k=log 2 n次

选择排序法

定义:例如说让输入的数字从小到大排序,或者从大到小。或者字母按顺序。

以下是代码让他们从小到大排序(or从大到小)有点难理解说实话emo

学会怎么让两个变量交换值---引入中间变量tmp

#include <iostream>

using namespace std;

int main()
{
    int lh,rh;
    int myarray[10]={10,2,3,4,5,6,7,8,9,1};
    for(lh=0;lh<10;lh++)
    {
        rh=lh;
        for(int k=lh;k<10;k++)
        {
            if(myarray[k]<myarray[rh]) rh=k;//若想从大到小排序只需改成>
        }
        int tmp=myarray[rh];
        myarray[rh]=myarray[lh];
        myarray[lh]=tmp;
    }

     for(lh=0;lh<10;lh++) cout<<myarray[lh]<<" ";

    return 0;
}

效率:比较总的次数为1+2+3.。。+n次

气泡排序法

与选择排序法的区别在于,气泡会在筛选一遍的过程中将最大的,次大的,次次大的,拉到后面去。从而提高了效率。

过程:比较相邻的元素,若不符合就调整顺序。所以说结束的标志就是没有交换动作!

代码:难敲:整体思路是for{flag+(for复合flag去判断flag)+flag是否break}

int main()
{
    int i,j;
    bool flag;
    int myarray[10]{7,8,9,0,1,2,3,4,5,6};
    for(i=1;i<10;++i)
    {
        flag=0;
        for(j=0;j<10-i;j++)//注意这个for没括号但是控制一整个if语句
        if(myarray[j]>myarray[j+1])
           {
               int tmp=myarray[j];
               myarray[j]=myarray[j+1];
               myarray[j+1]=tmp;
               flag=1;
           }
        if(!flag) break;//不在小for循环中
        }
        for(int o=0;o<10;o++) cout<<myarray[o]<<" ";

    return 0;
}

5.3二维数组

定义:数组的每一个元素又是一个数组

二维数组又叫做矩阵

二维数组的定义格式:int zu[2][3]------表示2行3列,定义了2*3=6个变量;

zu[0][0]zu[0][1]zu[0][2]
zu[1][0]zu[1][1]zu[1][2]

二维数组的内存:

是连续的,且按行序优先排:zu[0][0]、zu[0][1]、zu[0][2]、zu[1][0]...

初始化:int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  

               int a[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}};(这种明显更加方便!!)

部分赋初值:  int a[3][4] = { 1, 2 , 3, 4, 5 };    这是按一个一个填进去的

                       int a[3][4] = { {1, 2}, {3, 4}, {5}};  这样有更多的选择!

如果数组的长度未知,就设100,然后在for循环的时候就知道了,可以用n之类的限制

栗子:输入矩阵,并计算他们的乘积

#include <iostream>

using namespace std;

int main()
{   //定义
    int A[100][100];
    int B[100][100];
    int C[100][100]={0};
    int rowofA,col,rowofB;
    int m=0;
    int o=0;

    //输入行列
    cin>>rowofA>>col>>rowofB;

    //输入A
    for (int i=0;i<rowofA;i++)
    {
        for (int j=0;j<col;j++)
        {
            cin>>A[i][j];
        }
    }

    //输入B
        for (int i=0;i<rowofA;i++)
    {
        for (int j=0;j<col;j++)
        {
            cin>>B[i][j];
        }
    }

    //计算A*B
    for (int i=0;i<rowofA;i++)
    {
        for (int j=0;j<rowofB;j++)
        {
            o=0;//我就是这里忘了,导致后面无法进行运算!
            m=0;
            for(o=0;o<col;o++,m++)
            C[i][j]+=A[i][o]*B[m][j];//以及这里也很容易出错!
        }
    }

    //输出C
     for (int i=0;i<rowofA;i++)
    {
        for (int j=0;j<rowofB;j++)
        {
            cout<<C[i][j]<<" ";
        }
    }
    return 0;
}

栗子:输出n阶魔阵

#include <iostream>

using namespace std;

int main()
{   //定义
    int n=0;
    int zu[100][100]={0};
    int row=0;

    //shuru
    cin>>n;
    int col=n/2;
    //填数1
    zu[0][n/2]=1;
    //xuhuantianshu
    for (int i=2;i<=n*n;i++)
    {
        int a=row;
        int b=col;
        if (row-1==-1) row=n-1;
        else row--;
        if (col+1==n) col=0;
        else col=col+1;
        if(zu[row][col]==0) zu[row][col]=i;
        else
        {
             if (a+1==n) a=0;
            else a++;
            zu[a][b]=i;
            row=a;
            col=b;
        }

    }
       //shuchu
        for (int u=0;u<n;u++)
        {
            cout<<endl;
            for (int p=0;p<n;p++)
            {
                cout<<zu[u][p]<<" ";
            }
        }


    return 0;
}

改进:比如行列换的时候会遇见 第零行-1变成第-1行怎么办?

rol=(rol-1+scale)%scale

要绘表 cout<<zu[u][p]<<'/t';     绘表‘/t’

5.4字符串

字符串的定义:由一系列字符组成的一个数据称为字符串。字符串的本质是一系列的有序字符,因此可以用一个字符数组来保存这组字符 。用数组名表示这个字符串。

字符串的分类

  • 字符串常量:用一对双引号括起来,如”Hello,world”。
  • 字符串变量:用字符类型的数组来表示。

字符串的储存

需要用‘\0’表示字符串的结束,所以字符串所需的存储空间比实际的字符串长度大1

e.g:如要将字符串”Hello,world”保存在一个数组中 ,该数组的长度为12。

字符串的初始化

char  ch[ ] = { ‘H’, ’e’, ’l’, ’l’, ’o’, ’,’, ’w’, ’o’, ’r’, ’l’, ’d’, ’\0’};注意:‘a’是简单字符变量 “a”是数组

char ch[ ] = {”Hello,world”};

char ch[ ] = ”Hello,world”;

空字符串

不包含任何字符的字符串称为空字符串,空字符串占用的空间为1个字节,存储‘\0’。

\n是换行
\0是字符串结束标志。只要有空间,就会自动填\0~我觉得还是自动有\0比较好

输入一个字符串(少于80个字符),统计并输出其中元音字母(AEIOUaeiou)的个数(不区分大小写)。错的很傻

#include <iostream>

using namespace std;

int main()
{   //定义与输入
    int Count=0;
    char zu[81];
    cin.getline(zu,82,'\n');//注意\n不进入数组中
    //
    for (int i=0;;i++)
    {
        if (zu[i]=='\0')//注意只要有/0的位置就会自动补/0
        break;
        if(zu[i]=='a'||zu[i]=='e'||zu[i]=='i'||zu[i]=='o'||zu[i]=='u'||zu[i]=='A'||zu[i]=='E'||zu[i]=='I'||zu[i]=='O'||zu[i]=='U')
        Count+=1;

    }
    cout<<"Count="<<Count;
    return 0;
}

字符串的输入

F1:cin.getline(字符数组,数组长度,结束标记);  cout << ch;

读取包含空白字符的一句话。直到达到结束标记或者字符串读满(包含\0)。默认结束标记为’\0’。

cin.getline(zu,6)也可以,属于是省略了结束标记,默认’/0‘

易错:写成cin.get,\n写成/n,正确是cin.get(zu,80,'\n')

🌰栗子:

char x[4];

cin.getline(x, 4, ‘2’);

cout <<x;

键入:1234  ,  显示:1易错并不包括2的

键入:13456,显示:134

键入:1 345,    显示:1 3

F2: cin >> ch;    cout << ch;

无法输入包含空白字符的字符串。要注意输入的字符串的长度不能超过数组的长度。

字符串的输出

其他数组都是cout<<zu; 显示的是数组首地址

而字符串不一样,cout<<zu; 显示的是hello(如果想显示数组首地址,cout  << (void *) zu)

cout<<zu+2   显示llo

   for (int i=0;zu[i]!='\0';i++)

字符串の处理函数

栗子:输入一行文字,统计有多少个单词。思路是空格,后面不是空格就算一个单词,在1的基础上。

#include <iostream>

using namespace std;

int main()
{   //定义
    char zu[100];
    int num=1;
    //
    cin.getline(zu,8);
    //
    for (int i =0;i<8;i++)
    {
        if (zu[i]==' '&&zu[i+1]!=' ')
        num+=1;
    }
    cout<<num;

    return 0;
}

cap.6过程封装-函数

6.1  函数的用途与定义

函数的分类:

标准库函数:ANSI/ISO C++定义的标准库函数 &第三方库函数(卖的那些)。

                        调用前需要#include相应的头文件。

自定义函数:用户自己编的,也可以去卖

函数定义:

int max(int a, int b)
{
    xxx

    return(a)
}

返回值return

若函数没有返回值,类型标识符用void。没有返回值的函数也称为过程。

只能有一个返回值,可以有多条返回语句。

返回值不能是数组!

无参数、无返回值,int max() {xx} 都不用写return!

6.2  函数的使用

函数的声明:

格式: 返回类型  函数名(参数表);  

参数表中的每个参数说明可以是类型,也可以是类型后面再接一个参数名。

如:int  max(int, int);       int  max(int a, int b);

如果被调函数的定义在主调函数之前,可以不必加声明。

函数调用:

函数名 (实际参数表)

 如:cout << Getmax(x , y );

函数调用可以套用的!如 p(Getmax(x,y))

存储单元问题:

实参和形参各自占用一个独立的存储单元,不可能共用。

默认参数:

(●ˇ∀ˇ●) /

对于某些函数,程序往往会用一些固定的值去调用它。

例如对于以某种数制(2进制、8进制、10进制、16进制)输出整型数的函数print: void print(int value, int base);      在大多数情况下都是以10进制输出,因此base的值总是为10。

C++在定义或声明函数时可以为函数的某个参数指定默认值。

当调用函数时没有为它指定实际参数时,系统自动将默认值赋给形式参数。

例如,可以将print函数声明为void print(int value, int base=10),调用print(20),等价于 print(20, 10)。

又例如:int special(int x=2, float y=1.5);  

调用时可用:

special(5, 3.2);  //x=5; y=3.2

special(6); //x=6; y=1.5

special( ); //x=2; y=1.5

6.3  变量的作用域与存储类别

局部变量 和 全局变量

全局变量:在所有函数之外定义的变量 ;作用范围:从定义位置到文件结束;用关键词extern在函数内说明此全局变量。全局变量破坏了模块化,建议尽量少使用。当全局变量和局部变量同名时,在局部变量的作用范围中全局变量被屏蔽。如果要使用全局变量,可以使用作用域运算符::

当内部块与外部块有同名变量时,在内部块中屏蔽外部块的同名变量。

形式参数不可以和局部变量同名。

存储类别

每个变量有两个属性:

数据类型:变量所存储的数据类型

存储类别:变量的存储位置和期限。存储类型决定了变量的生存期。

分类:

自动变量:auto。生存期是定义它的语句块。auto   int  i 等价于 int i;

静态变量:static。生存期是整个程序。只运行第一遍语句,之后就存着运行的数。未被程序员初始化的静态变量都由系统初始化为0。虽然局部静态变量在函数调用结束后仍然存在,但其他函数不能引用它。局部的静态变量在程序执行结束时消亡。

寄存器变量:register

外部变量:extern。 extern  int  num;用extern可引用另一文件中的全局变量。

     int f(int a)
       { int b=0;
          static int c=3;
          b=b+1; 
          c=c+1;
          return(a+b+c);
        }

       void main()
        {int a=2,i;
         for (i=0; i<3; ++i)
           cout << f(a);
        }
运行结果为:7 8 9

6.4函数变量为数组

函数:int average(int array[ ],int N)

调用时:cout<<average(sum)直接调用数组的名字

♥注意:在函数操作数组是会改变主函数中的值哦,,形式参数和实际参数是同一数组!!!

o(* ̄▽ ̄*)ブ在函数中并没有定义新的数组; 对形式参数数组指定规模是没有意义的,形式参数数组不需要指定大小,所以方括号中为空; 函数如何知道数组的规模?用另一个整型参数表示;

总结:数组传递需要两个参数: 数组名 ,数组规模。

6.5内联、重载、模板、递归

6.5.1内联函数

内联函数的定义:在函数头部前加保留词inline   栗子:inline float cube(float s)

理解:在调用内联函数时,编译器直接用内联函数的代码替换函数调用,于是省去了函数调用的开销。

慎用内联函数:

  • 内联以代码复制(膨胀)为代价,省去了函数调用的开销,提高函数的执行效率。如果相比于执行函数体内代码的时间,函数调用的开销可以忽略不计,那么效率的收获会很小。
  • 内联函数不能递归!
  • 内联函数必须定义在被调用之前。
  • 以下情况不宜用内联: 如果函数体代码比较长,内联将导致内存消耗代价较高。 如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大

6.5.2重载(好用的捏

理解:让具有相似功能的函数有一样的名字,比如取2个数的最大值、3个数的最大值、4个数的最大值,可以都叫max函数。

int max(int a1, int a2);

int max(int a1, int a2, int a3);

int max(int a1, int a2, int a3, int a4);

int max(int a1, int a2, int a3, int a4, int a5); 

谢谢编译器:由编译器确定某一次函数调用到底是调用了哪一个具体的函数。这个过程称之为绑定(binding,又称为联编或捆绑)。

6.5.3模板(好用的捏

定义形式:class T T是数据类型捏

    template<模板形式参数表>
    返回类型  函数名(形式参数表)
   {
	     //函数定义体
     }
     
     template<class T>
     T max(T a, T b)
     { return a>b ? a : b;}

 栗子:

template<class T1,class T2, class T3>
T3 calc( T1 x, T2 y)
{    return x+y;  }

main()
{
  int    x = calc<int , char , int  >(1,’2’);
  char y = calc<int , char, char>(1,’2’); 
  cout << x << " " << y << endl;
}

6.5.4递归(简化的捏

必须能写出这个形式:

if  (条件)
  return (不需要递归的简单答案);
else 
  return (递归调用同一函数);

栗子:

①阶乘

long  p(int n)
{
       if (n == 0) return 1;
       else return n * p(n-1);
 } 

②求n的k次幂

int RaiseIntToPower(int n, int k)
{ if  (k == 0) 
		return(1);
   else 
		return( n * RaiseIntToPower( n, k - 1));
} 

优缺点:

逻辑清晰,好写,代码就几行,但是运行的时间是灾难性的。

cap7指针

7.1指针简介

7.1.1指针概念

定义:int *intp

统配指针:void * 可以指向任何类别

空指针:NULL

7.1.2指针运算(intp是地址,*intp是那个变量呀)

赋值:intp=&x(&后不可以加常量或表达式,只能加变量)

赋初值这么写:int x, *p=&x;

间接访问:*intp=5等价于x=5;

算术运算:指针+1表示数组中指针指向数组的下一元素地址;(存的地址其实是+4)

                  指针-1表示数组中指针指向数组的上一元素地址;

                  p1 - p2也正确

7.1.3指针与数组

指针和数组关系密切,常常可以互换使用。

数组名可以看成是常量指针,数组名是数组的起始地址,也就是第0个元素的地址。

int  a[10], *p,并且执行了 p = a,则p[5]=a[5]都一样的,相当于换名了

数组元素的指针表示:*(p+1)=p[1]

注意数组名是常量指针,不可以加减。

7.1.4指针作为函数 参数和返回值

背景:我们的swap函数可是没法交换的。也是没法返回两个数的

swap(&x, &y);

swap(int  *a, int *b)

{    

         int c;

        c=*a;      

         *a= *b;          

        *b=c;

}

解一元二次方程!存在地址里,看例子吧

数组传递:type fun(type a[ ], int size);    也可写为 type fun(type *p , int size);

                建议:如果传递的是数组,用第一种形式;如果传递的是普通的指针,用第二种形式。

                调用时:func(数组名,长度)

                还挺灵活:sort(a, 100);    //排序整个数组

                                  sort(a, 50);     //排序数组的前50个元素  

                                  sort(a+50, 50);  //排序数组的后50个元素

返回指针的函数:

返回指针的函数原型:类型 *函数名(形式参数表);

当函数的返回值是指针时,返回地址对应的变量不能是局部变量。

引用和引用传递:

给一个变量取一个别名。隐式指针。

例如:int i;   int &j = i;

好多不能😅:::

定义引用时必须立即对它初始化,不能定义完成后再赋值。

为引用提供的初始值可以是一个变量或另一个引用。

引用不可重新赋值,不可使其作为另一变量的别名。

 int &a[3]; //不能建立引用数组    

int &&r; //不能建立引用的引用

引用参数 void swap(int &m, int &n) {     int temp;     temp=m;     m=n; n=temp; } 调用:swap(x, y)

返回引用的函数:

返回引用的函数原型:类型 &函数名(形式参数表);

左值????????????

7.2动态内存分配

new:用于进行内存分配

           p = new type;  

           p = new type[size];//分配数组p=new int[10];

           p = new type(56);

delete:释放new分配的内存

           delete p;

           delete [ ] p;

动态分配检查:int *p;    p = new int;    if(!p){cout << "allocation failure\n"; return 1;

                      #include <cassert>     assert (p != NULL);  //若p等于NULL,则退出程序执行

栗子:

 int *p, i, n;

   if (!(p = new int [n])) exit(1);
   for (i=0; i<n; ++i)  cin >> p[i];
   for(i=0; i<n; ++i)  sum += p[i];
   delete [] p;

7.3字符串再讨论

字符串的另一种表示是定义一个指向字符的指针,然后直接将一个字符串常量赋给它。

 eg:char * string;        string = “abcde”;

将存储字符串“abcde”的内存的首地址赋给指针变量string

字符串常量存储在一个称为数据段的内存区域里。数据段区不可修改。

字符指针:   cout <<  p; 显示整个字符串                      

                      cout << *p; 显示单个字符;

常量指针:定义格式 const type * 指针变量名;                

                   type const * 指针变量名;                          

                   比如:const int * p;      

                   作用:指针指向的内存内容不可修改,指针可移动;

指针常量:定义格式 type * const 指针变量名;                        

                 比如:int * const p;      

                作用:指针指向的内存内容可修改,但指针不可修改,指针定义时需同时初始化;

指向常量的常量指针:定义格式 const type * const 指针变量名;                          

                                    比如:const int * const p;

后置++与指针运算优先级、数据交换问题

7.4指针数组 与多级指针

指针数组:一个数组,如果他的元素均为指针,则称为指针数组。

定义形式:char *string[10]

main函数的参数:???????????????????????

多级指针:指针指向的内容还是一个指针,称为多级指针。

两级指针:类型名 **变量名; 三级指针:类型名 ***变量名;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值