1 - C++ 基础知识

​ 主要是一些 C++ 中的语法知识。

一、框架(基本格式)

#include<iostream)
using namespace std;

int main(){
	/*
	
		代码块
	
	*/
	system("pause");
	return 0;
}

程序解析

  • include 就是包含而 “#” 代表了预处理命令,简单的说就是要包含后面的 < > 里内容。C++C 一样,也使用一种预处理器。该编译指令导致预处理器将 < > 里面的内容添加到程序中。这是一种典型的预处理器操作:在源代码被编译之前,替换或添加文本。
  • iostream 就是输入输出的头文件,定义了 coutcin 等。iostream 中的 io 指的是输入(进入程序的信息)和输出(从程序中发出去的信息)。

  • using:就是使用的意思。

  • namespce :命名空间。

  • std :使用了 std 的命名空间。

  • cout 就是像屏幕输出文字,也就是输出流通常用"<<"表示。coutC++ostream 类型的对象,该类被封装在 < iostream > 库中,该库定义的名字都在命名空间 std 中,所以 cout 全称是 std::cout

  • cin 是输入流,顾名思义像屏幕里输入数字,通常用">>"表示。

  • cout:简单理解为 “c output”, cin:简单理解为 “c input”。

  • endl:表示换行的意思。

1、头文件名

​ 像 iostream 这样的文件叫做包含文件 (include file) ——由于它们被包含在其它文件中;也叫头文件——由于它们被包含在文件起始处。

2、名称空间

​ 名称空间支持是 C++ 中一项较新的特性,它是为了使编写将多个厂商已有的代码组合起来的程序更简单而设计的。

​ 类、函数、和变量都是 C++ 编译器的标准组件,它们现在都被放置在名称空间 std 中。这意味着在 iostream 中定义的、用于输出的cout变量实际上是 std::out,而 endl 实际上是 std::endl。因此可以省略 using 指令(即在编写程序的时候不写 using namespace std),以下述方式进行编码:

std::out<<"Hello World!"

std::out<<std::endl

​ 而 using namespace std 可以直接使用 std 名称空间中定义的名称,不需要加 std 前缀,就会省去一些麻烦。也可以直接使用 using 声明来实现:

using std::cout

using std::endl

using std::cin

3、注释

​ 单行注释:使用 // 进行单行注释。

​ 多行注释:使用 /* 描述信息 */ 进行多行注释。

4、main() 函数

​ 即使一个文件夹下面有多个 .cpp 文件,这些文件里面也只能有一个 main() 函数,这个 main() 函数是程序的入口,假如一个文件里面的多个文件拥有不只一个 main() 函数,就会导致程序无法运行。

二、变量

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

创建语法数据类型 变量名 = 变量初始值

理解:数据类型即 int float 等,计算机会根据所给的数据类型在内存上开辟出对应的空间,变量名就是给这段空间命名,初始值就是给这段空间里面放入一些值,例如 int a = 5,即计算机首先读取 int,并在内存空间上分配了 4 个字节的空间,给这四个字节的空间命名为 a,接着在这段空间里面放入值为 5

三、常量

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

两种方式

  • #define 宏常量:#define 常量名 常量值
    通常在文件上方定义,表示一个常量。

    #define day 7
    
  • const 修饰的变量: const 数据类型 常量名 = 常量值
    通常在变量定义前加关键字 const,修饰该变量为常量,不可更改。

    const int month = 12
    
    #include<iostream>
    #define day 7   // 定义一个常量。
    using namespace std;
    
    int main(){
        
        cout << "一周总共有" <<day << "天" << endl;
        
        const int month = 12;  // const 也修饰一个不可更改的常量。
        cout << "一年总共有" << month <<"月" << endl;
        
        system("pause");
        return 0;
    }
    

四、字符串

作用:用于表示一串字符。

两种风格

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

实例

int main(){
	
	char str1[]="Hello World!";
	cout<<str1<<endl;
	
	system("pause");
    
	return 0;
}

