(内容来自小破站《黑马程序员C++》复习自用,从入门到劝退)
作用:讲一段经常使用的代码封装起来,减少重复代码。
// 语法:
返回值类型 函数名(参数列表){
函数体语句
return表达式
}
int add(int num1, int num2) {
int sum = num1 + num2;
return sum;
}
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
//main函数中调用add函数
int a = 10;
int b = 20;
//函数调用语法:函数名称(参数)
//ab成为“实际参数”,简称“实参”、
//当调用函数的时候,实参的值会传递给形参,计算结果给c
int c = add(a, b);
cout << "c = " << c << endl;
system("pause");
return 0;
}
值传递,就在函数调用的时候,实参将数值传给形参,值传递时,如果形参发生改变,并不会影响实参。
#include
using namespace std;
#include
//定义函数,实现两个数字进行交换函数
//如果函数不需要返回值,声明的时候可以谢void
void swap(int num1, int num2)
{
cout << "交换前: " << endl;
cout << "num1 = " << num1 << endl; cout << "num2 = " << num2 << endl;
int temp = num1; num1 = num2; num2 = temp;
cout << "交换后: " << endl;
cout << "num1 = " << num1 << endl; cout << "num2 = " << num2 << endl;
temp = num1; num1 = num2; num2 = temp;
return;//返回值不需要的时候,可以不写return
}
int main()
{
int a = 10; int b = 20;
cout << "a = " << a << endl; cout << "b = " << b << endl;
swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << " 值传递时,如果形参发生改变,并不会影响实参" << endl;
system("pause");
return 0;
}
#include
using namespace std;
#include
//1. 无参无返
void test01() {
cout << "this is test01" << endl;
}
//2. 有参无返
void test02(int a) {
cout << "this is test02, a = " << a << endl;
}
//3. 无参有返
int test03() {
cout << "this is test03, and ";
return 200;
}
//4. 有参有返
int test04(int a) {
cout << "this is test04, and a = " << a << endl;
return a;
}
//函数调用
int main() {
test01();
test02(100);
int num03 = test03();
cout << "num03 = " << num03 << endl;
int num04 = test04(404);
cout << "num04 = " << num04 << endl;
system("pause");
return 0;
}
作用:告诉编译器函数名称以及如何调用函数,函数的实际主体可以单独定义。函数的声明可以多次,到那时函数的定义只能有一次。
#include
using namespace std;
#include
//比较函数,两个整型数字比较,返回较大值
//声明可以写很多次,但是定义只能写一次
int maax(int a, int b);
int maax(int a, int b);
int maax(int a, int b);
//定义
int maax(int a, int b)
{
return a > b ? a : b;
}
//int maax(int a, int b) }
//错的,定义只能写一次
// return a > b ? a : b;
//}
int main() {
int a = 10;
int b = 20;
cout << maax(a, b) << endl;
system("pause");
return 0;
}
作用:让代码结构更加清晰。
作用:可以通过指针间接访问内存
内存编号是从0开始记录的,一般用十六进制数字表示,可以利用指针变量保存地址
语法:数据类型 * 变量名;
#include
using namespace std;
#include
int main() {
//1.定义指针
int a = 10;
//指针定义的语法:数据类型 * 指针变量;
int* p;
//让指针记录变量a的地址,&是取指符号
cout << "a的地址为:" << &a << endl << endl;
p = &a;
cout << "指针p为:" << p << endl << endl;
//2.使用指针
//可以通过解引用的方式来找到指针指向的内存(指针前加一个*)。
*p = 1000;
cout << "a = " << a << endl << endl;
cout << "*p = " << *p << endl << endl;
system("pause");
return 0;
}
指针也是种数据类型
#include
using namespace std;
#include
int main() {
//指针所占内存空间
int a = 10;
int* p = &a;
//在32位操作系统下,指针占4个字节空间大小,不论什么数据类型,64位-8个字节。
cout << "sizeof (int *) = " << sizeof(p) << endl;
cout << "sizeof (float *) = " << sizeof(float*) << endl;
cout << "sizeof (double *) = " << sizeof(double*) << endl;
cout << "sizeof (char *) = " << sizeof(char*) << endl;
system("pause");
return 0;
}
空指针:指针变量指向内存中编号为零的空间。
用途:初始化指针变量。
注意:空指针指向的内存是不可以访问的。
野指针:指针变量指向非法的内存空间
三种情况:
① const 修饰指针——常量指针;
② const 修饰常量——指针常量;
③ const即修饰指针——又修饰常量。
int a = 10;
int b = 10;
int * p = &a;
说明:创建变量a,存放了10,b存放了10,a的地址编号是0x0011,b的地址编号是0x0022,p指向的是a,保存的就是a的地址0x0011。const修饰指针,就是在指针的前边加一个const。
const int * p = &a; //常量指针// 特点:指针的指向可以修改,但是指针指向的值不可以修改。
判断正误:
*p = 20;
// *p是对p指向的内存进行操作,p指向的0x0011,想把10要改成20。
P = &b;
// 正确,指针的指向可以更改
int * const p = &a; //这种形式是指针常量
// 特点:指针的指向不可以改,但是指针指向的值可以修改。
const int * const p = &a;
// 特点:指针的指向,和,指针指向的值,都不可以修改
目的:利用指针访问数组中的每一个元素。(数组是一段连续的空间中,存放了相同类型的数据元素)
#include
using namespace std;
#include
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素为: " << arr[0] << endl; //正常访问数组内第一个元素。
int* p = arr; //arr就是数组名就是数组的首地址,*p解引用,就能解出来数组的第一个数据。
cout << "利用指针访问第一个元素为: " << *p << endl;
p++; //让指针向后偏移四个字节
cout << "利用指针访问第二个元素为: " << *p << endl << endl;
cout << "开始利用指针遍历数组" << endl;
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
//cout << arr[i] << endl;
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
作用:利用指针作函数参数,可以修改实参的值
#include
using namespace std;
#include
//实现两个数字进行交换
void swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "swap01 a = " << a << endl;
cout << "swap01 b = " << b << endl;
}
void swap02(int* p1, int* p2) // int了两个指针 p1 p2
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
cout << "swap02 *p1 = " << *p1 << endl;
cout << "swap02 *p2 = " << *p2 << endl;
}
int main()
{
//1.值传递
int a = 10;
int b = 20;
//swap01(a, b);
//cout << "a = " << a << endl;
//cout << "b = " << b << endl;
//2.地址传递(地址传递可以修饰实参)
swap02(&a, &b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;//将输出a=20,b=10
system("pause");
return 0;
}
案例描述:封装一个函数,冒泡排序,实现对整型数组{4,3,6,9,1,2,10,8,7,5}的升序排列。
#include
using namespace std;
#include
void bubbleSort(int* arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
//如果j > j+1的值,交换数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//打印数组
void printArray(int* arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
cout << arr[i] << " < ";
}
cout << 10 << endl << endl;
}
int main() {
//1.先创建数组
int arr[] = { 4,3,6,9,1,2,10,8,7,5 };
int len = sizeof(arr) / sizeof(arr[0]);//数组长度
//2.创建函数,实现冒泡排序
bubbleSort(arr, 10);
//3.打印排序后的数组
printArray(arr, len);
system("pause");
return 0;
}
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型(整形、浮点型、字符型、布尔数据类型、字符串型)。可以创建无数个,只要开心可以随意写。
语法:struct 结构体名{ 结构体成员列表 };
通过结构体创建变量的方式 *3
#include
using namespace std;
#include
//1. 创建学生数据类型:学生包括(姓名,年龄,分数)
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;
//2. 通过学生类型创建具体学生
int main()
{
//2.1 struct Student s1
struct Student s1;
//进行赋值
s1.name = "AA";
s1.age = 18;
s1.score = 100;
cout << "name:" << s1.name << " s1.age:" << s1.age << " score: " << s1.score << endl; //s1.name是一个string,所以需要include 包含一下这个头文件
//2.2 stuct Student s2 = { ... }
struct Student s2 = { "CC" , 19,80 }; //按顺序给初值
cout << "name:" << s2.name << " s2.age:" << s2.age << " score: " << s2.score << endl;
//2.3 在定义结构体时顺便创建结构体变量
s3.name = "ccc"; //赋初值
s3.age = 18;
system("pause");
return 0;
}
作用:将自定义结构体放到数组中方便维护
语法:struct 结构体名称 数组名[元数个数] = { {} , {} , … , {} }
#include
using namespace std;
#include //记得包含头文件
//1. 定义一个结构体
struct student
{
string name;//姓名年龄分数
int age;
int score;
};
int main()
{
//2. 创建结构体数组
struct student stuArray[3] =
{
{ "AA", 18, 100 },
{ "BB", 19, 95 },
{ "CC", 20, 99 },
};
//3. 给结构体数组中的元素赋值
stuArray[2].name = "GG";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4. 遍历(访问)结构体数组
int i = 0;
for (int i = 0; i < 3; i++)
{
cout << "Stu01's name: " << stuArray[i].name
<< " Age: " << stuArray[i].age
<< " Score: " << stuArray[i].score << endl << endl;
};
system("pause");
return 0;
}
作用:通过指针访问结构体中的成员。利用操作符->可以通过结构体指针访问结构体属性。
#include
using namespace std;
#include
// 定义学生结构体
struct student
{
string name;
int age;
int score;
};
int main()
{
//1. 创建学生结构体变量
struct student s = { "AA",18,100 };
//2. 通过指针指向结构体变量
struct student* p = &s;
//3. 通过指针访问结构体变量中的数据'->'
cout << "name: " << p->name << endl << endl
<< "age:" << p->age << endl << endl
<< "score" << p->score << endl << endl;
system("pause");
return 0;
}
#include
using namespace std;
#include
//1. 定义学生结构体
struct student
{
string name; // 学生姓名
int age; // 学生年龄
int score; // 考试分数
};
struct teacher
{
int id; // 教师编号
string name; // 教师姓名
int age; // 教师年龄
struct student stu; // 辅导的学生
};
int main()
{
teacher t; // t老师
t.id = 20253001;
t.age = 30;
t.name = "TT"; // t老师的名字是TT
t.stu.name = "yy"; // TT老师的学生是yy
t.stu.score = 78; //这个学生考了78分
cout << t.name << " " << t.id << " " << t.stu.score << endl;
system("pause");
return 0;
}
作用:将结构体作为参数向函数中传递
传递两种方式:
#include
using namespace std;
#include
//定义一个学生结构体
struct student
{
//姓名,年龄,分数
string name;
int age;
int score;
};
//打印学生信息的函数
//1. 值传递
void printStudent1(struct student s)
{
s.age = 100;
cout << "子函数1中 姓名:" << s.name << " 年龄:" << s.age << endl;
}
//2. 地址传递
void printStudent2(struct student* p)
{
p->age = 200;
cout << "子函数2中 姓名:" << p->name << " 年龄:" << p->age << endl;
}
int main()
{
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 85;
printStudent1(s);
printStudent2(&s);
cout << "main函数中打印 姓名:" << s.name << " 年龄:" << s.age << endl;
system("pause");
return 0;
}
作用:使用const来防止误操作,康斯特,可读不可写
看到康斯特,就代表了是要限定一个只读状态,防止修改操作。
#include
using namespace std;
#include
struct student {
string name;
int age;
int score;
}; // 先写一个结构体
//将函数中的形参改为指针,可以减少内存空间,指针只占四个字节,并且不会复制一个新的副本出来
void printStudents(const student* s)
{
//s->age = 150;
cout << "姓名:" << s->name << " 年龄:" << s->age << endl;
}
int main() {
//创建结构体变量
struct student s = { "张三" , 15,70 }; // 15岁、70分
//通过函数打印结构体变量信息
printStudents(&s);
cout << "main's.age: " << s.age << endl;
system("pause");
return 0;
}
/*值传递:
void printStudents(student s) {
cout << "name: " << s.name << endl;}
主函数中 printStudents(s);
在值传递中,void中是s和主函数struct student s中的s,不是同一个s。
如果在void中加一个s.age = 150; 把年龄改成了150岁,main中的s不会修改。
因为值传递会把s中所有的数据拷贝出来一份,放在void printStudents(student s)形参中的s中。*/
案例描述:
毕设,每名老师带领五个学生,共三名老师,设计学生和老师的结构体。在老师的结构体中,有老师姓名和一个存放五名学生的数组作为成员。学生的成员有姓名、考试分数。创建数组存放三名老师,通过函数给每一个老师及所带学生赋值,最终打印出老师数据和老师所带学生数据。
#include
using namespace std;
#include
struct Student //学生的结构体
{
string sName;
int score;
};
struct Teacher//老师的结构体
{
string tName;
struct Student sArray[5];
};
string nameSeed = "ABCDE";
//给老师赋值的函数
void allocateSpace(struct Teacher tArray[], int len)
{
for (int i = 0; i < len; i++) //开始给老师赋值了
{
tArray[i].tName = "Teacher_";
tArray[i].tName += nameSeed[i];
//通过循环给每名老师带的学生赋值
for (int j = 0; j < 5; j++)
{
tArray[i].sArray[j].sName = "Student_";
tArray[i].sArray[j].sName += nameSeed[j];
int random = rand() % 61 + 40; // 40~100
tArray[i].sArray[j].score = random;
}
}
}
//打印所有信息
void printInfo(struct Teacher tArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "老师姓名:" << tArray[i].tName << endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生姓名:" << tArray[i].sArray[j].sName << " 考试分数:" << tArray[i].sArray[j].score << endl;
}
}
}
int main()
{
srand((unsigned int)time(NULL));//随机数种子#include
//1. 创建三名老师的数组
struct Teacher tArray[3];
//2. 通过函数给三名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
//3. 打印所有老师及所带学生的信息
printInfo(tArray, len);
system("pause");
return 0;
}
案例描述:
设计一个英雄的结构体,包括成员姓名、年龄、性别。创建结构体数组,数组中存放五名英雄,通过冒泡排序算法,将数组中的英雄按照年龄进行升序排序,并打印排序后的结果。(设定:刘备23、关羽22、张飞20、赵云21、貂蝉19。)
#include
using namespace std;
#include
//1. 设计英雄结构体
struct Hero
{
string name;
int age;
string sex;
};
//冒泡排序,实现年龄升序排列
void bubbleSort(struct Hero heroArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
//如果j下表的元素年龄大于j+1下表的元素的年龄,交换这两个元素
if (heroArray[j].age > heroArray[j + 1].age)
{
struct Hero temp = heroArray[j];
heroArray[j] = heroArray[j + 1];
heroArray[j + 1] = temp;
}
}
}
}
//打印排序后的信息
void printHero(struct Hero heroArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄:" << heroArray[i].age << " 性别:" << heroArray[i].sex << endl;
}
}
int main()
{
//2. 创建数组存放5名英雄
struct Hero heroArray[5] =
{
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"},
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
/*输出测试*/
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄:" << heroArray[i].age << " 性别:" << heroArray[i].sex << endl;
}
//3. 对数组进行排序,按照年龄进行排序
bubbleSort(heroArray, len);
cout << endl << "排序后打印结果:" << endl;
//4. 将排序后的结果进行输出
printHero(heroArray, len);
system("pause");
return 0;
}