C++基础语法

C++初识

第一个C++程序

编写一个C++程序总共分为4个步骤

  • 创建项目
  • 创建文件
  • 编写代码
  • 运行程序

创建项目

Visual Studio是我们用来编写C++程序的工具

创建文件



编写代码

#include <iostream>
using namespace std;

int main() 
{
	cout << "hello world" << endl;

	/*
	main函数是一个程序的入口
	每个程序都必须有这么一个函数
	有且仅有一个
	*/

	system("pause");

	return 0;
}

运行程序

注释

作用:在代码中加一些说明和解释,方便自己或其他程序员阅读代码

两种格式

  1. 单行注释://说明信息

    • 通常放在一行代码上方,或者一条语句的末尾,对该代码说明
  2. 多行注释:/*说明信息*/

    • 通常放在一段代码的上方,对该段代码做整体说明

    编译器在执行代码时,会忽略注释的内容

变量

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

语法:数据类型 变量名 = 初始值;

示例

#include <iostream>
using namespace std;

int main() 
{
	//变量的创建语法:数据类型 变量名 = 变量初始值
	int a = 10;

	system("pause");

	return 0;
}

常量

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

C++定义常量两种方式

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

示例

#include <iostream>
using namespace std;
// 宏常量
#define day 7

int main() {

	cout << "一周总共有:" << day << "天" << endl;
    
	// const修饰变量
    
	const int year = 100;
    
	return 0;

}

关键字

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

  • 在定义变量或者常量的时候,不要使用关键字

标识符命名规则

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

  • 标识符不能是关键字

  • 标识符只能由字母、数字、下划线组成

  • 第一个字符必须为字母或者下划线

  • 标识符中字母区分大小写

    建议:给标识符命名时,争取见名知意的效果

数据类型

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

整型

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

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

数据类型 占用空间 取值范围
short(短整型) 2字节 -215~215-1
int(整型) 4字节 -231~231-1
long(长整型) win为4字节、Linux32位为4字节/64位为8字节 -231~231-1
long long(长长整型) 8字节 -263~263-1

sizeof关键字

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

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

示例

#include <iostream>
using namespace std;

int main() {

	int a = 5;

	cout << sizeof(a) << endl;

	cout << sizeof(int) << endl;
	
	const int year = 100;

	cout << sizeof(year) << endl;

	return 0;

}

实型(浮点型)

作用:用于表示小数

浮点型分为两种:

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

两者的区分在于表示的有效数字范围不同

数据类型 占用空间 有效数字范围
float 4bit 7为有效数字
double 8bit 15~16位有效数字
#include <iostream>
using namespace std;

int main() {

	// float
	float a = 5.6;

	cout << a << endl;

	// double
	double b = 5.6;

	cout << b << endl;

	//科学计数法表示
	float d = 3e2;   //代表 3 * 10 ^ 2

	cout << d << endl;
	

	return 0;

}

字符型

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

语法:char c = "a";

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

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

  • C++和C中字符型变量只占用1个字节
  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放到存储单元
#include <iostream>
using namespace std;

int main() {

	// 字符型
	char d = 'D';
	cout << d << endl;
	cout << (int)d << endl;  // 字符型对应ASCII编码

	/*
	char d = "D";  创建字符型变量时候,要用单引号
	char d = 'hello';  创建字符型变量时候,单引号内只能有一个数值
	*/
	system("pause");
	

	return 0;

}

转义字符

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

常用的转义字符有://、/t、/n

#include <iostream>
using namespace std;

int main() {

	// 换行符  \n
	cout << "Hello World \n";
	cout <<"Hello World" << endl;

	// 反斜杆 \\

	cout << "\\" << endl;

	// 水平制表符 \t  可以整齐输出数据
	cout << "Hello \t World";

	system("pause");
	return 0;

}

字符串型

作用:用于表示一串字符

两种风格

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

    #include <iostream>
    using namespace std;
    
    int main() {
    
    	char a[] = "hello world";  // 双引号
    	cout << a <<endl;
    	cout << sizeof(a) << endl;  // 12
    
    	system("pause");
    	return 0;
    
    }
    
  2. C++风格字符串:string 变量名 = "字符串值"

    #include <iostream>
    #include <string>  // 用C++风格字符串的时候,要包含这个头文件
    using namespace std;
    
    int main() {
    	
        // 包含一个头文件
    	string a = "hello world";
    	cout << a <<endl;
    	cout << sizeof(a) << endl;  // 40
    
    	system("pause");
    	return 0;
    
    }
    

布尔数据类型 bool

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

