C++基础入门
1.初识C++
1.1 Helloworld程序
1.2 注释
- 单行注释
//
- 多行注释
/* 注释语句 */
1.3 变量
- 变量存在的意义:给变量分配合适的内存空间,方便我们管理内存空间
- 变量创建的语法:
数据类型 变量名[=值];
1.4 常量
- 作用:用于记录程序中不可更改的数据
- 定义常量的两种方式
- #define宏常量
# define 常量名 常量值
- 通常在文件上方定义,表示一个常量
- const 修饰的变量
const 数据类型 变量名=值
- 写在函数体内部
- #define宏常量
1.5 关键字
1.6 标识符命名规则
- 标识符不能是关键字
- 只能由字符、数字和下划线组成
- 不能以数字开头
- 区分大小写
2.数据类型
2.1整型
占用空间不同
数据类型 | 占用空间 | 取值范围 | |
---|---|---|---|
short(短整型) | 2字节 | -2^15 -2^15-1(-32768-23767) | |
int(整型) | 4字节 | -2^31 - 2^31-1 | |
long(长整型) | windows为4字节 | -2^31 - 2^31-1 | |
long long(长长整型) | 8字节 | -2^63 - 2^63-1 | |
2.2 sizeof关键字
- sizeof 可以求出数据类型占用内存大小
2.3 实型(浮点型)
- 作用:表示小数
- 分类:两者的区别在于有效数字范围不同
- 单精度 float 4字节
- 双精度 double 8字节
2.4字符型
作用:显示单个字符
语法:char 变量名=‘a’
注意1:只能是单个字符
注意2:用单引号
所占内存空间为1字节,在内存中对应的是ASCII码
2.5 转义字符
2.6字符串型
作用:显示多个字符
语法:string 变量名 = “hello world”
注意:必须添加头文件 #include 2.2.7
2.7 bool类型
只有两个值:
-
ture ==> 1
-
false ==> 0
占用内存空间1字节
2.8 数据的输入
作用:用于从键盘上获取数据
语法:cin
3.运算符
运算符类型 | 作用 |
---|---|
逻辑运算符 | 用于判断,返回bool值 |
赋值运算符 | 给变量赋值 |
比较运算符 | 表达式的比较,返回bool值 |
算术运算符 | 四则运算 |
4. 程序流程结构
三种程序运行结构:顺序结构、选择结构、循环结构
4.1 选择结构
4.1.1 if语句
-
单行if语句:只有if
-
多行if语句:if…else…
-
多条件if语句:if … else if … else…
#include <iostream>
using namespace std;
int main()
{
// 用户输入的分数大于600,则为一本
int score;
cout << "请输入你的高考分数:";
cin >> score;
if (score >= 600)
cout << "你的分数为" << score << "分," << "一本!";
return 0;
}
4.1.2 三目运算符
在C++中三目运算符返回的是变量,可以继续赋值
语法:表达式1 ? 表达式2 : 表达式3
语义:如果表达式1返回值为真,返回表达式2的结果,否则返回表达式3的结果
4.1.3 switch语句
#include <iostream>
using namespace std;
int main()
{
int score;
cout << "您的分数:";
cin >> score;
int rank = score / 10;
switch (rank)
{
case 9: cout << "优秀" << endl;
break;
case 8:
case 7: cout << "良好" << endl;
break;
case 6: cout << "及格" << endl;
break;
default: cout << "未及格!" << endl;
break;
}
return 0;
}
4.1.4 if与switch的区别
- switch只能判断数值或字符型,不能判断范围
- case后不跟break会一直执行下去
4.2循环结构
4.2.1 while循环语句
作用:满足循环条件,执行循环语句
语法:while(循环条件){循环语句}
解释:只要循环条件为真,就一直循环
案例:猜数字
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
int main()
{
// 设置玩家猜测数的变量和初始化猜测次数
int player_num, i = 0;
// 添加随机种子,防止每次的随机数是一样的
srand((unsigned int)time(NULL));
// rand()%100 表示生成0-99里面的任意一个数
idea_num = rand() % 100 + 1;
while (true)
{
if (i == 0) cout << "你觉得我心里想的数字是几呢 :";
else cout << "给提示咯,再猜:";
cin >> player_num;
if (player_num > idea_num)
{
cout << "太大了,再小点!\n";
}
else if (player_num < idea_num)
{
cout << "太小了,再大点!\n";
}
else
{
cout << "\abingo,你猜对了!\n";
break;
}
i++;
}
cout << "你总共猜了" << i << "次!" << endl;
return 0;
}
4.2.2 do…while…循环
语法:do{循环语句}while(循环条件)
案例:猜数字
#include <iostream>
using namespace std;
#include <string>
#include <ctime>
int main()
{
// 设置玩家猜测数的变量和初始化猜测次数
int player_num, i = 1;
// 添加随机数种子,防止每次随机数是一样的
srand((unsigned int)time(NULL));
// rand()%100 表示从0-99中随机生成一个数
int idea_num = rand() % 100 + 1;
do
{
if (i == 1) cout << "你觉得我心里想的数字是几呢 :";
else cout << "给提示咯,再猜:";
cin >> player_num;
if (player_num > idea_num)
{
cout << "太大了,再小点!\n";
}
else if (player_num < idea_num)
{
cout << "太小了,再大点!\n";
}
else
{
cout << "\abingo,你猜对了!\n";
break;
}
i++;
} while (true);
cout << "你总共猜了" << i << "次!" << endl;
return 0;
}
while与do…while的区别:do…while会先执行一次循环语句再判断
案例:水仙花数
#include <iostream>
using namespace std;
#include <string>
#include <cmath>
int main()
{
int num = 100;
cout << "三位数中水仙花数有:\t";
do
{
int a = num / 100; // 获取百位
int b = (num - a * 100) / 10; // 获取十位
int c = (num - a * 100) % 10; // 获取个位
if ((pow(a, 3) + pow(b, 3) + pow(c, 3)) == num)
cout << num << "\t";
num++;
} while (num < 1000);
return 0;
}
4.2.3 for 循环语句
语法:for(起始表达式; 条件表达式; 末尾循环体){循环语句}
案例:水仙花数
#include <iostream>
using namespace std;
#include <string>
#include <cmath>
int main()
{
cout << "三位数中水仙花数有:\t";
for(int num = 100; num < 1000; num++)
{
int a = num / 100;
int b = (num - a * 100) / 10;
int c = (num - a * 100) % 10;
if ((pow(a, 3) + pow(b, 3) + pow(c, 3)) == num)
cout << num << "\t";
}
return 0;
}
案例:敲桌子
#include <iostream>
using namespace std;
#include <string>
#include <cmath>
int main()
{
// 能被7整除、个位有7及十位有7的数都改为敲桌子
for(int num = 1; num < 100; num++)
{
if ((num % 7 == 0) || (num % 10 == 7) || (num / 10 == 7))
{
cout << "敲桌子,";
}
else cout << num << ",";
}
return 0;
}
4.2.4 嵌套循环
案例:进度条
#include <iostream>
using namespace std;
#include <iomanip>
#include <windows.h>
int main()
{
for (int i = 1; i <= 100; i++)
{
cout << "\r[";
for (int j = 1; j <= i; j++)
{
cout << "*";
}
cout << "]" << "已完成" << i << "% ";
Sleep(100);
}
return 0;
}
案例:九九乘法表
#include <iostream>
using namespace std;
#include <cmath>
#include <iomanip>
int main()
{
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= i; j++)
{
cout << i << "x" << j << "=" << setw(2) << i * j << " | ";
}
cout << endl;
}
return 0;
}
4.3跳转语句
4.3.1 break
作用:跳出选择结构或者循环结构
break使用的时机
- 出现在switch条件语句中,作用是终止case结束switch循环
- 出现在循环语句中,作用是跳出当前循环体
- 出现在嵌套循环中,跳出最近的内层循环
4.3.2 continue
作用:在循环语句中,满足条件时,不执行循环语句,但对后面的循环无影响
案例:只1-10中的偶数
#include <iostream>
using namespace std;
int main()
{
for (int i = 1; i <= 10; i++)
{
if (i % 2 != 0) continue;
else cout << i << endl;
}
return 0;
}
4.3.3 goto语句
作用:可以无条件跳转语句(不建议过度使用)
语法:goto 标记
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记位置
#include <iostream>
using namespace std;
int main()
{
cout << "a" << endl;
cout << "b" << endl;
goto FLAG;
cout << "c" << endl;
cout << "d" << endl;
FLAG:
cout << "e" << endl;
return 0;
}
5.数组
5.1 概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点:
- 数组中的每个元素都是相同的数据类型
- 数组是由连续的内存位置组成的
5.2 一维数组
5.2.1 一维数组定义方式
三种定义方式:
数据类型 数组名[数据长度]
数据类型 数组名[数组长度] = {value}
数据类型 数组名[] = {value}
注意:
- 下标从0开始
- 数组名是常量,不能重新赋值
定义数组
#include <iostream>
using namespace std;
int main()
{
// 定义时不赋值
int arr1[5];
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
arr1[3] = 4;
arr1[4] = 5;
// 定义时赋值,若赋值个数未达到数组设置长度,默认用0填充
int arr2[5] = {1, 2, 3, 4};
// 不给数组长度定义时必须赋值
int arr3[] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++)
{
cout << arr1[i] << ' '<< arr2[i] << " " << arr3[i] << endl;
}
return 0;
}
案例:找数组中的最大值
#include <iostream>
using namespace std;
int main()
{
int arr[5] = { 23, 45, 67, 25, 62 };
int m = arr[0];
for (int i = 0; i <= sizeof(arr) / sizeof(int) - 1; i++)
{
if (m < arr[i]) m = arr[i];
}
cout << m << endl;
return 0;
}
案例:数组元素逆置
#include <iostream>
using namespace std;
int main()
{
int arr[5] = { 23, 45, 67, 25, 62 };
cout << "原始数组元素顺序:\n";
for (int i = 0; i <= 4; i++)
{
cout << arr[i] << " ";
}
cout << '\n';
// 逆置
int start = 0;
int end = sizeof(arr) / sizeof(int) - 1;
while (start < end)
{
// 两个元素互换,创建一个临时变量
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
// 下标更新
start++;
end--;
}
cout << "逆置后数组顺序:\n";
for (int i = 0; i <= 4; i++)
{
cout << arr[i] << " ";
}
return 0;
}
案例:冒泡排序(从小到大)
using namespace std;
#include <string>
int main()
{
int arr[10] = { 1,4,7,2,10,5,9,3,6,8 };
// 计算数组长度
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i <= len - 1; i++)
{
for (int j = i + 1; j <= len - 1; j++)
{
if (arr[i] > arr[j])
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
for (int k = 0; k <= len; k++)
{
cout << arr[k] << ' ';
}
return 0;
}
5.3二维数组
5.3.1 创建二维数组
定义:
- 一般使用:
数据类型 数组名[行数][列数] = {{value}, {value}}
#include <iostream>
using namespace std;
int main()
{
// 创建二维数组
int arr[2][3] = { {1,2,3},{4,5,6} };
// 打印
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j <= 2; j++ )
{
cout << arr[i][j] << ' ';
}
cout << endl;
}
return 0;
}
5.3.2二维数组数组名
略(同一维)
5.3.3二维数组应用案例
案例:打印成绩
案例描述:有三名同学(张三、李四、王五),打印在一次考试中的语数外成绩。
姓名 | 语文 | 数学 | 英语 |
---|---|---|---|
张三 | 98 | 100 | 100 |
李四 | 92 | 80 | 98 |
王五 | 78 | 89 | 57 |
#include <iostream>
using namespace std;
int main()
{
int arr[3][3] = {
{100, 100, 100},
{90, 50, 100},
{60, 70, 80}
};
string name[3] = { "张三", "李四", "王五" };
cout << '\t' << "语文" << " " << "数学" << " " << "英语" << " " << "总分" << endl;
for (int i = 0; i <= 2; i++)
{
int sum = 0;
cout << name[i] << "\t";
for (int j = 0; j <= 2; j++)
{
sum += arr[i][j];
cout << setw(6) << left << arr[i][j];
}
cout << setw(6) << sum << endl;
}
return 0;
}
6.函数
6.1概述
6.2函数的定义
函数的定义一般五个步骤:
- 返回值类型
- 函数名
- 参数列表
- 函数体语句
- return表达式
6.3函数的调用
6.4值传递
函数调用时实参将数值传给定义函数的形参
6.5函数的常见形式
常见函数样式:
- 无参无返
- 有参无返
- 无参有返
- 有参有返
6.6函数的声明
main函数放最前面时,调用其他函数需声明
注意:声明可以多次,但定义只能一次
6.7函数的分文件编写
函数分文件编写的四个步骤:
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
7.指针
7.1 指针的基本概念
可以通过指针间接访问内存
- 内存编号是从0开始记录的,一般用十六进制表示
- 可以利用指针变量保存地址
注意:指针也是一种数据类型
7.2指针变量的定义与使用
指针变量定义语法:数据类型 * 指针名
#include <iostream>
using namespace std;
int main()
{
// 1.定义指针
int a = 10;
// 指针定义的语法 数据类型 * 指针变量名
int * p;
// 让指针记录变量a的地址
p = &a;
cout << "a的地址为:&a = " << &a << endl;
cout << "p代表a的内存地址:p = " << p << endl;
// 2.使用指针
// 可以通过解引用(指针前加*)的方式来找到指针指向的内存的值
*p = 20;
cout << "a = " << a << endl;
cout << "*p代表a的值:*p = " << *p << endl;
return 0;
}
7.3指针所占空间
32位操作系统,都是4字节;64位下是8字节。
7.4空指针与野指针
7.4.1空指针
指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
#include <iostream>
using namespace std;
int main()
{
// 定义空指针
int* p = NULL;
// 指针p的内存地址为:00000000
cout << p << endl;
// cout << *p << endl; 报错
return 0;
}
7.4.2野指针
指针变量指向非法的内存空间(指向未申请的空间)
#include <iostream>
using namespace std;
int main()
{
// 定义野指针
int* p = (int* )0x1100;
cout << p << endl;
return 0;
}
7.5 const修饰指针
三种情况:
- 修饰指针–常量指针
- 特点:指针指向的内存地址可以更改,指针指向的值不可改
- 修饰常量–指针常量
- 特点:指针指向的内存地址不可更改,指针指向的值可更改
- 既修饰指针又修饰常量
- 特点:什么都不能修改
#include <iostream>
using namespace std;
int main()
{
int a = 10, b = 20;
// 常量指针
const int* p = &a;
cout << p << endl;
p = &b; // 可改指针指向的内存地址
cout << p << endl;
// 指针常量
int* const point = &a;
cout << *point << endl;
*point = b; // 可改指针指向内存的值
cout << *point << endl;
// 既修饰指针又修饰常量
int c = 10, d = 20;
const int* const point1 = &c;
cout << p << endl;
// point1 = &d; 报错
// *point1 = d; 报错
cout << p << endl;
return 0;
}
7.6 指针和数组
作用:利用指针访问数组的元素
示例
#include <iostream>
using namespace std;
int main()
{
int arr[8] = { 1,2,3,4,5,6,7,8 };
int* p = arr;
for (int i = 0; i <= 7; i++)
{
cout << *p++ << endl;
}
return 0;
}
7.7 指针与函数
函数参数传递方式
- 值传递:形参无法改变实参
- 地址传递:形参可以改变实参
示例
#include <iostream>
using namespace std;
// 值传递
void swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
// cout << "a = " << a << "\nb = " << b << endl;
}
// 地址传递
void swap02(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int a = 10, b = 20;
cout << "a, b原值:\n" << "a = " << a << "\nb = " << b << endl;
swap01(a, b);
cout << "值传递后:\n" << "a = " << a << "\nb = " << b << endl;
swap02(&a, &b);
cout << "地址传值后:\n" << "a = " << a << "\nb = " << b << endl;
return 0;
}
7.8 指针、数组、函数
示例:冒泡排序
8. 结构体
8.1 结构体概念
结构体属于用户自定义的数据类型,允许用户存储不同类型的值
8.2结构体定义与使用
语法:struct 结构体名 {结构体成员列表}
#include <iostream>
#include <string>
using namespace std;
// 1.创建学生数据类型
struct Student
{
// 成员列表
string name;
int age;
int score;
}s3; // <---2.3
int main()
{
// 2.通过学生数据类型创建具体的实例,创建结构体实例时可省去struct,定义时不可省
// 2.1 struct Student s1
struct Student s1;
s1.name = "张三";
s1.age = 20;
s1.score = 100;
cout << "姓名:" << s1.name << "\t年龄:" << s1.age << "\t分数:" << s1.score << endl;
// 2.2 struct Student s2 = {value};
struct Student s2 = { "李四", 18, 90 };
cout << "姓名:" << s2.name << "\t年龄:" << s2.age << "\t分数:" << s2.score << endl;
// 2.3在定义结构体时顺便创建结构体变量
s3.name = "王五";
s3.age = 19;
s3.score = 88;
cout << "姓名:" << s3.name << "\t年龄:" << s3.age << "\t分数:" << s3.score << endl;
return 0;
}
注意:创建结构体实例时可省去struct,定义时不可省struct关键字;
8.3结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = {{},{},{}}
#include <iostream>
#include <string>
using namespace std;
// 1.创建学生数据类型
struct Student
{
// 成员列表
string name;
int age;
int score;
};
int main()
{
struct Student arr[3] = {
{"张三", 20, 100},
{"李四", 18, 90},
{"王五", 19, 88},
};
// 遍历打印
for (int i = 0; i <= 2; i++)
{
cout << "姓名:" << arr[i].name << "\t年龄:" << arr[i].age << "\t分数:" << arr[i].score << endl;
}
return 0;
}
8.4结构体指针
作用:通过指针访问结构体中的成员
利用操作符"->"可以通过结构体指针访问结构体属性
#include <iostream>
#include <string>
using namespace std;
// 1.创建学生数据类型
struct Student
{
// 成员列表
string name;
int age;
int score;
};
int main()
{
struct Student s = { "yph", 23, 100 };
// 通过指针指向结构体变量
Student* p = &s;
// 通过指针访问结构体中的变量
cout << "姓名:" << p->name << "\t年龄:" << p->age << "\t分数:" << p->score << endl;
// 指针访问结构体数组
struct Student arr[3] = {
{"张三", 20, 100},
{"李四", 18, 90},
{"王五", 19, 88},
};
Student * p1 = arr;
for (int i = 0; i <= 2; i++)
{
cout << "姓名:" << p1->name << "\t年龄:" << p1->age << "\t分数:" << p1->score << endl;
p1++;
}
return 0;
}
8.5结构体嵌套结构体
作用:结构体的成员可以是另一个结构体
#include <iostream>
#include <string>
using namespace std;
struct Student
{
int sid;
string name;
int score;
};
struct Teacher
{
int tid;
string name;
int age;
struct Student stu;
};
int main()
{
Teacher miss_wang = { 1001, "王八", 30, {202009, "小王", 90} };
cout << "教师编号:" << miss_wang.tid
<< "\n教师姓名:" << miss_wang.name
<< "\n教师年龄:" << miss_wang.age
<< "\n辅导学生姓名:" << miss_wang.stu.name
<< "\n学生分数:" << miss_wang.stu.score << endl;
return 0;
}
8.6 结构体做函数参数
作用:将结构体做为参数向函数传递
传递方式有两种:
- 值传递
- 地址传递
#include <iostream>
#include <string>
using namespace std;
struct Student
{
int sid;
string name;
int score;
};
void printStu(Student stu)
{
cout << "printStu函数中打印学生信息:"
<< "\n\t姓名:" << stu.name
<< "\n\t学号:" << stu.sid
<< "\n\t分数" << stu.score << endl;
}
void printStuAddr(Student * stu)
{
stu->name = "赵六";
cout << "printStuAddr函数中打印学生信息:"
<< "\n\t姓名:" << stu->name
<< "\n\t学号:" << stu->sid
<< "\n\t分数" << stu->score << endl;
}
int main()
{
// 创建结构体
Student stu = { 202009, "yph", 100 };
cout << "main函数中打印学生信息:"
<< "\n\t姓名:" << stu.name
<< "\n\t学号:" << stu.sid
<< "\n\t分数" << stu.score << endl;
// 结构体做函数参数
// 值传递
printStu(stu);
//地址传递
printStuAddr(&stu);
cout << "main函数中打印学生信息:"
<< "\n\t姓名:" << stu.name
<< "\n\t学号:" << stu.sid
<< "\n\t分数" << stu.score << endl;
}
8.7结构体中const使用场景
作用:用const防止误操作
8.8案例
案例一
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值最终打印出老师数据以及老师所带的学生数据。
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct Student
{
string sname;
int score;
};
struct Teacher
{
string tname;
struct Student stu[5];
};
void print_info(Teacher teachers[], int len)
{
for (int i = 0; i <= len - 1; i++)
{
cout << "教师姓名:" << teachers[i].tname << "\n";
for (int j = 0; j <= 4; j++)
{
cout << "学生姓名:" << teachers[i].stu[j].sname
<< "\t学生分数:" << teachers[i].stu[j].score;
}
cout << endl;
}
}
void allocateValue(Teacher teas[], int len)
{
srand((unsigned int)time(NULL));
string tags = "ABCDE";
for (int i = 0; i <= len - 1; i++)
{
teas[i].tname = "Teacher_";
teas[i].tname += tags[i];
for (int j = 0; j <= 4; j++)
{
teas[i].stu[j].sname = "Stu_";
teas[i].stu[j].sname += tags[j];
teas[i].stu[j].score = rand() % 100 + 1;
}
}
}
int main()
{
// 创建结构体数组实例
Teacher teaArr[3];
// 计算数组长度
int len = sizeof(teaArr) / sizeof(teaArr[0]);
// 赋值
allocateValue(teaArr, len);
// 打印
print_info(teaArr, len);
return 0;
}
案例二
#include <iostream>
#include <string>
using namespace std;
struct hero
{
string name;
int age;
string sex;
};
void bubbleSort(struct hero heros[], int len)
{
for (int i = 0; i <= len - 1; i++)
{
for (int j = 0; j <= len - 1 - i; j++)
{
if (heros[j].age > heros[j + 1].age)
{
hero temp = heros[j];
heros[j] = heros[j + 1];
heros[j + 1] = temp;
}
}
}
}
void printHero(hero heros[], int len)
{
for (int i = 0; i <= len - 1; i++)
{
cout << heros[i].name << "\t" << heros[i].age << "\t" << heros[i].sex << endl;
}
}
int main()
{
hero heros[5] = {
{"刘备", 23, "男"},
{"张飞", 21, "男"},
{"关羽", 22, "男"},
{"赵云", 24, "男"},
{"貂蝉", 19, "女"}
};
int len = sizeof(heros) / sizeof(heros[0]);
bubbleSort(heros, len);
printHero(heros, len);
return 0;
}
通讯录管理系统
1.系统需求
2.创建项目
2.1创建项目
2.2创建cpp文件
3.菜单功能
功能描述:用户选择功能界面,如图
步骤:
- 封装函数显示菜单界面,如
void showMenu()
- 在main函数中调用
4.退出功能
功能描述:退出通讯录系统,
思路:根据用户不同的选择,进入不同的功能,可以使用switch分支结构
退出条件:用户输入0时退出
5.添加联系人
功能描述:实现添加联系人,联系人上限1000人,联系人信息包括:姓名、性别、年龄、联系电话、家庭地址
实现步骤:
- 设计联系人结构体
- 设计通讯录结构体
- main函数中创建通讯录
- 封装添加联系人函数
- 测试
6.显示联系人
7.删除联系人
8.查找联系人
9.修改联系人
10.清空联系人
11.完整代码
#include <iostream>
#include <string>
constexpr auto MAX = 100; // 通讯录最大人数;
using namespace std;
// 定义联系人结构体
struct Person
{
string m_name;
int m_sex; // 1为男, 2为女
int m_age;
string m_phone;
string m_addr;
};
// 定义通讯录结构体
struct Notebook
{
struct Person contactList[MAX]; // 联系人列表数组
int n_size; // 联系人个数
};
// 封装菜单功能函数
void showMenu()
{
cout << "***********************" << endl;
cout << "*** 1、添加联系人 ***" << endl;
cout << "*** 2、显示联系人 ***" << endl;
cout << "*** 3、删除联系人 ***" << endl;
cout << "*** 4、查找联系人 ***" << endl;
cout << "*** 5、修改联系人 ***" << endl;
cout << "*** 6、清空联系人 ***" << endl;
cout << "*** 0、退出通讯录 ***" << endl;
cout << "***********************" << endl;
}
// 1. 添加联系人
void addPerson(Notebook* cBook)
{
// 判断通讯录是否满了
if (cBook->n_size == MAX)
{
cout << "\a通讯录容量已达最大值!" << endl;
return;
}
else
{
// 添加具体联系人
// 姓名
string name;
cout << "新建联系人姓名:" << endl;
cin >> name;
cBook->contactList[cBook->n_size].m_name = name;
// 性别
int sex;
cout << "新建联系人性别:" << endl;
cout << " 1代表男\n 2代表女" << endl;
while (true)
{
cin >> sex;
if ((sex == 1) || (sex == 2))
{
break;
}
else
{
cout << "输入错误,请重新输入!" << endl;
}
}
cBook->contactList[cBook->n_size].m_sex = sex;
// 年龄
cout << "新建联系人年龄:" << endl;
int age;
cin >> age;
cBook->contactList[cBook->n_size].m_age = age;
// 联系方式
cout << "新建联系人号码:" << endl;
string number;
cin >> number;
cBook->contactList[cBook->n_size].m_phone = number;
// 家庭地址
cout << "新建联系人地址:" << endl;
string addr;
cin >> addr;
cBook->contactList[cBook->n_size].m_addr = addr;
// 更新通讯录人数
cBook->n_size++;
cout << "添加成功!" << endl;
system("pause");
system("cls");
}
}
// 2. 显示联系人
void showPerson(Notebook* cBook)
{
// 判断通讯录中人数是否为0
if (cBook->n_size == 0)
{
cout << "\a当前联系人为空!" << endl;
system("pause");
system("cls");
}
else
{
for (int i = 0; i <= cBook->n_size - 1; i++)
{
cout << "序号:" << i+1
<< "\t姓名:" << cBook->contactList[i].m_name
<< "\t性别:" << (cBook->contactList[i].m_sex == 1 ? "男" : "女")
<< "\t年龄:" << cBook->contactList[i].m_age
<< "\t联系方式:" << cBook->contactList[i].m_phone
<< "\t家庭地址:" << cBook->contactList[i].m_addr << endl;
}
system("pause");
system("cls");
}
}
// 检测联系人是否存在,如果存在返回在数组中的位置,否则返回-1
int isExist(Notebook* cBook, string name)
{
for (int i = 0; i <= cBook->n_size - 1; i++)
{
if (name == cBook->contactList[i].m_name)
{
return i; // 存在,返回位置
}
}
return -1; // 不存在,返回-1
}
// 3.删除指定联系人
void delPerson(Notebook* cBook)
{
cout << "请输入要删除的联系人:" << endl;
string name;
cin >> name;
int res = isExist(cBook, name);
if (res != -1)
{
for (int i = res; i <= cBook->n_size - 1; i++)
{
// 数据前移,逻辑删除
cBook->contactList[i] = cBook->contactList[i + 1];
}
cBook->n_size--;
cout << "删除成功!" << endl;
}
else
{
cout << "\a无法删除不存在的联系人!" << endl;
}
system("pause");
system("cls");
}
// 4.查找联系人
void findPerson(Notebook* cBook)
{
cout << "请输入你要查找的联系人:" << endl;
string name;
cin >> name;
int res = isExist(cBook, name);
if (res != -1)
{
cout << "序号:" << res+1
<< "\t姓名:" << cBook->contactList[res].m_name
<< "\t性别:" << cBook->contactList[res].m_sex
<< "\t年龄:" << cBook->contactList[res].m_age
<< "\t联系方式:" << cBook->contactList[res].m_phone
<< "\t家庭地址:" << cBook->contactList[res].m_addr
<< endl;
}
else
{
cout << "\a查无此人!" << endl;
}
system("pause");
system("cls");
}
// 5.修改联系人
void changePerson(Notebook* cBook)
{
cout << "请输入待修改联系人的姓名:" << endl;
string name;
cin >> name;
int res = isExist(cBook, name);
if (res != -1)
{
// 姓名
string name;
cout << "请输入(新)名称:" << endl;
cin >> name;
cBook->contactList[res].m_name = name;
// 性别
int sex;
cout << "性别:" << endl;
cout << " 1代表男\n 2代表女" << endl;
while (true)
{
cin >> sex;
if ((sex == 1) || (sex == 2))
{
break;
}
else
{
cout << "输入错误,请重新输入!" << endl;
}
}
cBook->contactList[res].m_sex = sex;
// 年龄
cout << "(新)年龄:" << endl;
int age;
cin >> age;
cBook->contactList[res].m_age = age;
// 联系方式
cout << "新号码:" << endl;
string number;
cin >> number;
cBook->contactList[res].m_phone = number;
// 家庭地址
cout << "(新)地址:" << endl;
string addr;
cin >> addr;
cBook->contactList[res].m_addr = addr;
}
else
{
cout << "\a通讯录中无此联系人信息!" << endl;
}
system("pause");
system("cls");
}
// 6.清空联系人
void cleanPerson(Notebook* cBook)
{
cout << "您确定要删除所有联系人吗?(y/n)" << endl;
string alert;
cin >> alert;
if (alert == "y")
{
cBook->n_size = 0; // 将当前记录的联系人数量置为0;
cout << "\a通讯录已清空!" << endl;
}
else
{
cout << "您已放弃删除所有联系人!" << endl;
}
system("pause");
system("cls");
}
// 主函数
int main()
{
// 通讯录结构体变量
Notebook cBook;
// 初始化通讯录人数
cBook.n_size = 0;
// 创建用户选择输入的变量
int select = 0;
while(true)
{
// 菜单调用
showMenu();
// 用户输入
cin >> select;
switch (select)
{
case 1: // 添加联系人
addPerson(&cBook);
break;
case 2: // 显示联系人
showPerson(&cBook);
break;
case 3: // 删除联系人
delPerson(&cBook);
break;
case 4: // 查找联系人
findPerson(&cBook);
break;
case 5: // 修改联系人
changePerson(&cBook);
break;
case 6: // 清空联系人
cleanPerson(&cBook);
break;
case 0: // 退出通讯录
cout << "欢迎下次使用!";
system("pause");
break;
default:
break;
}
}
return 0;
}