2. C++ 风格字符串string 变量名 = "字符串值",需要添加头文件 #include <string>

实例

#include<string>
int main(){
	
	string str2 ="Hello World!";
	cout<<str2<<endl;
	
	system("pause");
    
	return 0;
}

五、数据输入

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

关键字cin

注意:所有的数据一开始的时候都要初始化。

实例

#include<iostream>
using namespace std;

int main(){
    
    int a = 0;		//开始的时候必须初始化变量
    cout <<"请输入a的值:" << endl;
    cin >> a;    //这里只有一个>>,不是两个,后面不接endl
    cout << "a的值为:a=" <<endl;
    
    system("pause");
    
    return 0;
}

六、程序流程结构

1、选择结构

if 语句

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

注意if 语句后面不加分号也不加冒号。单行 if 可以省略 "{}",如果 if 执行语句有多行则需要添加 "{}"

#include<iostream>
using namespace std;

int main(){

    int score = 0;    //一开始的时候需要初始化

    cout <<"请输入您的成绩:";
    cin >>score;

    if(score > 600)
        cout << "恭喜您考上了一本大学"<<endl;
    else if (score > 400)
        cout <<"恭喜您考上了二本大学"<<endl;
    else
        cout <<"很遗憾您落榜了"<<endl;

    system("pause");
    return 0;

}

if 语句的嵌套

​ 可以在 if 语句里面继续添加判断语句,以继续进行更准确的判断。

else if(score > 600){               //if的嵌套语句,可以在if条件里面继续添加判断语句
        if (score>650)
        cout << "恭喜您考上了北京大学"<<endl;

        else if (score <=650)
        cout << "恭喜您考上了清华大学"<<endl;
    }

三目运算符

作用:实现简单的判断。

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

解释

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

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

#include<iostream>
using namespace std;

int main(){

    int a = 10;
    int b = 20;
    int c = 0;

    c = (a>b?a:b);

    cout<<"c的值为:c="<<c<<endl;

    system("pause");
    return 0;

}

注意:三目运算符返回的值是一个变量因此,可以对返回值继续赋值。

(a>b?a:b)=100;      //如果a>b,则返回a且将100赋值给a,否则返回b且将100赋值给b。
    cout<<"a的值为:a="<<a<<endl;
    cout<<"b的值为:b="<<b<<endl;  
/*
	a的值为:a=10
	b的值为:b=100
*/

switch 语句

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

语法

switch(表达式)
{
    case 结果1 :执行语句 ;break;
  
    case 结果2 :执行语句 ;break;
        ...
    default : 执行语句; break;
}

注意switch 后面的表达式只能是整形或字符型,不能是一个区间;break 作为条件分支的跳出语句,必须添加,否则会出现多个结果。

#include<iostream>
using namespace std;

int main(){

    cout<<"请您对该电影进行评分:"<<endl;
    int score = 0;
    cin >> score;

    switch (score)
    {
    case 10:
        cout<<"您认为该片是经典电影"<<endl;
        break;
    case 6:
        cout<<"您认为该片是好电影"<<endl;
        break;
    case 4:
        cout<<"您认为该片是一般电影"<<endl;
        break;
    case 2:
        cout<<"您认为该片是烂片"<<endl;
        break;
    default:
        break;
    }

    system("pause");
    return 0;
}

​ 假如不添加 break,那么在输入内容为 10 的时候会出现以下结果,为依次运行 cout

"您认为该片是经典电影" "您认为该片是经典电影"
"您认为该片是经典电影" "您认为该片是好电影"
"您认为该片是经典电影" "您认为该片是一般电影"
"您认为该片是经典电影" "您认为该片是烂片"

2、循环结构

while 循环语句

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

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

#include<iostream>
using namespace std;

int main(){

    int num = 0;
    while (num<10)
    {
        cout<<num<<endl;
        num++;
    }
    
    system("pause");
    return 0;
}

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;
}