bool类型只有两个值

  • true:真(本质是1)
  • false:假(本质是0)

bool类型占一个字节大小

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	// 创建bool数据类型
	bool flag = true;  // true代表真
	cout << flag << endl;  // 本质上,1代表真的值,0代表假的值

	// 查看bool类型占用的内存空间
	cout << flag << endl;

	system("pause");
	return 0;

}

数据的输入

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

语法:cin >> 变量

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	// 整型
	int a = 0;
	cout << "请输入一个整数:";
	cin >> a;
	cout << "整型变量a = " << a << endl;

	// 字符串型
	string a = "hello";
	cout << "请输入一个字符串数:";
	cin >> a;
	cout << "字符串型变量a = " << a << endl;

	// bool型
	bool a = false;  // 非空即为真
	cout << "请输入一个bool数:";
	cin >> a;
	cout << "bool型变量a = " << a << endl;

	// 字符型
	char a = '0';
	cout << "请输入一个字符:";
	cin >> a;
	cout << "字符型变量a = " << a << endl;

	// 浮点型
	float a = 3.14f;
	cout << "请输入一个浮点数:";
	cin >> a;
	cout << "浮点型变量a = " << a << endl;

	system("pause");
	return 0;

}

运算符

作用:用于执行代码的运算

算术运算符

作用:用于处理四则运算

“+” 加, “-” 减, “/” 除, “*” 乘, “%” 取余, “++” 递增, “–“递减

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
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;

	system("pause");
	return 0;

}

++ 和 —

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	// ++ 递增
	int a = 10;
	++a;  // 让变量进行加一的结果,前置递增
	a++;  // 后置递增

	// 前置递增 先进行变量+1,后进行表达式的运算
	int b = 10;
	int c = ++b * 10;
	cout << "前置b=" << b << endl;
	cout << "前置c=" << c << endl;
	// 后置递增 先进行表达式的运算,后让变量+1
	int b1 = 10;
	int c1 = b1++ * 10;
	cout << "后置b=" << b1 << endl;
	cout << "后置c=" << c1 << endl;

	system("pause");
	return 0;

}

赋值运算符

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

“=” 等于, “+=” 加等于 , “-=” 减等于 , “/=” 除等于 , “%=” 余等于 , “*=” 乘等于

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	// +=
	a += b;  // 相当于:a = a + b
	cout << a << endl;

	// -=
	a -= b;  // 相当于:a = a - b
	cout << a << endl;

	// /=
	a /= b;  // 相当于:a = a / b 
	cout << a << endl;

	// *= 
	a *= b;  // 相当于a = a * b
	cout << a << endl;

	// =
	a = b - a;
	cout << a << endl;

}

比较运算符

“==”等于 , “<=” 小于等于, “>=” 大于等于 , “!=” 不等于 , “<” 小于 , “>” 大于

返回bool类型

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	// >=
	cout << (a >= b) << endl;

	// <=
	cout << (a <= b) << endl;

	// ==
	cout << (a == b) << endl;

	// != 
	cout << (a != b) << endl;

	// <
	cout << (a < b) << endl;

	// >
	cout << (a > b) << endl;

}

由于运算的优先级,要用括号隔开

逻辑运算符

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

“!” 非 , “&&” 与 , “||” 或

#include <iostream>
#include <string>  // 用C++风格字符串的时候,要包含这个头文件
using namespace std;

int main() {

	// 逻辑运算符

	// ! 真变假、假变真
	bool a = true;
	cout << !a<< endl;

	// && 两个都为真,则为真;同真则真,其余为假
	int a1 = 10;
	int b = 0;
	cout << (a1 && b) << endl;

	// || 只要有一个为真,则为真;同假则假,其余为真
	cout << (a1 || b) << endl;
    
    // 综合应用
   	cout << (a1 || !( a1 && ! a ) );

}

程序流程结构

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

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

选择结构

if语句

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

if语句的三种形式

  • 单行格式if语句
  • 多行格式if语句
  • 多条件的if语句

单行格式

#include <iostream>
using namespace std;

int main() {
	// 选择结构 单行if语句
    
	// 用户输入一个数字
	int num = 1;
	cout << "请输入一个数字:";
	cin >> num;

	// 判断数字是否大于100,是则输出原数
	if (num >= 100){  // 注意if语句后面不要加分号,否则,if将不会进行判断
		cout << num; 
	}
}

多行if语句

#include <iostream>
using namespace std;

