C++基础入门

1. C++初始

1.1 第一个C++程序

示例代码

# include <iostream>

using namespace std;

int main()
{
    cout << "hello Word!" << endl;

    system("pause");

    return 0;

}

1.2 注释

  1. 单行注释 //
  2. 多行注释 / /

1.3 变量

作用:给一段指定的内容空间起名,方便操作这段内容。

语法:数据类型 变量名 * 初始值。

示例代码

# include <iostream>

using namespace std;

int main()
{
    int a = 10;

    cout << "a = " << a << endl;

    system("pause");

    return 0;

}

1.4 常量

作用:用于记录程序中不可更改的数据。

C++定义常量两种方式

  1. #define宏常量: #define 常量名 常量值
  • 通常在文件上方定义,表示一个常量
  1. const修饰的变量 const 数据类型 常量名 = 常量值
  • 通常在变量定义前加关键词const,修饰该变量为常量,不可修改。

示例代码

# include <iostream>

using  namespace  std;

# define DAY 7

int main()
{
    cout << "一周有:" << DAY << "天" << endl;

    const int month = 12;
    cout << "一年总共有:" << month << "个月份" << endl;

    system("pause");

    return 0;
}

1.5 关键字

作用:关键字是C++中预先保留的单词(标识符)

Notice:在定义变量和常量的时候不要用关键词。

1.6 标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有自己一套规则

  • 标识符不能是关键字
  • 标识符只能由字母、数字、下划线组成
  • 第一个字符必须是字母或下划线
  • 标识符中字母区分大小写

建议:在给标识符明名时,尽量做到清晰,贴合意义的效果,方便自己和他人的阅读。

2. 数据类型

说明

C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存。

意义

给变量分配合适的内存空间,减小资源浪费。

2.1 整型

作用:整型变量表示的是整数类型的数据。

C++中能够表示整形的类型有以下几种方式,区别在于所占内存空间不同。

2.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存的大小

语法:sizeof(数据类型 / 变量)

示例代码

# include <iostream>

using namespace std;

int main()
{

    cout << "short占用内存空间为:" << sizeof(short) << endl;
    cout << "int占用内存空间为:  " << sizeof(int) << endl;
    cout << "long占用内存空间为: " << sizeof(long) << endl;
    cout << "long long占用内存空间为:" << sizeof(long long) << endl;

    system("pause");

    return 0;

}

2.3 实型(浮点型)

作用:用于表示小数

浮点型变量分为两种:

  1. 单精度:float
  2. 双精度:double

示例代码

# include <iostream>

using namespace std;

int main()
{
    float a = 3.1415926;
    float f1 = 3e2;
    float f2 = 3e-2;
    double b = 3.1412657;

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "f1 = " << f1 << endl;
    cout << "f2 = " << f2 << endl;
    cout << "float占用字节大小为: " << sizeof(f1) << endl;
    cout << "double占用字节大小为: " << sizeof(f2) << endl;

    system("pause");

    return 0;

}

2.4 字符型

作用:字符型变量用于显示单个字符

语法:char ch = 'a';

NOTICE

在显示字符型变量时,用单引号将字符括起来,不要用双引号

单引号内只能有一个字符,不可以是字符串

C和C++中字符变量只占用1个字节。

字符型变量并不是吧字符本身放到内存中存储,而是将相对应的ASCII编码放入到存储单元。

示例代码

# include <iostream>

using namespace std;

int main()
{
    char ch = 'a';

    cout << ch << endl;
    cout << "char所占的字节数:" << sizeof(char) << endl;
    cout << (int)ch << endl;        //字符型变量对应ASCII编码
    ch = 97;                        //可以直接用ASCII码直接给字符型变量赋值
    cout << ch << endl;

    system("pause");
    return 0;

}

ASCLL码表

ASCLL码大致由以下两个部分组成:

  • ASCLL非打印控制字符:ASCLL表上的数字0-31分配给了控制字符,用于控制像打印机等一些外围设备。
  • ASCLL打印字符:数字32 - 126分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。

2.5 转义字符

作用:用于表示一些不能显示出来的ASCII字符。

转义字符 含义 ASCII码值(十进制)
\a
\b
\f
\n
\r
\t
\v
\ \
\ '
\ "
\?
\0
\ddd
\xhh

示例代码

# include <iostream>

using namespace std;

int main()
{

    cout << "helloworld \n";
    cout << "\\" << endl;
    cout << "aaa\thello" << endl;         //比如输出3个a,则中间空格数为8-3为5个
    cout << "aa\thello" << endl;
    cout << "aaaaaa\thello" << endl;

    system("pause");
    return 0;
}

2.6 字符串型