输出结果: 0 1 2 3 4 5 6 7 8 9

对比do...whilewhile 的执行结果 。

#include<iostream>
using namespace std;

int main(){

    int num = 0;

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

    system("pause");
    return 0;
}

​注意上述代码中 **** 这一行,num 的条件,如果是 do...while 由于会先执行一次语句,因此,在执行完之后,num 由原来的 0 变为 1,此时,while 的条件变为 while(1),为真,因此会继续循环。结果为一直循环。

#include<iostream>
using namespace std;

int main(){

    int num = 0;
    while (num)
    {
        cout<<num<<endl;
        num++;
    }
    
    system("pause");
    return 0;
}

​ 由于此处 while 的循环条件为 while(0),为假,因此循环语句不会执行。

for 循环表达式

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

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

#include<iostream>
using namespace std;

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

    system("pause");
    return 0;
}

3、跳转语句

break 语句

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

break 使用时机

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

实例1

#include<iostream>
using namespace std;

int main(){

    //出现在switch语句中的break
    cout<<"请输入您要选择难度:"<<endl;
    cout<<"1、普通"<<endl;
    cout<<"2、中等"<<endl;
    cout<<"3、困难"<<endl;

    int select = 0;
    cin >> select;

    switch (select)
    {
    case 1:
        cout<<"您选择的难度是\"普通\""<<endl;
        break;
    case 2:
        cout<<"您选择的难度是\"中等\""<<endl;
        break;
    case 3:
        cout<<"您选择的难度是\"困难\""<<endl;
        break;
    default:
        break;
    }

    system("pause");
    return 0;
}

实例2

#include<iostream>
using namespace std;

int main (){

    //出现在for循环中的break语句
    for (int i = 0;i<10;i++){
        if(i == 5){
            break;
        }
        cout << i <<" " ;
    }

    system("pause");
    return 0;
}

实例3

#include<iostream>
using namespace std;

int main (){

    //出现在循环嵌套中的break
    for(int i =0;i<10;i++){
        for(int j = 0;j<10;j++){
            if(j == 5){
                break;
            }
            cout <<"* ";
        }
        cout<<endl;
    }
    
    system("pause");
    return 0;
}

continue 语句

作用continue 之后的语句不再执行,跳出本次循环,继续执行下一次循环。

#include<iostream>
using namespace std;

int main(){

    //打印0~100中的奇数,但是不打印奇数
    for(int i = 0;i<=100;i++){
        if(i%2==0){
            continue;   //当取余结果为0的时候,即该数为偶数的时候,跳出本次循环,不执行之后的语句,并继续执行下一次循环
        }
        cout<<i<<endl;
    }

    system("pause");
    return 0;
}

goto 语句

作用:无条件跳转到标签所在地方,并执行标签之后的代码,goto 与标签之间的代码不再执行。

goto 表达式goto 标签名;

标签表达式"标签名" + ":",标签名一般约定俗成为全大写字母,可以自己定义标签名,且标签作为一个单独语句出现。

实例

#include<iostream>
using namespace std;

int main(){

    //goto语句:当运行到goto语句的时候,会自动跳转到标签位置,执行标签之后的代码
    cout<<"1、这是一"<<endl;
    cout<<"2、这是二"<<endl;

    goto FLAG;      //执行到该语句的时候,系统会寻找标签FLAG所在地,执行FLAG之后的代码,而goto和标签FLAG之间的语句不再执行

    cout<<"3、这是三"<<endl;
    cout<<"4、这是四"<<endl;

    FLAG:           //此处为标签FLAG所在地方,由标签名“FLAG”+一个“:”组成
    cout<<"5、这是五"<<endl;

    system("pause");
    return 0;
}

7、数组

1、概述

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

特点1:数组中每个数据元素都是相同的数据类型

特点2:数组是由连续的内存位置组成的

2、一维数组

