C++基础语法
C++初识
第一个C++程序
编写一个C++程序总共分为4个步骤
- 创建项目
- 创建文件
- 编写代码
- 运行程序
创建项目
Visual Studio是我们用来编写C++程序的工具
创建文件
编写代码
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
/*
main函数是一个程序的入口
每个程序都必须有这么一个函数
有且仅有一个
*/
system("pause");
return 0;
}
运行程序
注释
作用:在代码中加一些说明和解释,方便自己或其他程序员阅读代码
两种格式
-
单行注释://说明信息
- 通常放在一行代码上方,或者一条语句的末尾,对该代码说明
-
多行注释:/*说明信息*/
- 通常放在一段代码的上方,对该段代码做整体说明
编译器在执行代码时,会忽略注释的内容
变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
示例
#include <iostream>
using namespace std;
int main()
{
//变量的创建语法:数据类型 变量名 = 变量初始值
int a = 10;
system("pause");
return 0;
}
常量
作用:用于记录程序中不可更改的数据
C++定义常量两种方式
#define
宏常量:#define
常量名 常量值- 通常在文件上方定义,表示一个常量
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;
}
实型(浮点型)
作用:用于表示小数
浮点型分为两种:
- 单精度
float
- 双精度
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;
}
字符串型
作用:用于表示一串字符
两种风格
-
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; }
-
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...}
#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开始索引
数组名
一维数组名称的用途:
- 可以统计整数组在内存中的长度
- 可以获取数组在内存中的首地址
#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,直到不需要比较
排序 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 }, {数据3, 数据4}} ;
数据类型 数组名 [ 行数 ] [ 列数 ] = {数据1, 数据2, 数据3, 数据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个步骤
- 返回值类型
- 函数名
- 参数系列
- 函数体语句
- 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种
- 有参无返
- 无参无返
- 无参有返
- 有参有返
#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个步骤
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在新的源文件中写函数的定义
/* 新建的源文件中 */
#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修饰指针有三种情况
- const修饰指针 --常量指针
const int * p = &a
- 指针的指向可以修改,但是指向的值不可以修改
- const修饰常量 --指针常量
int * const p = &a
- 指针的指向不可以改,指针的值可以改
- 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);
};
本文来自博客园,作者:Kenny_LZK,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/15799465.html