作用:用于表示一串字符

两种风格

  1. C风格字符串:char 变量名[ ] = "字符串值";

示例

# include <iostream>
using namespace std;

int main()
{
    char str1[] = "hello world";
    cout << str1 << endl;

    system("pause");

    return 0;
}
  1. C++风格字符串:string 变量名 = ”字符串值“;

示例

# include <iostream>
# include <string>
using namespace std;

int main()
{
    string str2 = "helloworld";

    cout << str2 << endl;

    system("pause");

    return 0;

}

C++风格字符串,需加入头文件 # include

2.7 布尔类型bool

作用:布尔数据类型代表真或假的值。

bool类型只有两个值。

  • true --- 真(本质为1)
  • false --- 假(本质为0)

bool类型占1个字节的大小

示例

# include <iostream>
using namespace std;

int main()
{
    bool flag = true;
    cout << flag << endl;

    flag = false;
    cout << flag << endl;

    cout << "bool类型所占字节的大小为:" << sizeof(flag) << endl;

    system("pause");

    return 0;

}

2.8 数据的输入

作用:用于从键盘获取数据

关键词:

示例代码

# include <iostream>
using namespace std;

int main()
{
    cout << "请给整数a赋值:" << endl;
    cin >> a;
    cout << "a = " << a << endl;

    system("pause");
    return 0;
}

3. 运算符

说明

用于执行代码的运算。

主要分为以下几类运算符

运算符类型 作用
算术运算符 用于处理四则运算
赋值运算符 用于将表达式的值赋给变量
比较运算符 用于表达式的比较,并返回一个真值或假值
逻辑运算符 用于根据表达式的值返回真值或假值

3.1 算数运算符

作用:用于处理四则运算

示例代码

# include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int b = 3;

    cout << a + b << endl;
    cout << a - b << endl;
    cout << a * b << endl;
    cout << a / b << endl;
    cout << a % b << endl;      //两个小数之间不可以进行取模运算

    int a1 = 10;
    ++a1;
    cout << "a1 = " << a1 << endl;

    int b1 = 10;
    b1++;
    cout << "b1 = " << b1 << endl;

    //前置和后置的区别

    //前置递增,先让变量加1,然后进行表达式运算
    int a2 = 10;
    int b2 = ++a2 * 10;
    cout << "a2 = " << a2 << endl;
    cout << "b2 = " << b2 << endl;

    //后置递增,先进行表达式运算,然后变量加1
    int a3 = 10;
    int b3 = a3++ * 10;
    cout << "a3 = " << a3 << endl;
    cout << "b3 = " << b3 << endl;

    system("pause");
    return 0;

}

3.2 赋值运算符

作用:用于将表达式的值赋值给变量

赋值运算符包括以下几个符号

运算符 术语 示例 结果
= 赋值 a = 2; a = 2;
+= 加等于 a = 0;a+=2; a = 2;
-= 减等于 a = 5;a-=2; a = 3;
*= 乘等于 a = 2;a*=2; a = 4;
/+ 除等于 a = 6;a/=2; a = 3;
%= 模等于 a = 4; a%=3; a = 1;

示例代码

3.3 比较运算符

作用:用于表达式的比较,并返回一个真值或假值。

比较运算符有以下符号:

运算符 术语 示例 结果
== 等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
> 大于 4 > 2 1
<= 小于等于 4 <= 3 0
>= 大于等于 4 >= 1 1

示例代码

3.4 逻辑运算符

作用:用于根据表达式的值返回真值或假值

逻辑运算符有以下符号:

运算符 术数 示例 结果
!a 若a为假,则为真
&& a && b 一假则假,全真才为真
|| a || b 一真则真,全假才为假

示例代码

4. 程序流程结构

C/C++支持最基本的三种程序运行结构:顺序结构,选择结构,循环结构

  • 顺序结构:程序按顺序执行,不发生跳转
  • 选择结构:依据条件是否满足,有选择地执行相应功能。
  • 循环结构:依据条件是否满足,循环多次执行某段代码

4.1 选择结构

4.1.1 if语句

作用:执行满足条件的语句

if语句的三种形式

  • 单行格式if语句
  • 多行格式if语句
  • 多条件的if语句
  1. 单行格式if语句:if语句(条件){条件满足执行的语句}

此处应有一个框图

示例代码

  1. 多行格式if语句:if(条件){条件满足执行的语句} else{条件不满足执行的语句}

此处应有一个框图

示例代码

  1. 多条件的if语句:if(条件1){条件1满足执行的语句} else if(条件2){条件2满足执行的语句}……else{都不满足执行的语句}

此处应有一个框图

示例代码

扩展