定义方式

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

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

实例

#include<iostream>
using namespace std;

int main(){

    //1、数据类型	数组名[ 数组长度 ];
    int arr[5];
    //给数组赋值
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;
    arr[4] = 50;
    //输出数组值
    cout << arr[2] << endl;


    //2、数据类型 	数组名[ 数组长度 ] = { 值1,值2,... }
    int arr1 [5] = {10, 20, 30 ,40 ,50};
    //输出数组值
    cout << arr[3] << endl;


    //3、数据类型	数组名[  ] = { 值1,值2,... }
    int arr3[] = {10,20,30,40,50};
    //输出数组值
    cout << arr[1] << endl;


    system("pause");
    return 0;
}

3、二维数组

定义方式

  1. 数据类型 数组名[ 行数 ] [ 列数 ];

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

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

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

第二种更加直观,具有可读性。

实例1

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

class Person {
public:
	Person(string name, int age) {
		this->s_Name = name;
		this->s_Age = age;
	}

	string s_Name;
	int s_Age;
};

void test02() {
	vector<Person*> v;
	
   //连续创建类对象
	cout << "请输入指针数组长度:" << endl;
	int len=0;
	cin >> len;
	Person** Parr = new Person*[len];
	for (int i = 0; i < len; i++) {
		string name;
		int age;

		cout << "输入名字:" << endl;
		cin >> name;
		cout << "输入年龄:" << endl;
		cin >> age;

		Person* p = new Person(name,age);
		Parr[i] = p;

		v.push_back(p);
	}

	for (int i = 0; i < len; i++) {
		cout << Parr[i]->s_Name << endl;
	}


	for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++) {
		cout << "姓名:"<< (*it)->s_Name << " 年龄:" << (*it)->s_Age << endl;		//此处是->是因为(*it)是一个指针,所以只能使用->
	}
}

int main() {

	test02();

	system("pause");
	return 0;
}

实例2

#include<iostream>
using namespace std;

int main(){


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

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

    system("pause");
    return 0 ;

}

实例3

#include<iostream>
using namespace std;

int main(){

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

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

    system("pause");
    return 0;
}

实例4

#include<iostream>
using namespace std;

int main(){

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

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

    system("pause");
    return 0;
}

在定义二维数组的时候,如果初始化了数据,可以省略行数,但是列数不可以省略。

八、函数

1、概述

作用:将一段经常使用的代码封装起来,减少重复代码。

一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。

2、函数的定义

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

  1. 返回值类型

  2. 函数名

  3. 参数表列

  4. 函数体语句

  5. return 表达式

语法

返回值类型  函数名(参数列表){
    
    函数体语句;
        
    return表达式;
}

实例

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

3、函数的构成

函数由部分构成:

  1. 返回值类型:即函数在执行完代码之后,返回什么类型的数据,例如 int,char,bool 等,特殊的,假如不需要返回类型,可以使用 void

  2. 函数名称:为了函数之后可以进行调用,因此函数名必不可少,命名要注意见名知意。

  3. 参数

    1. 形式参数(形参):是指在函数定义阶段,用以在函数内部进行运算的参数,作用是用来接收调用函数时所传递的实际参数,

    2. 实际参数(实参):是指在函数调用阶段,传递到函的具体的值,其作用是将实际参数传递给函数定义阶段的形参,以进行函数内部运算。

  4. 代码体:函数内部代码体用 { } 括起来。

  5. return:用来将运算结果进行一个返回,返回的值需要一个变量来进行接收。

4、函数的调用

功能:使用定义好的参数。

语法函数名(参数)

实例

#include<iostream>
using namespace std;

int add(int num1,int num2){		//函数的定义,其中num1,num2为形参
    int sum= 0 ;

    sum = num1 + num2;

    return sum;

}

int main(){

    int  sum = add(2,3);  //函数的调用,其中2,3为实参

    cout << sum <<endl;

    system("pause");
    return 0;
}