int main() {
	// 选择结构 单行if语句
    
	// 用户输入一个数字
	int num = 1;
	cout << "请输入一个数字:";
	cin >> num;

	// 判断数字是否大于100,是则输出原数;否则,输出0
	if (num >= 100) {  // 注意if语句后面不要加分号,否则,if将不会进行判断
		cout << num << endl; 
	} 
    else {
        cout << "0" << endl;
    }
}

多条件if语句

#include <iostream>
using namespace std;

int main() {
	// 选择结构 单行if语句
    
	// 用户输入一个数字
	int num = 1;
	cout << "请输入一个数字:";
	cin >> num;

	// 判断数字是否大于600,是则输出原数;数字是否小于600,大于0,是则输出100;否则,输出0
	if (num >= 600) {  // 注意if语句后面不要加分号,否则,if将不会进行判断
		cout << num << endl; 
	} 
    else if (num >= 100) {
        cout << "100" << endl;
    }
    else {
        cout << "0" << endl;
    }
}

if ( 条件1 ) { 条件1满足执行语句} else if ( 条件2 ) { 条件2满足,同时条件1不满足,执行的语句 }··· else { 都不满足执行的语句 }

嵌套if语句

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

案例:输入3个数字,判断出最大的数字

#include <iostream>
using namespace std;

int main() {
	int num = 1;
	int num1 = 1;
	int num2 = 1;
	cout << "请输入三个数字:";
	cin >> num;
	cin >> num1;
	cin >> num2;

	if ( num > num1 ) {  // 判断 num 和 num1
		if ( num > num2 ) {  // 判断 num 和 num2
			cout << num << "最大" << endl;
		}
		else {
			cout << num2 << "最大" << endl;
		}
	}
	else {
		if (num1 > num2) {
			cout << num1 << "最大" << endl;
		}
		else {
			cout << num2 << "最大" << endl;
		}
		cout << "判断完毕" << endl;
	}
}

三目运算符

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

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

#include <iostream>
using namespace std;

int main() {
	
	// 三目运算
	
	// 将 a 和 b 做比较,将大的值赋值给c
	int a = 10;
	int b = 20;
	int c = 0;

	c = a > b ? a : b;  // 如果 a 比 b 大,则将a赋值给c
    
    /*
    if ( a > b ) {
    	c = a;
    }
    else {
    	c = b
    }
    */

}

在C++中,三目运算符返回的是变量,可以继续赋值

switch语句

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

语法:

switch ( 表达式 ) {
    case 结果1: 执行语句; break;  // switch里面不一定每个case都要对应break,break的作用的向外跳出一层
    ······
    default: 执行语句; break;  // 不一定需要default判断
} 

示例

#include <iostream>
using namespace std;

int main() {
	
	// switch 语句

	// 电影打分
	int score = 0;
	cout << "请输入分数:";
	cin >> score;
	cout << "您打的分数为:" << score << endl;

	switch (score) {
	case 10:
			cout << "是经典电影" << endl;
			break;  // 退出当前分支,如果没有break,则会继续向下运行
	default:  // 当所有条件不满足时,执行该语句
			cout << "普通" << endl;

	}

}

缺点:判断的时候,只能是整型或者字符型,不可以是一个区间

优点:结构清晰,执行效率高

注意

  • switch语句中表达式类型只能是整型或者字符型
  • case里如果没有break,那么程序会一直向下执行

循环结构

while循环语句

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

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

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

#include <iostream>
using namespace std;

int main() {

	int nu = 0;
		// 在屏幕中打印0到9的数字
	while ( nu < 10 )
	{
		cout << nu << endl;
		nu++;
	}
}
猜数字游戏
#include <iostream>
using namespace std;
// time系统时间头文件包含
#include <ctime>

int main() {

	// 添加随机数的种子,利用当前系统时间生成随机数,防止每次随机数一样
	srand((unsigned int)time(NULL));

	// 系统生成随机数
	int rand_nu = rand() % 100 + 1; // rand()%100生成0到99的随机数

	// 猜测数字
	int guess_nu = 0;
	while (guess_nu != rand_nu) {
		cout << "请输入一个数字:";
		cin >> guess_nu;
		// 判断
		if (guess_nu > rand_nu) {
			cout << "输大了,请重新猜测!!!" << endl;
		}
		else if (guess_nu < rand_nu){
			cout << "输小了,请重新猜测!!!" << endl;
		}
		else {
			cout << "恭喜你,猜对了!!!" << endl;
			break;
		}
	}
}

do···while循环语句

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

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

注意:与while的区别在于do…while会先执行一次循环时间,在判断循环条件

#include <iostream>
using namespace std;