嵌套if语句:在if语句中,可以嵌套使用if语句,达到更精确的条件判断。

示例代码

4.1.2 三目运算符

作用:通过三目运算符实现简单的判断

语法:表达式1 ?表达式2 :表达式3

解释:

  • 如果表达式1的值为真,执行表达式2,并返回表达式2的结果

  • 如果表达式1的值为假,执行表达式3,并返回表达式3的结果

示例代码

4.1.3 Switch语句

作用:执行多条件分支语句

语法:

switch(表达式)
{

    case 结果1: 执行语句; break;
    case 结果2: 执行语句; break;
    case 结果3: 执行语句; break;
    case 结果4: 执行语句; break;

    default: 执行语句;break;

}

NOTICE:

switch语句中表达式类型只能是整型或者字符型

case语句中如果没有break,那么程序会一直向下执行

与if语句相比,对于多条件判断时,switch的结构清晰,执行效率高,缺点是switch不能判断区间。

4.2 循环结构

4.2.1 while循环语句

作用:满足循环条件,执行循环语句。

语法:while(循环条件) {循环语句}

解释:只要循环条件的结果为真,就执行循环语句

此处应有一个框图

示例代码

# include <iostream>
using namespace std;

int main()
{
    int num = 0;

    while(num < 10)
    {
        cout << num << endl;
        num++;
    }

    system("pause");
    return 0;

}

在执行循环语句的时候,程序必须提供跳出循环的出口,否则出现死循环。

Example:猜数字

# include <iostream>
using namespace std;

int main()
{
    srand((unsigned int)time(NULL));

    int num = rand() % 100 + 1;

    while(1)
    {
        int val = 0;

        cin >> val;

        if(val > num)
            cout << "猜测过大" << endl;

        else if(val < num)
            cout << "猜测过小" << endl;

        else
        {
            cout << "猜测正确" << endl;
            break;
        }

    }

    system("pause");
    return 0;

}

4.2.2 do……while循环语句

作用:满足循环条件,执行循环条件;

语法:do{循环语句} while(循环条件);

注意:与while的区别在于do……while会执行一次循环语句,再判断循环条件。

此处应有框图

示例代码

# include <iostream>
using namespace std;

int main()
{
    int num = 0;

    do
    {
        cout << num << endl;
        num++;
    }while(num < 10);

    system("pause");
    return 0;
}

Example:输出100 - 999之间的水仙花数

# nclude <iostream>
using namespace std;

int main()
{
    int num = 100;

    do
    {
        int g,s,b;
        g = num % 10;
        s = num / 10 % 10;
        b = num / 100;

        if(g*g*g + s*s*s +b*b*b == num)
            cout << num << endl;

    }while(num < 1000)

    system("pause");
    return 0;

}

4.2.3 for循环语句

作用:满足循环条件,执行循环语句

语法:for(起始表达式;条件表达式;末尾循环体) {循环语句}

执行顺序:A - B - D - C - B - D - C - B - D - C

for(A;B;C)

{

​ D;

}

示例代码:

# include <iostream>
using namespace std;

int main()
{

    for(int i = 0;i < 10;i++)
    {
        cout << i << endl;
    }

    system("pause");
    return 0;

}

NOTICE

for循环中的表达式,要用分号进行分割

while, do……while,for都是开发中常用的循环结构,for循环结构比较清晰,比较常用。

4.2.4 嵌套循环

作用:在循环体中再嵌套一层循环,解决一些实际问题。

特点:外层执行一次,内层执行一周

示例代码

# include <iostream>
using namespace std;

int main()
{
    for(int i = 0;i < 10;i++)
    {
        for(int j = 0;j < 10;j++)
        {
            cout << "*";
        }

        cout << endl;                 //换行
    }

    system("pause");
    return 0;

}

4.3 跳转语句

4.3.1 break语句

作用:用于跳出选择结构或者循环结构

break使用的时机 :

  • 出现在switch条件语句中,作用是终止case并跳出switch
  • 出现在循环语句中,作用是跳出当前的循环语句
  • 出现在嵌套循环中,跳出最近的内层循环语句

示例代码

# include <iostream>
using namespace std;

int main()
{

    system("pause");
    return 0;
}

4.3.2 continue语句

作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环

示例代码

# include <iostream>
using namespace std;

int main()
{
    for(int i = 0;i < 100;i++)
    {
        if(i % 2 == 0)          //跳过偶数
        {
            continue;
        }

        cout << i << endl;
    }

    system("pause");
    return 0;

}

4.3.3 goto语句

作用:可以无条件跳转语句

语法:goto标记

解释:如果标记的名称,执行到goto语句时,会跳转到标记的位置