5、值传递

  • 所谓值传递,就是函数调用时实参将数值传入给形参。

  • 值传递的时候,形参发生改变,不会对实参造成影响

    这是因为,形参虽然只用来接收传递的实参,但是它确确实实在内存上开辟了一段空间,而实参也在内存上开辟了一段空间,这是分开的两段空间,可以理解为,传递的过程就是赋值的过程,整个过程就是实参开辟空间上的数值赋值给形参开辟的空间上,无论函数内部如何运转,都是在形参开辟空间上进行的,对原实参开辟的空间,并没有造成影响。

实例

#include<iostream>
using namespace std;

void swap(int num1,int num2){

    cout << "交换之前:" << endl;          //交换之前
    cout << "num1 = " << num1 << endl;      //num1 = 10
    cout << "num2 = " << num2 << endl;      //num2 = 20

    int temp = 0;
    temp = num1;
    num1 = num2;
    num2 = temp;

    cout << "交换之后:" << endl;           //交换之后
    cout << "num1 = " << num1 <<endl;       //num1 = 20
    cout << "num2 = " << num2 <<endl;       //num2 = 10

}

int main(){

    int a = 10;
    int b = 20;

    cout << "传递之前:" << endl;       	//传递之前
    cout << "a = " << a << endl;       	//a = 10
    cout << "b = " << b << endl;       	//b = 20

    swap(a,b);                     //传递,交换

    cout << "传递之后:" << endl;        //传递之后
    cout << "a = " << a << endl;       	//a = 10
    cout << "b = " << b << endl;       	//num2 =20


    system("pause");
    return 0;
}

6、函数的声明

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

main() 函数在定义函数之前的时候使用,函数可以声明很多次,但是只能定义一次。

实例

#include<iostream>
using namespace std;

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

int main(){

    int result = max (2,3);
    cout << result <<endl;

    system("pause");
    return 0;
}

int max(int a, int b){

    return a > b ? a : b;
}

九、函数的分文件编写

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

步骤

  1. 创建后缀名为 .h 的头文件:主要包含函数的声明以及 <iostream>

  2. 创建后缀名为 .cpp 的源文件:主要用以编写函数内容,函数的实现。

  3. 在头文件中写函数的声明。

  4. 在源文件中写函数的定义。

注意include 之后使用双引号 " " 表示包含自己定义的头文件

swap.h:

#include<iostream>
using namespace std;

void swap(int num1, int num2);

swap.cpp:

#include "swap.h"

void swap(int num1, int num2) {

    cout << "交换之前:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    int temp = 0;
    temp = num1;
    num1 = num2;
    num2 = temp;

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

}

main.cpp:

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

int main() {

    int a = 10;
    int b = 20;

    swap(a, b);                         

    system("pause");
    return 0;
}

理解:我们都知道头文件的作用就是在编写代码之前所做的预编译,以上述举例,就是在主函数中首先引用了名为 "swap.h" 的头文件,此时编译器会将 "swap.h" 内所有的声明首先进行预编译,而编译的内容必须在其它源文件中可以找到对应的函数实现,最后在主函数文件里面引入头文件,就可以实现不同 cpp 文件之间的连接,但是要注意,实现函数的 cpp 文件中的函数假如是类下的局部函数,则需要添加作用域名称,例如假如一个 cpp 函数中有一个名为 setR() 的函数,而这个函数并非全局函数,是定义在 类Circle 中的一个成员函数,那么此时就需要在该源文件中添加作用域变为Circle::setR(),否则就会报错。

十、指针

1、指针的基本概念

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

  • 内存编号是从 0 开始记录的,一般用十六进制数字表示。

  • 可以利用指针变量保存地址。

2、指针变量的定义及其使用

语法数据类型 * 变量名

实例

#include<iostream>
using namespace std;

