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);
};
posted @   Kenny_LZK  阅读(456)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示