# include <iostream>
using namespace std;

int main()
{
    cout << "1.xxxx" << endl;
    cout << "2.XXXX" << endl;

    goto FLAG:

    cout << "3.xxxx" << endl;
    cout << "4.XXXX" << endl;

    FLAG:
    cout << "5.XXXX" << endl;

    system("pause");
    return 0;

}

在程序中不建议使用goto语句,以免造成程序流程混乱。

5. 数组

5.1 数组概述

说明

所谓数组,就是一个集合,里面存放了相同类型的数据元素。

特点

  • 数组中的每个数据元素都是相同的数据类型
  • 数组是由连续的内存位置组成的

5.2 一维数组

5.2.1 一维数组的定义方式

一维数组定义的三种方式:

  1. 数据类型 数组名[数组长度];
  2. 数组类型 数组名[数组长度] = {值1,值2……};
  3. 数组类型 数组名[] = {值1,值2……};

示例代码

# include <iostream>
using namespace std;

int main()
{
    //数组定义的第一种方式
    int arr1[5];
    arr1[0] = 10;
    arr1[1] = 10;
    arr1[2] = 10;
    arr1[3] = 10;
    cout << arr1[0] << endl;

    //数组定义的第二种方式
    int arr2[5] = {10,20,30,40,50};
    cout << arr2[0] << endl;

    //数组定义的第三种方式
    int arr3[] = {10,20,30,40,50};
    cout << arr3[0] << endl;

    for(int i = 0;i < 5;i++)
    {
        cout << arr3[i] << endl;
    }

    system("pause");
    return 0;

}

5.2.2 一维数组数组名

一维数组名称的用途:

  1. 可以统计整个数组在内存中的长度
  2. 可以获取数组在内存中的首地址

示例代码

# include <iostream>
using namespace std;

int main()
{
    int arr[5] = {10,20,30,40,50}; 

    cout << "整个数组占用的内存空间为:" << sizeof(arr) <<endl;
    cout << "数字首元素占用的内存空间为:" << sizeof(arr[0]) << endl;
    cout << "数组中的元素为:" << sizeof(arr) / sizeof(arr[0]) << endl;

    cout << "数组首地址为:" << arr <<endl;
    cout << "数组种第一个元素地址为:" << (int)&arr[0] <<endl;
    cout << "数组种第二个元素地址为:" << (int)&arr[1] <<endl;

    system("pause");
    return 0;

}

数组名是常量,不可以被赋值。

Example:将数组元素逆置

# include <iostream>
using namespace std;

int main()
{
    int arr[5] = {1,2,3,4,5};

    for(int i = 0;i < 5;i++)
    {
        cout << arr[i] << endl;
    }

    int start = 0;
    int end = sizeof(arr) / sizeof(arr[0]) - 1;

    while(start < end)
    {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;

        start++;
        end--;
    }

    system("pause");
    return 0;

}

5.2.3 冒泡排序

作用:最常用的排序算法,对数组内元素进行排序。

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
  3. 重复以上的步骤,,每次比较次数-1,知道不需要比较。

示例代码

# include <iostream>
using namespace std;

int main()
{
    int arr[9] = {4,2,8,0,5,7,1,3,9};

    for(int i = 0;i < 9 - 1;i++)                  //排序总轮数                
    {
         for(int j = 0; j < 9 - 1 - i;j++)           //比较次数
         {
             if(arr[j] > arr[j+1]);
             {
                 int temp = arr[j];
                 arr[j] = arr[j+1];
                 arr[j+1] = arr[j];
             }
         }       
    }

    for(int i = 0;i < 9;i++)
    {
        cout << arr[i] << " " 
    }
        cout << endl;

    system("pause");
    return 0;  
}

5.3 二维数组

说明

二维数组就是在一维数组上,多加一个维度。

5.3.1 二维数组定义方式

二维数组定义的四种方式:

  1. 数据类型 数组名[行数][列数];
  2. 数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
  3. 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
  4. 数据类型 数组名[] [列数] = {数据1,数据2,数据3,数据4};

以上四种定义方式,第二种更加直观,提高代码的可读性

示例代码

# include <iostream>
using namespace std;

int main()
{

    system("pause");
    return 0;
}

5.3.2 二维数组的数组名

作用

  1. 查看二维数组所占内存空间
  2. 获取二维数组首地址

示例代码

# include <iostream>
using namespace std;