int main(){

    int a = 10;
    int* p;         //定义一个指针p
    p = &a;         //将a的地址赋值给指针p

    cout <<"a的地址为:"<<&a<<endl;     //0x62fe14
    cout <<"p的值为:"<< p <<endl;      //0x62fe14

    //使用指针
    //可以通过解引用的方式来找到指针指向的内存
    //指针前加" * "代表解引用,找到指针指向的内存中的数据

    *p = 1000;
    cout <<"a="<<a<<endl;     
    cout <<"*p="<< *p <<endl;     

    system("pause");
    return 0 ;
}

3、指针所占内存空间

实例

#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(char*)=" << sizeof(char*) << endl;
	cout << "sizeof(float*)=" << sizeof(float*) << endl;
	cout << "sizeof(double*)=" << sizeof(double*) << endl;

	system("pause");
	return 0;
}

4、空指针和野指针

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

用途:初始化指针变量。

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

实例1:空指针

#include<iostream>
using namespace std;

int main() {

	//指针变量指向内存编号为0的空间
	int* p = NULL;

	//访问空指针报错
	//内存编号0~255为系统所占用内存,不允许用户访问
	cout << *p << endl;		//引发了异常: 读取访问权限冲突

	system("pause");
	return 0;
}

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

实例2:野指针

#include<iostream>
using namespace std;

int main() {

	//指针变量指向内存地址编号为0x1100的空间,但此前并未赋予访问权限
	int* p = (int*)0x1100;

	//访问野指针报错
	cout << *p << endl;		//读取访问权限冲突。


	system("pause");
	return 0;
}

5、const 修饰指针

const 关键字:将 const 之后的变量修饰为一个不可修改的常量,即可以修饰普通变量,也可以修饰指针变量。

const 修饰指针有三种情况:

  • const 修饰指针——常量指针:本质是一个指针,但是指向的内容是一个常量不可以修改。

  • const 修饰常量——指针常量:本质是一个常量,这个指针是一个常量,所以指针的指向不可以修改。

  • const 既修饰指针,又修饰常量。

常量指针

特点:指针的指向可以修改,指针指向的值不可以修改。

语法const int * p

实例

#include<iostream>
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	//const在指针之前
	const int* p = &a;
	//*p = 20;		//报错,*p不可以修改
	p = &b;			//可以,指针指向可以变
	
	system("pause");
	return 0;
}

指针常量

特点:指针的指向不可以修改,指针指向的值可以修改。

语法int * const p

实例

#include<iostream>
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	int* const p = &a;
	*p = 20;		//可以,指针指向的值可以修改
	//p = &b;		//错误,指针常量不可以修改指向

	system("pause");
	return 0;
}

const 修饰指针与常量

特点:指针指向以及指向的值都不可以修改。

语法const int * const p

#include<iostream>
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	const int* const p = &a;
	//*p = 20;		//错误,指针指向的值*p不可以修改
	//p = &b;		//错误,指针指向不可以修改


	system("pause");
	return 0;
}

巧记

  • const 在前就是常量指针,const 在后就是指针常量。

  • 常量 (const) 指针 (int *) —— const int * p

    const 修饰 *p,而 *p 是解引用,即这个变量的内容,因此,const 修饰这块内容是无法改变的。

  • 指针 (int *) 常量 (const) —— int * const p

    const 修饰指针 p ,而指针 p 也是一个变量,当用 const 修饰指针的时候,这个指针就是一个常量,因此指针的内容不可以更改,即指针的指向不可以更改。

意义

常量指针要比指针常量用的多,比如常量指针经常用在函数传参中,以避免函数内部修改内容。

6、指针和数组

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

实例

#include<iostream>
using namespace std;

//利用指针访问数组中的元素
int main() {
		
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int* p = arr;

	for (int i = 0; i < 10; i++) {
		cout << *p << endl;
		p++;	//指针向后移动一个数据类型(int)字节大小的位置
	}


	system("pause");
	return 0;
}

7、指针和函数

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

实例

#include<iostream>
using namespace std;


