再系统地过一次,夯实基础
学习目标:
过一遍黑马程序员C/C++学习视频学习内容:
一、C++基础入门
7. 指针
7.1 指针的基本概念
指针的作用: 可以通过指针间接访问内存
- 内存编号时从 0 开始记录的,一般使用十六进制数字表示
- 可以利用指针变量保存地址
语法 数据类型* 指针变量
#include <iostream>
using namespace std;
int main(){
//1. 定义指针
int a = 10;
int* p;
//让指针记录变量a的地址
p = &a;
cout << "a的地址为: " << &a << endl;
cout << "指针p为: " << p << endl;
//2. 使用指针
//可以通过解引用的方式找到指针指向的内存
//指针前加一个*号,代表解引用,找到指针指向的内存中的数据
*p = 1000;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
7.3 指针所占内存空间
指针存的是一个地址如:0x0000
在32位操作系统下:4个字节空间
在64位操作系统下:8个字节空间
示例:`int* p = &a;
7.4 空指针和野指针
空指针: 指针变量指向内存中编号位0的空间
用途: 初始化指针变量
注意: 空指针指向的内存是不可以访问的
//黑马的空指针设置方式:
int *p = NULL;
//C++11新特性写法
int *p = nullptr;
//C++11中,nullptr在C++11中就是代表空指针,不能被转换成数字,以前NULL其实是会被当作0;
野指针: 指针变量指向非法的内存空间
程序中应该避免写出野指针
7.5 const 修饰指针
const修饰指针有三种情况:
- const 修饰指针 – 常量指针
- const 修饰常量 --指针常量
- const 即修饰指针,又修饰常量
常量指针的特点:指针的指向可以修改,但是指针指向的值不可以修改
//常量指针,const修饰指针
int a = 10;
int b = 10;
const int* p = &a;
指针常量的特点:指针的指向不可以修改,但是指针指向的值可以修改
//指针常量,const修饰常量
int* const p = &a;
即修饰指针,又修饰常量的特点就是,指针的指向,指针的值都不可以修改
const int* const p = &a;
7.6 指针和数组
作用: 利用指针访问数组中的元素
int arr[10] = { 1, 2, 3, 4, 5 };
int* p = arr;
p++;
7.7 指针和函数
作用: 利用指针做函数参数,可以修改实参的值
//地址传递
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 10;
int b = 20;
swap(a, b);
//等同于 swap(&a, &b)
cout << "a: " << a << endl;
cout << "b: " << b << endl;
system("pause");
return 0;
}
7.8 指针、数组、函数
案例描述: 封装一个函数,利用冒泡排序,实现对整型数组的升序排序
#include <iostream>
using namespace std;
void sort(int* arr) {
for (int i = 9; i >= 0; i--) {
int temp;
for (int j = 0; j < 9; j++) {
if (arr[j] > arr[j + 1]){
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[10] = {
4, 3, 6, 9, 1, 2, 10, 8, 7, 5 };
sort(arr);
for (int i = 0; i < 10; i++) {
cout << arr[i] << ' ';
}
system("pause");
return 0;
}
8. 结构体
8.1 结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
8.2 结构体定义和使用
语法: struct 结构体名 { 结构体成员名列表 };
通过结构体创建变量的方式又三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = { 成员1值, 成员2值 }
- 定义结构体时顺便创建变量
#include <iostream>
#include <string>
using namespace std;
//自定义数据类型
struct Student {
string name;
int age;
double score;
}s3; //后面添加 s3,就代表在顺便创建结构体变量
//创建具体的学生
// struct Student s1
// struct Student s2 = { ... }
// 在定义结构体时顺便创建结构体变量
int main() {
//创建具体的学生
// struct Student s1
//具体实施过程中 struct关键字可以不写
Student s1;
s1.name = "Zhang san";
s1.age = 18;
s1.score = 99.1;
cout << "s1.name: " << s1.name << "age: " << s1.age << endl;
// struct Student s2 = { ... }
Student s2 = {
"Lisi", 15, 88.1 };
// 在定义结构体时顺便创建结构体变量
s3.name = "s3";
cout << s3.name << endl;
system("pause");
return 0;
}
8.3 结构体数组
作用: 将自定义的结构体放入到数组中方便维护
语法: struct 结构体名 数组名[ 元素个数 ] = { {}, {}, {}, {} };
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int age;
float score;
};
int main() {
struct Student stuArray[3] = {
{
"zhangsan", 18, 88.5},
{
"Lisi", 18, 55.0},
{
"wangwu", 15, 99.1}
};
cout << stuArray[0].age << endl;
system("pause");
return 0;
}
8.4 结构体指针
作用: 通过指针访问结构体中的成员
- 利用操作符
->
可以通过结构体指针访问结构体属性
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int age;
float score;
};
int main() {
Student A1 = {
"wang", 18, 50.2 };
Student* p = &A1;
cout << p->name << endl;
//cout << (*p).name << endl; 两种方式相同
system("pause");
return 0;
}
8.5 结构体嵌套结构体
作用: 结构体中的成员可以是另一个结构体
例如: 每个老师辅导一个学院,一个老师的结构体中,记录一个学生的结构体
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int age;
int score;
};
struct Teacher {
string name;
int age;
Student stu;
};
int main() {
Student stu1 = {
"wang", 18, 55 };
Teacher Ma = {
"mayichao", 30, stu1 };
cout << Ma.stu.name << endl;
system("pause");
return 0;
}
8.6 结构体做函数参数
作用: 将结构体作为参数向函数中传递
传递方式有两种:
- 值传递
- 地址传递
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int age;
int score;
};
void stu(Student* who) {
cout << who->name << endl;
cout << who->age << endl;
cout << who->score << endl;
}
int main() {
Student stu1 = {
"wang", 18, 55 };
stu(&stu1);
system("pause");
return 0;
}
8.7 结构体中 const 使用场景
作用: 用const来防止误操作
加入const之后,一旦有修改的操作就会报错。
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int age;
int score;
};
//将函数中的形参改为指针,可以节约内存,而不会复制新的副本出来
void printStudent(const Student *s) {
s->age = 22;
cout << "name: " << s->name << endl;
}
int main() {
Student stu1 = {
"wang", 18, 55 };
printStudent(&stu1);
system("pause");
return 0;
}
8.8 结构体案例
8.8.1
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct Student {
string name;
int score;
};
struct Teacher {
string name;
Student stus[5];
};
void allocateSpace(Teacher tea[],int len) {
//给老师赋值
string nameSeed = "ABCDE";
for (int i = 0; i < len; i++) {
tea[i].name = "Teacher_";
tea[i].name += nameSeed[i];
//通过循环给每名老师所带的学生赋值
for (int j = 0; j < 5; j++) {
tea[i].stus[j].name = "Student_";
tea[i].stus[j].name += nameSeed[j];
int scores = rand() % 61 + 40; // 0 ~ 100;
tea[i].stus[j].score = scores;
}
}
}
void printInfo(Teacher tea[], int len) {
for (int i = 0; i < 3; i++) {
cout << "老师的姓名: " << tea[i].name << endl;
for (int j = 0; j < 5; j++) {
cout << " 学生的姓名: " << tea[i].stus[j].name << endl;
cout << " 学生的分数: " << tea[i].stus[j].score << endl;
}
}
}
int main() {
//随机数种子;
srand((unsigned int)time(NULL));
Teacher teachs[3];
int len = sizeof(teachs) / sizeof(teachs[0]);
allocateSpace(teachs, len);
printInfo(teachs, len);
system("pause");
return 0;
}
8.8.2
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct heros {
string name;
int age;
string sex;
};
void exchange(heros* H, int index) {
heros temp;
temp = H[index];
H[index] = H[index + 1];
H[index + 1] = temp;
}
void bubblesort(heros* H, int n) {
for (int i = n - 1; i >= 0; i--) {
for (int j = 0; j < n - 1; j++) {
string names;
int ages;
string sexs;
if ( H[j].age > H[j+1].age ) {
exchange(H, j);
}
}
}
}
int main() {
heros Heros[5] = {
{
"刘备", 23, "boy"},
{
"关羽", 22, "boy"},
{
"张飞", 20, "boy"},
{
"赵云", 21, "boy"},
{
"貂蝉", 18, "girl"}
};
int len = sizeof(Heros) / sizeof(Heros[0]);
bubblesort(Heros, len);
for (int i = 0; i < 5; i++)
cout << Heros[i].name << ' ' << Heros[i].age << endl;
system("pause");
return 0;
}
二、通讯录管理系统
#include<iostream>
using namespace std;
#include<string>
#define MAX 1000
void showMenu() {
string gongneng[7] = {
"1、添加联系人", "2、显示联系人", "3、删除联系人", "4、查找联系人", "5、修改联系人",
"6、清空联系人", "0、退出通讯录" };
for (int i = 0; i < 9; i++) {
if (i == 0) {
for (int j = 0; j < 29; j++) {
cout << "*";
}
cout << endl;
}
else if (i == 8) {
for (int j = 0; j < 29; j++) {
cout << "*";
}
cout << endl;
}
else
cout << "*****\t" << gongneng[i - 1] << "\t*****" << endl;
}
}
//联系人结构体
struct Person {
string name;
int sex; //1代表男 2代表女 其他不通过
int age;
string tell;
string address;
};
//通讯录结构体
struct Addressbooks {
struct Person personArray[MAX];
int m_Size;
};
void addusers(Addressbooks* address) {
int cur = address->m_Size;
while (1) {
if (cur == MAX) {
cout << "通讯录已满";
break;
}
cout << "添加姓名: ";
cin >> address->personArray[cur].name;
cout << endl;
cout << "添加性别: ";
while (1) {
int sexx;
cin >> sexx;
if (sexx == 1 || sexx == 2) {
address->personArray[cur].sex = sexx;
cout << endl;
break;
}
cout << "输入非法,请重输:" << endl;
}
cout << "添加年龄: ";
cin >> address->personArray[cur].age;
cout << endl;
cout << "添加电话: ";
cin >> address->personArray[cur].tell;
cout << endl;
cout << "添加地址: ";
cin >> address->personArray[cur].address;
cout << endl;
address->m_Size++;
cout << "添加成功,请进行下一次操作!" << endl;
system("pause");
system("cls");//清屏操作
break;
}
}
void showusers(Addressbooks address) {
if (address.m_Size == 0)
cout << "没有联系人" << endl;
for (int i = 0; i < address.m_Size; i++) {
cout << "用户 " << i << ":" << endl;
cout << "\t" << address.personArray[i].name << endl;
cout << "\t" << (address.personArray[i].sex == 1 ? "男" : "女") << endl;
cout << "\t" << address.personArray[i].age << endl;
cout << "\t" << address.personArray[i].tell << endl;
cout << "\t" << address.personArray[i].address << endl;
}
system("pause");
system("cls");
}
int isExist(Addressbooks address, string name) {
for (int i = 0; i < address.m_Size; i++) {
if (address.personArray[i].name == name) {
return i;//返回该用户的下标
}
}
return -1;
}
//删除指定联系人
void deletePerson(Addressbooks* address) {
cout << "请输入您要删除的联系人: " << endl;
string name;
cin >> name;
if (isExist(*address, name) == -1) {
cout << "查无此人" << endl;
}
else cout << "待删除联系人下标为: " << isExist(*address, name) << endl;
int index = isExist(*address, name);
//address->personArray[index] = address->personArray[address->m_Size - 1];
//address->m_Size--;
//cout << "删除成功" << endl;
if (index < address->m_Size - 1) {
for (int i = index; i < address->m_Size; i++) {
address->personArray[index] = address->personArray[index + 1];
}
}
address->m_Size--;
cout << "删除成功: " << endl;
}
//查找
void find(Addressbooks address) {
cout << "请输入您要查找的联系人: " << endl;
string name;
cin >> name;
int flag = 0;
for (int i = 0; i < address.m_Size; i++) {
if (address.personArray[i].name == name) {
cout << "姓名: " << address.personArray[i].name << endl;
cout << "性别: " << (address.personArray[i].sex == 1 ? "男" : "女") << endl;
cout << "年龄: " << address.personArray[i].age << endl;
cout << "电话: " << address.personArray[i].tell << endl;
cout << "地址: " << address.personArray[i].address << endl;
flag = 1;
break;
}
}
if (flag == 0) cout << "查无此人" << endl;
else cout << "查找成功" << endl;
}
int main() {
int keyboard = 0;
Addressbooks address;
address.m_Size = 0;
//实现退出功能
while (true) {
showMenu();
cin >> keyboard;
if (keyboard == 1) {
//添加
addusers(&address);
}
else if (keyboard == 2) {
//显示
showusers(address);
}
else if (keyboard == 3) {
//删除
deletePerson(&address);
system("pause");
system("cls");
}
else if (keyboard == 4) {
//查找
find(address);
system("pause");
system("cls");
}
else if (keyboard == 5) {
//修改
cout << "不写了" << endl;
system("pause");
system("cls");
}
else if (keyboard == 6) {
//清空
address.m_Size = 0;
cout << "清空成功" << endl;
system("pause");
system("cls");
}
else if (keyboard == 0) {
//退出
cout << "成功退出系统";
break;
}
else cout << "输入错误请重新输入" << endl;
}
return 0;
}
三、C++核心编程
四、基于多态的企业职工系统
五、C++提高编程
六、基于STL泛化编程的演讲比赛
七、C++实战项目机房预约管理系统
学习产出:
1、github 啃STL简化项目,能够自己实现STL相关项目
2、做一个微信小程序,具体功能暂定