int main() {

	// do...while语句
	// 在屏幕中输出 0 到 9 这10个数字
	int num = 0;

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

水仙花数

水仙花数是指一个三位数,它的每个位上的数字的3次幂之和等于它本身

如:1 ^ 3 + 5 ^ 3 + 3 ^ 3 = 153

#include <iostream>
using namespace std;


int main() {

	int nu = 100;
	// 水仙花数
	do {
		int ge = 0;  // 定义个位的数字
		int shi = 0;  // 定义十位的数字 
		int bai = 0;  // 定义百位的数字
		
		ge = nu % 10;
		shi = nu / 10 % 10;
		bai = nu / 100;

			if (ge*ge*ge + shi*shi*shi + bai*bai*bai == nu){
				cout << "水仙花数:" << nu << endl;
			}
			nu++;

	} while ( nu <= 999 );
}

for循环语句

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

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

#include <iostream>
using namespace std;


int main() {

	// for循环
	// 从数字0打印到9

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

	// 也可以
	int i = 0;
	for (;;) {
		if (i >= 10) {
			break;
		}
		cout << i << endl;
		i++;
	}
}

案例:敲桌子

从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余的打印输出

#include <iostream>
using namespace std;


int main() {
	// 从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余的打印输出

	for (int i = 1; i < 100; i++) {
		if (i % 10 == 7 || i % 100 / 10 == 7 || i % 7 == 0) {
			cout << "敲桌子" << endl;
		}
		else {
			cout << i << endl;
		}
	}
}

嵌套循环

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

#include <iostream>
using namespace std;


int main() {

	// 嵌套循环
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			cout << "*";
		}
		cout << "" << endl;
	}

}

打印九九乘法口诀表

#include <iostream>
using namespace std;


int main() {

	// 嵌套循环
	for (int i = 1; i < 10; i++) {
		for (int j = 1; j < i+1; j++) {
			cout << i << "*" << j << "=" << i * j << "\t";
		}
		cout << "" << endl;
	}
}

跳转语句

break语句

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

break使用的时机:

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

continue语句

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

#include <iostream>
using namespace std;


int main() {
	
	for (int i = 0; i <= 10; i++) {
		if (i % 2 == 0) {
			continue;
		}
		else {
			cout << i << "\t";
		}
	}

}

goto语句

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

语法:goto 标记;

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

#include <iostream>
using namespace std;


int main() {
	
	// goto
	cout << "hello" << endl;
	cout << "hello" << endl;
	cout << "hello" << endl;
	goto flag;
	cout << "hello" << endl;
	cout << "hello" << endl;
flag:
	cout << "world";
}

数组

概述

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

特点

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

一维数组

定义方式

  1. 数据类型 数组名[ 数组长度 ];
  2. 数组类型 数组名[ 数组长度 ] = {值1, 值2...};
  3. 数组类型 数组名[ ] = {值1, 值2...}
#include <iostream>
using namespace std;


int main() {
	
	// 1. 数据类型 数组名[ 数组长度 ];
	int arr[4];
	arr[0] = 10;  // 赋值操作

	// 2. 数组类型 数组名[ 数组长度 ] = {值1, 值2...};
	int arr1[5] = { 2, 2, 10, 20 };  // 如果在初始化数据的时候,没有全部填完,会用0来填补剩余数据
	cout << arr1[0] << endl;  // 通过下标索引取值

	// 利用循环取值
	for (int i = 0; i < 5; i++) {
		cout << arr1[i] << endl;  
	}
}

定义数组的时候必须有一个初始的长度

数组名的命名规范与变量名命名规范一致,不要和变量重名

数组中下标是从0开始索引

数组名

一维数组名称的用途:

  1. 可以统计整数组在内存中的长度
  2. 可以获取数组在内存中的首地址
#include <iostream>
using namespace std;


int main() {

	int arr[5] = { 2, 2, 10, 20 };
	cout << "数组所占空间为" << sizeof(arr) << "\n" << "里面有" << (sizeof(arr) / sizeof(arr[0])) << "个元素" << endl;
	cout << "数组的首地址为" << (int)arr << "\n每个元素所占空间为" << sizeof(arr[0]) << "\n数组中第一个元素的地址为" << (int)&arr[0] << endl;
}

数组名是一个常量,不可以进行赋值的操作

案例

找出数组中的最大的元素
#include <iostream>
using namespace std;