//交换函数
//值传递
void swap01(int num1, int num2) {
	int temp;
	temp = num1;
	num1 = num2;
	num2 = temp;

	//由值传递的函数,只会在内部进行交换,并不会影响实际传入的参数
}

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

	//由地址传递的函数,会对实际传入的参数造成影响
}

int main() {

		int a = 10;
		int b = 20;
		swap01(a, b);
		cout << "a="<<a << endl;
		cout << "b="<<b << endl;

		swap02(&a, &b);
		cout << "a=" << a << endl;
		cout << "b=" << b << endl;

	system("pause");
	return 0;
}

总结:依据需要选择传递方式,如果想修改实参的值,就使用地址传递,如果不想修改,就使用值传递。

8、指针,函数,数组

实例

#include<iostream>
using namespace std;

//冒泡排序	参数1:传递数组名,数组名即为数组首地址		参数2:传递数组长度
void bubbleSort(int* arr,int len) {
	for (int i = 0; i < len-1; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (arr[j]>arr[j+1]) {
				int temp;
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

//打印数组
void printArray(int* arr,int len) {
	for (int i = 0; i < len; i++) {
		cout << arr[i] << endl;
	}
}
int main() {

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

	bubbleSort(arr, len);	//冒泡排序实现升序
	printArray(arr, len);	//输出整个数组

	system("pause");
	return 0;
}

十一、结构体

1、结构体的基本概念

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

2、结构体的定义和使用

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

创建方式

  • struct 结构体名 变量名

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

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

实例

#include<iostream>
using namespace std;

//定义一个学生的数据类型
struct Student {
	string name;
	int age;
	int score;
}s3;

int main() {

	//创建一个学生类型的数据
	//方法一:struct Student  s1;
	struct Student s1;
	s1.age = 18;
	s1.name = "张三";
	s1.score = 100;
	cout << "年龄:" << s1.age << " 名字:" << s1.name << " 分数:" << s1.score << endl;

	//方法二:struct Student s2 = {按顺序添加参数},在数据类型使用阶段,struct关键字可以省略
	Student s2 = { "李四",19,90 };
	cout << "年龄:" << s2.age << " 名字:" << s2.name << " 分数:" << s2.score << endl;

	//方法三:在创建结构体的时候直接创建了变量,如上面结构体代码块的s3
	s3.age = 10;
	s3.name = "王五";
	s3.score = 70;
	cout << "年龄:" << s3.age << " 名字:" << s3.name << " 分数:" << s3.score << endl;


	system("pause");
	return 0;
}

3、结构体数组

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

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

实例

#include<iostream>
using namespace std;

//创建一个结构体
struct Student{
	string name;
	int age;
	int score;
};

int main() {

	/*Student stuArr[3] = {
		{"张三",18,100},
		{"李四",28,90},
		{"王五",38,80}
	};*/

	//通过for循环来输入结构体的内容
	Student stuArr[3];

	for (int i = 0; i < 3; i++) {
		cout << "请输入姓名:";
		string name;
		cin >> name;
		stuArr[i].name = name;

		cout << "请输入年龄:";
		int age;
		cin >> age;
		stuArr[i].age = age;

		cout << "请输入分数:";
		int score;
		cin >> score;
		stuArr[i].score = score;
	}

	//数组内容是可以进行更改的。
	//stuArr[2].name = "赵六";

	for (int i = 0; i < 3; i++) {
		cout << "姓名:" << stuArr[i].name << " 年龄:" << stuArr[i].age << " 分数:" << stuArr[i].score << endl;
	}

	system("pause");
	return 0;
}

4、结构体指针

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

  • 利用操作符 "->" 可以i通过结构体指针访问结构体属性。

实例

#include<iostream>
using namespace std;

//创建一个结构体
struct student {

	string name;
	int age;
	int score;
};
int main() {

	//创建一个结构体变量
	student s = { "张三",29,100 };
	//创建一个结构体指针,指针类型应为结构体数据类型
	student* p = &s;

	//使用“->"来进行指向
	cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;



	system("pause");
	return 0;
}

5、结构体嵌套结构体

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

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

实例

#include<iostream>
using namespace std;

//创建一个学生结构体
struct student {
	string name;
	int age;
	int score;
};

//创建一个教师结构体并嵌套学生结构体
struct teacher {
	string name;
	int id; //教师编号
	int age;	//教师年龄
	struct student stu;
};

int main() {

	//创建一个教师结构体变量
	teacher t1;
	t1.name = "老王";
	t1.age = 50;
	t1.id = 10000;
	t1.stu.age = 18;
	t1.stu.name = "小王";
	t1.stu.score = 100;

	cout << "教师姓名:" << t1.name << " 教师年龄:" << t1.age << " 教师编号:" << t1.id << endl<< "教师所带学生姓名:" << t1.stu.name << " 学生年龄:" << t1.stu.age << " 学生分数:" << t1.stu.score << endl;

	system("pause");
	return 0;
}

6、结构体做函数参数

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

传递方式有两种

  • 值传递

  • 地址传递

实例

#include<iostream>
using namespace std;

//创建一个学生结构体
struct Student {
	string name;
	int age;
	int score;
};

//打印方式一:值传递打印
void printStudent1(Student s) {
	cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.score << endl;
};

//打印方式二:地址传递打印
void printStudent2(Student*p) {
	cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
};

int main() {

	//创建一个学生结构体变量
	Student s;
	s.age = 20;
	s.name = "张三";
	s.score = 100;

	printStudent1(s);	//值传递打印
	printStudent2(&s);	//地址传递打印


	system("pause");
	return 0;
}

7、结构体中 const 使用场景

实例

#include<iostream>
using namespace std;

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

void printStudent(const student*s) {
	//s->age = 150;				//使用const修饰之后,就无法进行对值的修改,可以防止误操作
	cout << "年龄:" << s->age << " 姓名:"<<s->name << " 分数:" <<s->score<< endl;
};
int main() {

	student s;
	s.age = 19;
	s.name="张三";
	s.score = 80;

	printStudent(&s);


	system("pause");
	return 0;
}

8、结构体案例

实例

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

	学校正在做毕设项目,每名老师带领五个学生,总共有三个教师,需求如下:
	设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员,学生的成员有姓名、考试分数,
	创建数组存放三名老师	,通过函数给每个老师及所带的学生赋值,最终打印出老师数据以及老师所带的学生数据

*/

struct student {
	string name;	//学生姓名
	int score = 0;		//学生分数
};

struct teacher {
	string name;	//老师姓名
	student stu[5];
};

//给老师和学生赋值的函数
void allocateSpace(teacher* p, int len) {
	for (int i = 0; i < len; i++) {
		cout << "请输入第" << i + 1 << "个老师的名字:";
		cin >> p->name;
		for (int j = 0; j < 5; j++) {
			cout << "请输入" << p->name << "老师带的第" << j + 1 << "个学生姓名:";
			cin >> p->stu[j].name;
			cout << "请输入" << p->name << "老师带的第" << j + 1 << "个学生分数:";
			cin >> p->stu[j].score;
		}
		p++;
	}
};

void printinfo(teacher* p, int len) {
	for (int i = 0; i < len; i++) {
		cout << "老师姓名:" << p->name << endl;
		for (int j = 0; j < len; j++) {
			cout << "\t学生姓名:" << p->stu[j].name << " 考试分数:" << p->stu[j].score << endl;
		}
		p++;
	}
}
int main() {

	teacher tea[3];
	int len = sizeof(tea) / sizeof(tea[0]);
	allocateSpace(tea, len);
	printinfo(tea, len);
	system("pause");
	return 0;
}
posted @ 2025-12-31 14:07  Amireux77  阅读(1)  评论(0)    收藏  举报