int main()
{
    double arr[2][3] = {{1,2,3},{4,5,6}};

    cout << "二维数组占用的内存空间:" << sizeof(arr) << endl;  
    cout << "二维数组第一行占用的内存空间为:" << sizeof(arr[0]) <<endl;
    cout << "二位数组第一个元素占用的内存空间为:" << sizeof(arr[0][0]) << endl;
    cout << "二维数组行数为:" << sizeof(arr) / sizeof(arr[0]) << endl;
    cout << "二维数组列数为:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;

    cout << "二维数组首地址为:" << arr <<endl;
    cout << "二维数组第一行首地址为:" << (int)&arr[0] <<endl;
    cout << "二维数组第二行首地址为:" << (int)&arr[1] <<endl;

    cout << "二维数组第一个元素首地址为:" << (int)&arr[0][0] <<endl;
    cout << "二维数组第二个元素首地址为:" << (int)&arr[0][1] <<endl;

    system("pause");
    return 0;
}

5.3.3 二维数组应用案例

考试成绩统计:

案例描述:有三名同学(张三,李四,王五),在一次考试中成绩如下表,请分别输出三名同学的总成绩

语文 数字 英语
张三 100 100 100
李四 90 50 100
王五 60 70 80

参考答案

# include <iostream>
# include <string.h>
using namespace std;

int main()
{
    int a[3][3] = {{100,100,100},{90,50,100},{60,70,80}};

    string name[3] = {"张三","李四","王五"};

    for(int i = 0;i < 3;i++)
    {
        int sum = 0;
        for(int j = 0;j < 3;j++)
        {
            sum += score[i][j];
        }

        cout << name[i] << "的总分为:" << sum << endl;

    }

    system("pause");
    return 0;
}

6. 函数

6.1 概述

作用

  1. 将一段经常使用的代码封装起来,减少重复代码
  2. 一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。

6.2 函数的定义

定义一个函数一般主要有五个步骤:

  • 返回值类型

  • 函数名

  • 参数列表

  • 函数体语句

  • return表达式

语法

返回值类型 函数名(参数列表)
{
    函数体语句

    return 表达式
}
  1. 返回值类型:一个函数可以返回一个值。在函数定义中
  2. 函数名:给函数起个名称
  3. 参数列表:使用该函数时,传入的数据
  4. 函数体语句:花括号内的代码,函数内需要执行的语句
  5. return表达式:和返回值类型挂钩,函数执行完成后,返回相应的数据

6.3 函数的调用

功能:使用定义好的函数

语法:函数名(参数)

示例代码

# include <iostream>
using namespace std;

int add(num1,num2)
{
    int sum = num1 + num2;
    return sum; 
}

int main()
{
    int a = 10;
    int b = 30;

    int c = add(a,b);
    cout << c << endl;

    system("pause");
    return 0;

}

总结:函数定义里小括号内称为形参,函数调用时传入的参数称为实参。

6.4 值传递

说明

  • 所谓值传递,就是函数调用时实参将数值传入给形参
  • 值传递时,如果形参发生改变,并不会影响实参

示例代码

# include <iostream>
using namespace std;

void swap(int num1,int num2)
{
    cout << "交换前:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    int temp;
    temp = num1;
    num1 = num2;
    num2 = num3;

    cout << "交换后:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    //返回值类型为void的时候,可以不用写return。
}

int main()
{
    int a = 10;
    int b = 20;

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    swap(a,b);

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    system("pause");
    return 0;

}

6.5 函数的常见形式

常见的函数样式有4种:

  1. 无参无返回值
  2. 有参无返回值
  3. 无参有返回值
  4. 有参有返回值

示例代码

# include <iostream>
using namespace std;

void test1()                        //无参无返回值
{
    cout << "this is test1" << endl;
}

void test2(int a)                       //有参无返回值
{
    cout << "this is test2" << endl;
}

void test3()                        //无参有返回值
{
    cout << "this is test3" << endl;
    return 100;
}

void test4(int a)                       //有参有返回值
{
    cout << "this is test4" << endl;
    return 100;
}

int main()
{
    test1();
    test2(100);
    test3();
    test4(10000);

    system("pause");
    return 0;

}

6.6 函数的声明

作用:告诉编译器函数名称及如何让调用函数。函数的实际主体可以单独定义。

NOTICE:

  • 函数的声明可以多次,但是函数的定义只能有一次。

示例代码

# include <iostream>
using namespace std;

int max(int a,int b);                   //函数声明

int main()
{
    int a = 10;
    int b = 20;

    cout << max(a,b) << endl;

    system("pause");
    return 0;

}

int max(int a,int b)                    //函数定义
{
    return a > b ? a : b;
}

6.7 函数的分文件编写

作用:让代码结构更加清晰

函数分文件编写一般有四个步骤:

  1. 创建后缀名为.h的头文件
  2. 创建后缀名为.cpp的源文件
  3. 在头文件中写函数的声明
  4. 在源文件中写函数的定义