int main() {
	//找出数组中最大的数字
	int max_nu = 0;  // max_nu用于存储最大值
	int arr[5] = { 300, 350, 200, 400, 250 };
	for (int i = 0; i < ((sizeof(arr) / sizeof(arr[0]))-1); i++) {
		max_nu = arr[i] > arr[i + 1] ? arr[i] : arr[i + 1];
	}
	cout << max_nu << endl;
}
组元素逆置

将数组中的元素首尾进行互换

#include <iostream>
using namespace std;


int main() {
	// 数组里面的内容逆转
	int arr1[5] = { 300, 350, 200, 400, 250 };
	int end = sizeof(arr1) / sizeof(arr1[0]);  // 末尾下标
	int start = 0;  // 起始下标
	while (start < end) {
		int temp = arr1[start];
		arr1[start] = arr1[end];
		arr1[end] = temp;
		start++;
		end--;
	}
	for (int i = 0; i < (sizeof(arr1) / sizeof(arr1[0])); i++) {
	cout << arr1[i] << endl;
	}
}

冒泡排序

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

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

排序 int arr = { 4, 2, 8, 0, 5, 7, 1, 3, 9};

#include <iostream>
using namespace std;


int main() {
	// 利用冒泡排序,实现升序排序
	int arr[ ] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
	cout << "排序前:";
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << arr[i] << "  ";
	}
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0]) - 1); i++) {  // 排序次数为元素个数减一
		for (int j = 0; j < (sizeof(arr) / sizeof(arr[0]) - 1 - i); j++) {  // 内层循环对比次数元素个数 - 排序次数 - 1
			if (arr[j] > arr[j + 1]) {  // 如果前一个数字比第二个数字大,交换顺序
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	cout << "排序后:";
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << arr[i] << "  ";
	}
}

二维数组

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

定义方式

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

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

#include <iostream>
using namespace std;


int main() {
	// 1. `数据类型 数组名 [ 行数 ] [ 列数 ];` 
	int arr1[2][3];
	// 2. `数据类型 数组名[行数][列数] = { { 数据1, 数据2 }, {数据3, 数据4} }; `
	int arr2[2][3] = {
		{1, 2 ,3},
		{4, 5, 6}
	};
	// 二次循环,外层循环打印行数,内层循环打印列数
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
	// 3. `数据类型 数组名[行数][列数] = { 数据1, 数据2, 数据3, 数据4 }; `
	int arr3[2][3] = { 1, 2, 3, 4, 5, 6 };
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
	// 4. `数据类型 数组名[][列数] = { 数据1, 数据2, 数据3, 数据4 }; `
	int arr3[2][3] = { 1, 2, 3, 4, 5, 6 };
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
}

数组名

  • 查看二维数组所占内存空间
  • 获取二维数组首地址
#include <iostream>
using namespace std;


int main() {
	int arr2[2][3] = {
	{1, 2 ,3},
	{4, 5, 6}
	};
	// 查看占用内存
	cout << "二维数组占用内存空间为:" << sizeof(arr2) << endl;
	cout << "二维数组第一行占用内存为:" << sizeof(arr2[0]) << endl;
	cout << "二维数组第一个元素占用的内存为:" << sizeof(arr2[0][0]) << endl;
	
	cout << "二位数组的一行的元素数量为:" << sizeof(arr2[0]) / sizeof(arr2[0][0]) << endl << "二维数组的行数为:" << sizeof(arr2) / sizeof(arr2[0]) << endl;

	// 查看二维数组的首地址
	cout << "二维数组首地址为:" << (int)arr2 << endl;
	cout << "二维数组第一行的首地址为:" << (int)arr2[0] << endl;
	cout << "二维数组第一个元素的首地址为:" << (int)&arr2[0][0];
}

案例

有一个数组 int arr[3][3] = {{100, 100, 100}, {90, 50, 100}, {60, 70, 80}}

计算该数组每一行的总和

#include <iostream>
using namespace std;


int main() {
	// 求数组中每一行内数字的总和
	int arr[3][3] = {
		{100, 100, 100},
		{90, 50, 100},
		{60, 70, 80}
	};

	// 二次循环,得到数组中的每一个值
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		int sum = 0;
		for (int j = 0; j < (sizeof(arr[0]) / sizeof(arr[0][0])); j++) {
			sum += arr[i][j];
		};
		cout << "第" << (i + 1) << "行的和为:" << sum <<endl;
	};

}

函数

概述

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

函数的定义

函数的定义一般主要有5个步骤

  1. 返回值类型
  2. 函数名
  3. 参数系列
  4. 函数体语句
  5. return表达式

语法

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

实现一个加法的函数,传入两个整型数值,计算数据相加的结果,并且返回

#include <iostream>
using namespace std;


