目录
1.1函数的定义:返回值类型、函数名、参数表列、函数体语句、return表达式
1、函数
将一段常用的代码封装起来,减少重复代码
1.1函数的定义:返回值类型、函数名、参数表列、函数体语句、return表达式
1.2函数的语法:
返回值类型 函数名(参数表列){
函数体语句
return表达式
}
例:
//两个数相加的函数
//返回值类型应该是一个数,
//函数名可自己命名,例如add
//参数应该是,两个数字,num1,num2
//函数体语句为求两数相加:int sum = num1+num2;
//return返回值是一个数
int add(int num1, int num2) {
int sum = num1 + num2;
return sum;
}
1.3 函数的调用:函数名 (参数)
int a = 10;
int b = 20;
//调用上述的add函数
//函数名 (参数)
//当调用函数时,实参的值会传递给形参
//a和b称为实参(实际参数)
add(a, b);
//函数add返回的是一个值,故可以直接打印结果
cout<< add(a, b)<<endl;
1.4 值传递
函数调用时实参将数值传入给形参
值传递时,形参发生任何改变,并不会影响实参
例:2个数字交换,内存的大致情况(创建变量时,会分配一个内存):值传递时,只是num1和num2的数据值交换,a和b不变。
数据 | |
a | 10 |
b | 20 |
num1 | |
num2 | |
temp | 10 |
1.5常见的函数样式
无参无返、有参无返、无参有返、有参有返
1.6函数的声明
告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数的声明可以多次,但是函数的定义只能有一次。
函数声明之后,定义该函数可以在main()函数之后。
补充:变量
定义 VS 声明
变量定义要给变量分配内存空间,而声明没有;定义可以初始化,声明不能。
声明: extern <类型名> <变量名>;
头文件中使用extern语句对一个文件中的全局函数进行声明;
函数使用一个全局变量但是还未见到其定义时使用extern语句对其进行声明。
1.7函数的分文件编写
让代码结构更加清晰
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
2、指针
通过指针间接访问内存
内存编号是从0开始记录的,一般用十六进制数字表示;可以利用指针变量保存地址
2.1指针变量定义语法:数据类型 *变量名;
int a = 10;
//定义指针
int *p;
//让指针记录变量a的地址
p = &a;
cout << "a的地址为:" << p << endl;
//使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加 * 代表解引用,找到指针指向的内存中的数据
*p = 1000;
//此时原先a的值已变为1000,*p即对应内存的数据内容
2.2 指针的所占内存空间
指针也是种数据类型,占4个字节空间(32位操作系统),64位操作系统下占8字节空间。
cout << "指针所占内存空间为:" << sizeof(int *) << endl;
2.3空指针
用于初始化指针变量;空指针指向的内存是不可以访问的
空指针:指针变量指向内存中编号为0的空间,而0-255之间的内存访问编号是系统占用的,因此不可以访问
例:
2.4 野指针:指针变量指向非法访问等的内存空间
例如:直接定义一个指针变量,且直接指向一个非法内存空间;
int *p = (int *)0x1100;运行时会发生异常,没有访问权限。
2.5 const修饰指针
const修饰指针 ---常量指针:const int *p = &a,指针的指向可以修改,指针指向的值不可以改
const修饰常量 ---指针常量:int * const p = &a;指针的指向不可以改,指针指向的值可以改
const既修饰指针,又修饰常量:const int * const p = &a;指针的指向和指针指向的值不可以改
2.6 指针和数组:利用指针访问数组中的元素
//指针访问数组元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int *p = arr;//arr就是数组首地址
for (int i = 0; i < 10; i++) {
cout << "指针访问数组第"<< i << "个元素:" << *p << endl;
p++;
}
2.7 指针和函数:利用指针作函数参数,可以修改实参的值
地址传递
void swap(int *num1, int *num2) {
int temp =*num1;
*num1 = *num2;
*num2 = temp;
}
int main() {
int a = 10;
int b = 20;
swap(&a, &b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
内存数据 | |
a(假设内存地址为0x0011) | 10 -> 20 |
b(假设内存地址为0x0022) | 20 -> 10 |
*num1 | 0x0011 |
*num2 | 0x0022 |
temp | 10 |
若想修改实参,使用地址传递;若不想修改实参,就使用值传递。
例:封装一个函数,利用冒泡排序,实现对整型数组的升序排序
//冒泡升序排序 参数1 数组的首地址 参数2 数组的长度
void bubbleSort(int *arr,int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
//如果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; i++) {
cout << arr[i] << endl;
}
}
int main()
{ //冒泡升序排序
int arr[9] = { 4,2,8,0,5,7,1,3,9 };
bubbleSort(arr,9);//需要传入的参数是数组和数组的长度
printArray(arr,9);//打印排序后的数组
system("pause");
return 0;
}
3、结构体
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
3.1 结构体的定义和使用
Struct 结构体名 {结构体成员列表};
通过结构体创建变量的方式有三种:
struct 结构体名 变量名
struct 结构体名 变量名 = {成员1值,成员2值...}
定义结构体时顺便创建变量
例:创建学生数据类型:学生姓名,年龄,分数
struct student {
string name;//姓名
int age;//年龄
int score;//分数
}s3;//定义结构体时顺便创建变量
int main()
{ //通过学生类型创建具体学生
//struct 结构体名 变量名;struct 可省略
//通过 . 访问成员
struct student s1;
s1.name = "李四";
s1.age = 18;
s1.score = 75;
cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;
//struct 结构体名 变量名 ={成员1值,成员2值...}
struct student s2 = { "张三",20,80 };
cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;
s3.name = "王五";
s3.age = 22;
s3.score = 60;
cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;
system("pause");
return 0;
}
3.2 结构体数组
将自定义的结构体放入到数组中方便维护
struct 结构体名 数组名{元素个数} = {{},{},{}...}
struct student {
string name;//姓名
int age;//年龄
int score;//分数
};
int main()
{ //结构体数组
//创建结构体数组
struct student StuArray[3] = { {"张三",20,80},{"李四",18,75} };
//给结构体数组中的元素赋值
StuArray[2].name = "王五";
StuArray[2].age = 22;
StuArray[2].score = 65;
//遍历结构体数组
cout << "姓名 " << "年龄 " << "分数 " << endl;
for (int i=0; i < 3; i++) {
cout << StuArray[i].name<<" " << StuArray[i].age << " " << StuArray[i].score << endl;
}
system("pause");
return 0;
}
3.3 结构体指针:通过指针访问结构体成员
利用操作符 -> 可以通过结构体指针访问结构体属性
//创建学生结构体变量
student s = {"张三",18,99};
//通过指针指向结构体变量
student *p = &s;
//通过指针访问结构体变量中的数据
string st = p->name;
cout << st << endl;//输出结果是张三
3.4 结构体嵌套结构体
结构体中的成员可以是另一个结构体
例:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
//定义学生结构体
struct student {
string name;//姓名
int age;//年龄
int score;//分数
};
//定义老师结构体
struct teacher {
int id;
string name;
int age;
struct student stu;//老师辅导的学生
};
int main()
{ //结构体嵌套一个结构体
teacher t;
t.id = 012;
t.name = "卢老师";
t.age = 30;
t.stu.name = "阿霞";
t.stu.age = 20;
t.stu.score = 95;
cout << "老师姓名:" << t.name << "老师编号:" << t.id << "老师年龄:" << t.age << endl;
cout << "老师辅导的学生姓名:" << t.stu.name << "学生年龄:" << t.stu.age << "学生成绩:" << t.stu.score << endl;
system("pause");
return 0;
}
3.5 结构体作函数参数:将结构体作为参数向函数中传递
值传递
printSt(st);//打印学生信息的函数,需传入学生结构体信息
void printSt(student st) {
cout << st.name << st.age << st.score << endl;
}
地址传递
printSt2(&st);
void printSt2(student *st) {
cout << st -> name << st->age << st->score << endl;
}
3.6 结构体中const使用场景
用const来防止误操作
将结构体作为参数向函数中进行地址传递时,实参值是可以改变的,若结构体参数前加上const即void printSt2(const student *st),此时,里面的数据就不可以修改了(原先值不改变)。
3.7 例子
3.7.1例1:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据
我的程序:
#include <iostream>
#include<string>
using namespace std;
//例子1
//两个结构体,老师:姓名和存放5个学生的数组;学生:姓名和考试分数
//创建数组存放三名老师
//函数,给每个老师及所带的学生赋值
//打印老师数据以及所带的学生数据
//学生结构体
struct student {
string sn;//学生姓名
int score;//考试分数
};
struct teacher {
string tn;//老师姓名
student stu[5];
};
void data(teacher t[],int len) {
//老师名字数组
string tname[3] = {"老师1","老师2" ,"老师3" };
string sname[3][5] = { "明", "红", "方", "何", "郑","丽", "简", "芬", "si", "me","橙", "佳", "穗", "熊", "ky" };
int score[3][5] = { { 80,81,86,85,82 } , { 95,93,87,98,100 } ,{ 100,89,92,85,94 } };
//给老师赋值
for (int i = 0; i < 3; i++) {
t[i].tn = tname[i];
cout << t[i].tn << "所带的学生为:"<<endl;
//给学生赋值
for (int j = 0; j < 5; j++) {
t[i].stu[j].sn = sname[i][j];
t[i].stu[j].score = score[i][j];
//打印信息
cout << t[i].stu[j].sn;
cout <<"("<<t[i].stu[j].score << "分) ";
}
cout << endl;
}
}
int main()
{
teacher t[3];
data(t,3);
system("pause");
return 0;
}
打印结果:
注:我是直接用一个数组存储老师姓名,学生姓名和学生成绩,直接访问。
3.7.2 例2
设计一个英雄结构体,包括成员姓名、年龄,性别;创建结构体数组,数组中存放五名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄排序进行升序排序,最终打印排序后的结果。
//例2,花费19分钟
//一个英雄结构体
//结构体数组,存放5名英雄
//对年龄进行冒泡升序排序
//打印排序后的结果
#include <iostream>
#include<string>
using namespace std;
struct hero {
string name;//姓名
int age;//年龄
string sex;//性别
};
//冒泡排序
void bubbleSort(hero h[],int len) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5 - i - 1; j++) {
if (h[j].age > h[j+1].age) {
hero htemp = h[j];
h[j] = h[j+1];
h[j + 1] = htemp;
}
}
}
}
//打印
void print(hero h[], int len) {
for (int i = 0; i < 5; i++) {
cout << " " << h[i].name << " " << h[i].age << " " << h[i].sex << endl;
}
}
int main() {
hero h[5] = { {"刘备",23,"男"},
{"关羽",22,"男"}, {"张飞",20,"男"},
{"赵云",21,"男"}, {"貂蝉",19,"女"}};
cout << " 姓名 年龄 性别" << endl;
bubbleSort(h, 5);
print(h, 5);
system("pause");
return 0;
}
写在最后:最后一道题我居然花了19分钟!!还是敲得不够多吧。基础语法和原理一定要弄懂滴,接着埋头练习算法吧!!!