示例代码(main.c)

# include <iostream>
# include "swap.h"                        //自定义函数用双引号括起来
using namespace std;

int main()
{
    int a = 10;
    int b = 20;
    swap(a,b);

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    system("pause");
    return 0;
}

示例代码(swap.cpp)

# include "swap.h"

void swap(int a,int b)
{
    int temp = a;
    a = b;
    b = temp;   
}

示例代码(swap.h)

# include <iostream>
using namespace std;
# include "swap.h"

void swap(int a,int b);

7. 指针

7.1 指针的基本概念

指针的作用:可以通过指针间接访问内存。

NOTICE:

  • 内存编号是从0开始记录的,一般用十六进制数字表示。
  • 可以利用指针变量保存地址。

7.2 指针变量的定义和使用

指针变量定义语法:数据类型 *变量名

示例代码

#  include <iostream>
using namespace std;

int main()
{
    int a = 10;                     
    int *p;                             //定义一个指针                                    
    p = &a;                             //让指针记录变量a的地址
    cout << "a的地址为:" << &a << endl;         //打印数据a的地址
    cout << "指针p为:"  << p << endl;           //打印指针变量p

    *p = 1000;                 //指针前加*表示解引用的操作,指的是找到指针指向的内存中的数据
    cout << "a的地址为:" << a << endl;
    cout << "指针p为:" << *p << endl;

    system("pause");
    return 0;

}

7.3 指针所占的内存空间

QUESTION:

指针也是种数据类型,那么这种数据类型占用多少内存空间?

示例代码

# include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int *p = &a;

    //在32位操作系统下,指针是占4个字节空间大小,不管是什么数据类型
    //在64位操作系统下,指针是占8个字节空间大小,不管是什么数据类型
    cout << "sizeof(int *) = " << sizeof(int *) << endl;
    cout << "sizeof(float *) = " << sizeof(float  *) << endl;
    cout << "sizeof(double *) = " << sizeof(double *) << endl;
    cout << "sizeof(char *) = " << sizeof(char *) << endl;

    system("pause");
    return 0;
}

7.4 空指针和野指针

7.4.1 空指针

空指针:指针变量指向内存中编号为0的空间

用途:初始化指针变量

注意:空指针指向的内存是不可以访问的

示例代码:空指针

# include <iostream>
using namespace std;

int main()
{
    //空指针用于给指针变量进行初始化
    int *p = NULL;

    //空指针是不可以进行访问的,比如 *p = 100;
    //0~255为系统占用内存,因此不可以访问

    system("pause");
    return 0;

}

7.4.2 野指针

野指针:指针变量指向非法的内存空间

示例代码:野指针

# include <iostream>
using namespace std;

int main()
{
    //野指针
    int *p = (int *)0x1100;         //地址未申请却执意去访问它,过界了

    cout << *p << endl;             //访问野指针报错

    system("pause");
    return 0;
}

总结:空指针和野指针都不是我们申请的空间,因此不要访问。

7.5 const修饰指针

const修饰指针有三种情况:

  1. const修饰指针 :常量指针
  2. const修饰常量 : 指针常量
  3. const既修饰指针,又修饰常量

7.5.1 常量指针

说明

指针的指向可以修改,但是指针指向的值不可以改。

语法

const int *p = &a;

图示:

image-20230810164133408

7.5.2 指针常量

说明

指针的指向不可以修改,但是指针指向的值可以改。

语法

int * const p = &a;

图示:

image-20230810164604663

7.5.3 指针修饰指针和常量

说明

指针的指向不可以修改,指针指向的值也不可以更改。

语法

const int * const p = &a;

图示:

image-20230810165118772

示例代码:(三种形式)

# include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int b = 10;

    //const修饰的是指针,指针指向可以改,指针指向的值不可以更改
    const int *p1 = &a;
    p1 = &b;            //报错
    *p1 = 100;          //报错

    //const修饰的是常量,指针指向不可以改,指针指向的值可以更改
    int *const p2 = &a;
    p2 = &b;            //报错
    *p2 = 100           //正确

    //const既修饰指针又修饰常量
    const int * const p3 = &a;
    p3 = &b;            //报错    
    *p3 = 100;          //报错

    system("pause");
    return 0;
}

技巧:看const右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量,把const看作常量的意思。

7.6 指针和数组

作用:利用指针访问数组中的元素。

示例代码

# include <iostream>
using namespace std;