// 函数体
int add(int num1, int num2) {
	return num1 + num2;
}

函数的调用

功能:使用定义好的函数

语法:函数名(参数)

#include <iostream>
using namespace std;


// 函数体
int add(int num1, int num2) {  // 函数定义里面的参数没有实际值,称为形参(形式参数)
	return num1 + num2;
}

int main() {
	cout << add(1, 2) << endl;  // 在main函数中调用add函数,其中,1和2为实参(实际参数),位置要一一对应
}

值传递

  • 所谓值传递,就是函数调用时实参将数值传入给形参
  • 值传递时,如果形参发生改变,不会影响实参
#include <iostream>
using namespace std;


/* 
值传递
定义函数,实现两个数字进行交换函数
如果函数不需要返回值声明的时候可以写void
*/
void swap(int num1, int num2) {
	cout << "交换前的数字" << endl << "num1:" << num1 << "\tnum2:" << num2;
	int temp = num1;
	num1 = num2;
	num2 = temp;
	cout << "\n交换后的数字" << endl << "num1:" << num1 << "\tnum2:" << num2;
}

int main() {
	int num1 = 10;
	int num2 = 20;
	cout << "未调用前的数字" << endl << "num1:" << num1 << "\tnum2:" << num2 << endl;  // 当我们做值传递的时候,函数的形参发生改变,并不会影响形参
	swap(num2, num1);
}

函数的常见样式

常见的函数样式有4种

  1. 有参无返
  2. 无参无返
  3. 无参有返
  4. 有参有返
#include <iostream>
#include <string>
using namespace std;


// 1. 有参无返
void test01(string str) {
	cout << str << endl;
}
// 2. 无参无返
void test02() {
	cout << "this is test02" << endl;
}
// 3. 无参有返
int test03() {
	return 100;
}
// 4. 有参有返
int test04(int num1, int num2) {
	return num1 * num2;
}

int main() {
	// 1. 有参无返调用
	test01("hello world");
	// 2. 无参无返调用
	test02();
	// 3. 有参无返调用
	cout << test03() << endl;
	// 4. 有参有返调用
	cout << test04(2, 3) << endl;
}

函数的声明

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

  • 函数声明可以多次,但是函数的定义只能有一次
#include <iostream>
#include <string>
using namespace std;


// 函数声明:提前告诉编译器函数的存在
// 函数声明-->如果没有该声明那么函数将不会调用
int max(int num1, int num2);

int main() {
	int a = 10;
	int b = 20;
	cout << max(a, b) << endl;
}

// 比较函数,实现两个整型数字进行比较,返回较大的数字
int max(int num1, int num2) {
	return num1 > num2 ? num1 : num2;
}

函数的分文件编写

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

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

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

#include "标头.h"
 

// 比较函数,实现两个整型数字进行比较,返回较大的数字,函数定义
int max(int num1, int num2) {
	return num1 > num2 ? num1 : num2;
}


/* 新建的头文件中(名称为标头.h) */

#include <iostream>
using namespace std;

int max(int num1, int num2);


/* 运行文件中 */

#include "标头.h"


int main() {
	int a = 10;
	int b = 20;
	cout << max(a, b) << endl;
}

指针

基本概念

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

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

定义和使用

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

#include <iostream>
using namespace std;


int main() {
	// 定义一个指针
	int a = 10;
	// 指针定义语法:数据类型 * 变量名
	int * p;
	// 让指针记录变量a的地址
	p = &a;  // & 取址符号
	cout << "a的地址为:" << &a << endl;
	cout << "指针p的值为:" << p << endl;
	// 使用指针
	// 可以通过解引用的方式来找到指针指向的内存
	// 指针前加 * 代表解引用,找到指针指向的内存中的数据
	*p = 100;
	cout << "a等于:" << a << "\n*p等于" << *p << endl;
}

指针所占的内存空间

#include <iostream>
using namespace std;


// 在32位操作系统下,指针占4bit,不管是什么数据类型
// 在64位操作系统下,指针占8bit
int main() {
	int a = 10;
	int * p = &a;
	cout << "int *:" << sizeof(int*) << endl;
    cout << "char *:" << sizeof(char*) << endl;
	cout << "p:" << sizeof(p) << endl;
}

空指针和隐指针

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

用途:初始化指针变量

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

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

#include <iostream>
using namespace std;


int main() {
	// 空指针
	// 空指针用于给指针对象初始化
	int* p1 = NULL;
	// 空指针不能被访问,其被系统占用

	// 野指针
	// 在程序中一定要避免野指针
	int * p = (int *)0x1100;
}