int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};

    cout << "第一个元素为:" << arr[0] <<endl;

    int *p = arr;
    cout << "利用指针访问第一个元素:" << *p << endl;

    p++;
    cout << "利用指针访问第二个元素:" << *p << endl;

    cout << "利用指针遍历数组" << endl;

    int *p2 = arr;
    for(int i = 0;i < 10;i++)
    {
        cout << *p2 << endl;
        p2++;
    }

    system("pause");
    return 0;
}

7.7 指针与函数

作用:利用指针作为函数参数,可以修改实参的值。

示例代码

# include <iostream>
using namespace std;

//值传递
void swap1(int a,int b)
{
    int temp = a;
    a = b;
    b = temp;
}

//地址传递
void swap2(int *p1,int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

int main()
{
    int a = 10;
    int b = 20;

    swap1(a,b);             //值传递不会改变实参
    swap2(&a,&b);           //地址传递会改变实参

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    system("pause");
    return 0;
}

总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递。

7.8 指针、 数组、函数

案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。

例如数组: int arr[10] = {4,3,6,9,1,2,10,8,7,5};

示例代码

# include <iostream>
using namespace std;

void bubbleSort(int * arr,int len)
{
    for(int i = 0;i < len - 1;i++)
    {
        for(int j = 0;j < len - 1 - i;j++)
        {
            if(arr[j] > arr[j+1])
            {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

int main()
{

    int arr[10] = {4,3,6,9,1,2,10,8,7,5};

    int len = sizeof(arr) / sizeof(arr[0]);
    bubbleSort(arr,len);

    for(int i = 0;i < len;i++)
    {
        cout << arr[i] << " ";
    }

    cout << endl;

    system("pause");

    return 0;

}

8. 结构体

8.1 结构体基本概念

说明

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。

8.2 结构体定义和使用

语法:struct 结构体名字 {结构体成员列表};

通过结构体创建变量的方式有三种:

  • struct 结构体名 变量名

  • struct 结构体名 变量名 = {成员1值,,成员2值……};

  • 定义结构体时顺便创建变量

示例代码

# include <iostream>
# include <string.h>
using namespace std;

struct Student
{
    string name;
    int score;
    int age;

}s3;

int main()
{
    //struct Student s1;
    struct Student s1;

    s1.name = "张三";
    s1.age = 19;
    s1.sorce = 90;

    cout << "name :" << s1.name << endl;
    cout << "age :" << s1.age << endl;
    cout << "sorce :" << s1.sorce << endl;

    //struct Student s2 = {……};
    struct Student s2 = {"李四", 19 , 80};
    cout << "name :" << s2.name << endl;
    cout << "age :" << s2.age << endl;
    cout << "sorce :" << s2.sorce << endl;

    //定义结构体时便创建变量名
    s3.name = "王五";
    s3.age = 19;
    s3.sorce = 91;
    cout << "name :" << s3.name << endl;
    cout << "age :" << s3.age << endl;
    cout << "sorce :" << s3.sorce << endl;

    system("pause");
    return 0;
}

定义结构体时的关键词是struct,不可以省略

创建结构体变量时,关键字struct可以省略

结构体变量利用操作符“ . ”访问成员。

8.3 结构体数组

作用:将自定义的结构体放入数组中方便维护

语法:struct 结构体名 数组名[元素个数] = { {},{},……{} };

示例代码

# include <iostream>
# include <string.h>
using namespace std;

//1.创建结构体
struct Student
{
    string name;
    int age;
    int sorce;
};

int main()
{
    //2.创建结构体数组
    struct Student stuArray[3] = 
    {
        {"张三",18,100},
        {"李四",28,99},
        {"王五",39,86}
    };

    //给结构体数组中的元素赋值
    stuArray.name[2] = "赵六";
    stuArray.age[2] = 66;
    stuArray.sorce[2] = 90;

    //4.遍历结构体数组
    for(int i = 0;i < 3;i++)
    {
        cout << "name :" << stuArray.name[i] << "age :" << stuArray.age[i] 
             << "sorce :" << stuArray.sorce[i] << endl;
    }

    system("pause");
    return 0;
}

8.4 结构体指针

作用:通过指针访问结构体中的成员

用法:利用操作符 -> 可以通过结构体指针访问结构体属性

示例代码

# include <iostream>
# include <string.h>
using namespace std;

//1. 定义一个结构体
struct student 
{
    string name;
    int age;
    int score;
};

int main()
{
    //2. 创建学生结构体变量
    struct student s = {"张三",18,100};

    //3. 通过指针指向结构体变量
    struct student *p = &s;

    //4. 通过访问结构体变量中的数据,通过结构体指针 访问结构体中的属性,需要利用 ->
    cout << "姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;

    system("pause");
    return 0;
}

8.5 结构体嵌套结构体

作用:结构体中的成员是另一个结构体

例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

示例代码

# include <iostream>
# include <string.h>
using namespace std;

struct student
{
    string name;
    int age;
    int score;

};

struct teacher
{
    string name;
    int id;             //职工编号
    int age;
    struct student stu;         //结构体中嵌套结构体
};

int main()
{
    struct teacher s;
    s.id = 123;
    s.name = "小王";
    s.age = 50;
    s.stu.age = 10;
    s.stu.name = "小杨";
    s.stu.score = 99;

    cout << "老师姓名:" << s.name << " 老师编号:" << s.id << " 老师年龄:"
        << s.age << endl;
    cout << "学生姓名:" << s.stu.name << " 学生年龄:" << s.stu.age << "  学生分数:"
        << s.stu.score << endl;

    system("pause");
    return 0;

}

8.6 结构体做函数参数

作用:将结构体作为参数向函数中传递。

传递方式有两种:

  • 值传递
  • 地址传递

示例代码

# include <iostream>
# include <string>
using namespace std;

struct student
{
    string name;
    int age;
    int sorce;

};

//值传递
void printstudent1(struct student s)
{
    cout << "学生姓名:" << s.name << "  学生年龄:" << s.age << "  学生分数:"
        << s.sorce << endl;
}

void printstudent2(struct student* p)
{
    p->age = 24;
    cout << "学生姓名:" << p->name << "  学生年龄:" << p->age << "  学生分数:"
        << p->sorce << endl;

}

int main()
{
    struct student s;
    s.name = "小杨";
    s.age = 20;
    s.sorce = 99;

    printstudent1(s);
    printstudent2(&s);
    /*cout << "学生姓名:" << s.name << "  学生年龄:" << s.age << "  学生分数:"
        << s.sorce << endl;*/

    system("pause");
    return 0;
}

总结:如果不想修改主函数中的数据,用值传递,反之用地址传递。

8.7 结构体中const的使用场景

作用:用const来防止误操作。

示例代码

# include <iostream>
# include <string>
using namespace std;

struct student
{
    string name;
    int age;
    int sorce;
};

//将函数中的形参改为指针,可以减少内存空间,而且不会赋值新的副本出来
void printstudent(const student *p)    //加const防止函数体中的误操作
{
    // p->age = 15;         //错误,因为加了const修饰
    cout << "学生姓名:" << p->name << "  学生年龄:" << p->age << "  学生分数:"
    << p->sorce << endl;
}

int main()
{
    struct student s = {"张三", 18, 90};

    printstudent(&s);

    system("pause");
    return 0;
}

8.8 结构体案例

8.8.1 案例一

案例描述:

学校正在做毕设项目,每名老师带领5名学生,总共有3名老师,需求如下

设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存在5名学生的数组作为成员

学生的成员有姓名,考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值,

最终打印出老师数据以及老师所带的学生数据。

示例代码

# include <iostream>
# include <string>
# include <ctime>                     //随机数种子需要抓取系统时间
using namespace std;

struct student
{
    string name;
    int sorce;

};

struct teacher 
{
    string name;
    struct student sArray[5];
};

//赋初值
void assignment(struct teacher tArray[], int len)
{
    string nameseed = "ABCDE";

    for (int i = 0; i < len; i++)
    {
        tArray[i].name = "teacher_";
        tArray[i].name += nameseed[i];

        for (int j = 0; j < 5; j++)
        {
            tArray[i].sArray[j].name = "student_";
            tArray[i].sArray[j].name += nameseed[j];

            int random = rand() % 61 + 40;  //40 ~ 100
            tArray[i].sArray[j].sorce = random;
        }
    }

}

//打印信息
void printIofo(struct teacher tArray[],int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << "老师姓名: " <<  tArray[i].name << endl;

        for (int j = 0; j < 5; j++)
        {
            cout << "\t学生姓名:" << tArray[i].sArray[j].name << "  学生分数:"
                << tArray[i].sArray[j].sorce << endl;
        }
    }

}

int main()
{
    srand((unsigned int)time(NULL));           //随机数种子

    struct teacher tArray[3];
    int len = sizeof(tArray) / sizeof(tArray[0]);

    assignment(tArray, len);

    printIofo(tArray,len);

    /*system("pause");*/
    return 0;

}

8.8.2 案例二

案例描述:

设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。

五名英雄的信息如下:

{刘备,23,男}
{关羽,22,男}
{张飞,20,男}
{赵云,21,男}
{貂蝉,19,女}

示例代码

分类: C++

易碎

易碎

我看到的今夜的星空,是几万年前的光,我眼中的你是此时的你!

0 条评论

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注

网站ICP备案皖ICP备2024045222号-1