const修饰指针

const修饰指针有三种情况

  1. const修饰指针 –常量指针const int * p = &a
    • 指针的指向可以修改,但是指向的值不可以修改
  2. const修饰常量 –指针常量int * const p = &a
    • 指针的指向不可以改,指针的值可以改
  3. const即修饰指针 ,又修饰常量
#include <iostream>
using namespace std;


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

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

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

记忆方法:看const右侧紧跟的是指针还是常量,是指针就是常量指针,是常量就是指针常量

指针和数组

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

#include <iostream>
using namespace std;


int main() {
	// 指针和数组
	// 利用指针访问数组中的元素

	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	cout << "第一个元素为:" << arr[0] << endl;

	int* p = arr;  // arr就是数组的首地址

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

	p++;  // 让指针偏移4bit
	 
	cout << "利用指针访问第二个元素:" << *p << endl;

	// 利用指针来访问数组,也可以通过p1[索引值来访问]
	int* p1 = arr;
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << *p1++ << "  ";
	}
    for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << p1[i] << "  ";
	}

}

指针和函数

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

#include <iostream>
using namespace std;


void swap(int* p1, int* p2) {
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main() {
	// 函数和指针
	// 地址传递
	int a = 10;
	int b = 30;
	cout << "a:" << a << " b:" << b << endl;
	swap(&a, &b);
	cout << "after a:" << a << " b:" << b << endl;  // 地址中的内存发生改变
}

指针、数组、函数

封装一个函数,利用冒泡排序,实现对整型数组的升序排序

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

#include <iostream>
using namespace std;


// 冒泡排序函数
void sort(int * arr, int length) {  // 参数为数组的内存地址
	for (int i = 0; i < length - 1; i++) {
		for (int j = 0; j < length - i - 1; j++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}
}
// 打印数组
void print(int* arr, int length) {
	for (int i = 0; i < length; i++) {
		cout << arr[i] << " ";
	}
}

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

结构体

基本概念

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

定义和使用

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

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

  • struct 结构体名 变量名
  • struct 结构体名 变量名 = { 成员值1, 成员值2, ... }
  • 定义结构体是顺便创建变量
#include <iostream>
#include <string>
using namespace std;


// 创建学生的数据类型:包括(姓名、年龄、分数)
// 自定义数据类型,一些类型集合组成的一个数据类型
struct Student  
{
	// 成员列表
	string name;  // name
	int age;  // age
	int score;  // score
}s3;  // 顺便创建结构体变量

int main() {
	// 通过学生类型创建具体学生
	// struct Student s1
	struct Student s1;  // struct关键字可以省略,但是定义的时候不能省略
	// 给s1属性赋值,通过.访问结构变量中的属性
	s1.name = "张三";
	s1.age = 18;
	s1.score = 90;
	cout << "name:" << s1.name << " age:" << s1.age << " score:" << s1.score << endl;

	// struct Stufent s2 = { ... }
	struct Student s2 = { "李四", 18, 80 };
	cout << "name:" << s2.name << " age:" << s2.age << " score:" << s2.score << endl;

	// 在定义接哦古体是顺便创建结构体变量
	s3.name = "王五";
	s3.age = 18;
	s3.score = 85;
	cout << "name:" << s3.name << " age:" << s3.age << " score:" << s3.score << endl;
}

结构体数组

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

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

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


// 结构体数组
// 定义结构体数组
struct Student
{
	string name;
	int age;
	int score;
};

int main() {

	// 创建结构体数组
	struct Student stuArray[3] = {	// 给结构体数组赋值
		{"zhangsan", 18, 100},
		{"lisi", 19, 99},
		{"wangwu", 20, 85}
	};

	// 修改值
	stuArray[2].name = "lihua";
	stuArray[2].age = 19;
	stuArray[2].score = 89;

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

结构体指针

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

  • 利用操作符 ->可以通过结构体指针访问结构体属性
#include <iostream>
#include <string>
using namespace std;


// 结构体指针

// 定义学生的结构体
struct Student
{
	string name;
	int age;
	int score;
};

int main() {

	// 创建学生结构体变量

	struct Student s = { "zhangsan", 18, 99 };

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

	// 通过指针指向访问结构体变量中的数据
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
}

结构体嵌套结构体

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

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

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


// 结构体指针

// 定义学生的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 定义老师结构体
struct Treacher
{
	int id;
	string name;
	int age;
	struct Student stu;  // 辅导学生
};

int main() {

	// 结构嵌套结构体
	// 创建老师对象
	struct Treacher t;
	t.id = 100000;
	t.name = "老王";
	t.age = 58;
	t.stu.name = "小王";
	t.stu.age = 16;
	t.stu.score = 60;

	cout << "tea_name:" << t.name << "  tea_id:" << t.id << "  tea_age:" << t.age << "\nstu_name:" << t.stu.name << "  stu_age:" << t.stu.age << "  stu_score:" << t.stu.score << endl;
}

结构体做函数参数

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

传递的方式有两种

  • 值传递
  • 地址传递
#include <iostream>
#include <string>
using namespace std;



// 定义学生的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 打印学生信息的函数,值传递
void printStuInfo(Student stu) {
	stu.age = 100;
	cout << "name:" << stu.name << "  age:" << stu.age << "  score:" << stu.score << endl;
};

// 地址传递:形参修改会引起实参的改变
void printStudentInfo2(Student* p) {
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
};


int main() {

	// 结构体做函数的参数
	// 将学生传入到一个参数中,打印学生身上的所有信息

	// 创建结构体变量
	struct Student stu;
	stu.name = "zhangsan";
	stu.age = 20;
	stu.score = 85;
	cout << "值传递" << endl;
	printStuInfo(stu);
	cout << "地址传递" << endl;
	printStudentInfo2(&stu);
}

结构体中const使用场景

作用:用const来防止五操作

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



// 定义学生的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 地址传递,节省空间
void printStudentInfo2(const Student* p) {  // 加入const之后,一旦有修改的操作就会报错,可以防止我们的误操作
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
};


int main() {

	// const使用场景

	// 创建结构体变量
	struct Student stu;
	stu.name = "zhangsan";
	stu.age = 20;
	stu.score = 85;
	printStudentInfo2(&stu);
}

结构体案例

案例一

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



// 定义学生的结构体
struct Student
{
	string name;
	int score;
};

// 老师结构定义
struct Teacher
{
	string name;
	Student stuArray[5];
};

// 给老师和学生赋值的函数
void allocateSpace(Teacher tArray[], int len) {
	// 给老师赋值
	string name = "abcde";
	for (int i = 0; i < len; i++) {
		tArray[i].name = "Teacher_";
		tArray[i].name += name[i];  // 字符串的取值
		
		// 给每名学生赋值
		for (int j = 0; j < 5; j++) {
			tArray[i].stuArray[j].name = "Student_";
			tArray[i].stuArray[j].name += name[j];

			int random = rand() % 61 + 40;  // 40-99
			tArray[i].stuArray[j].score = random;
		}
	};
};

// 打印学生和老师的信息
void printInfo(Teacher* tArray, int len) {
	for (int i = 0; i < len; i++) {
		cout << "teacher_name:" << tArray[i].name << endl;
		for (int j = 0; j < 5; j++) {
			cout << "stu_name:" << tArray[i].stuArray[j].name << "  stu_score:" << tArray[i].stuArray[j].score << endl;
		};
		cout << "--------------------------------------------------------------------------------" << endl;
	};
}

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

	// 三名老师数组
	Teacher tArray[3]; 
	
	// 通过函数给老师的信息赋值,并给老师带的学生信息赋值
	int len = sizeof(tArray) / sizeof(tArray[0]);
	allocateSpace(tArray, len);
	printInfo(tArray, len);
}

案例二

有五个学生,通过冒泡排序的方法,将数组中的学生按照年龄进行升序排序,最终打印排序后的结果

{ {“stu1”, 23}, {“stu2”, 22}, {“stu3”, 20}, {“stu4”, 21}, {“stu5”, 19} }

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



// 定义学生的结构体
struct Student
{
	string name;
	int age;
};

// 排序
void sort(Student* stuArray, int len) {
	for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (stuArray[j].age > stuArray[j + 1].age) {
				struct Student temp = stuArray[j];
				stuArray[j] = stuArray[j + 1];
				stuArray[j + 1] = temp;
			};
		};
	};
};

// 输出
void printInfo(const Student * stuArray, int len) {
	for (int i = 0; i < len; i++) {
		cout << "name:" << stuArray[i].name << "  age:" << stuArray[i].age << endl;
	};
};


int main() {
	// 创建数组存放五名学生
	Student stuArray[] = {
		{"stu1", 23},
		{"stu2", 22},
		{"stu3", 20},
		{"stu4", 21},
		{"stu5", 19}
	};
	int len = sizeof(stuArray) / sizeof(stuArray[0]);
	sort(stuArray, len);
	printInfo(stuArray, len);
};
Tags: