文章目录
申明:本篇博客无任何商业用途,仅仅是本人学习时的总结和笔记,如有侵权,请联系删除。由于本人技术有限,若有不正确或不妥之处,希望各位网友批评指正。
前言
C++学习汇总。
一、C++初阶
1.第一个C++程序。
代码如下(示例):
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
2.程序的注释
注释的作用:对代码的解释和说明,其目的是让自己或者其他人能更好地阅读和理解代码的含义。程序运行时会自动跳过被注释的内容。
注释分为单行注释和多行注释。
1.单行注释://描述信息
2.多行注释:/* 描述信息 */
3.变量
变量指的是把程序中准备使用的一段内存起一个简短,易于使用的名字,方便直接操作。
如何定义一个变量:数据类型 变量名=初始值;
#include<iostream>
using namespace std;
int main()
{
int a = 10;
cout << "整形变量a的初始值为" << a << endl;
return 0;
}
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。下面是一个实例:
#include <iostream>
using namespace std;
// 全局变量声明
int a = 20;
int main ()
{
// 局部变量声明
int a = 10;
cout << a;//输出10
return 0;
}
4.常量
常量通俗的说就是不可被修改的数值。
C++定义常量有两种方式。
1.#define定义的宏常量
定义:#define 常量名 常量值
2.const修饰的常变量
定义:const 数据类型 变量名=变量值
#include<iostream>
using namespace std;
#define Day 7 //define 定义的宏常量
int main()
{
cout << "一周总共有:" << Day << "天" << endl;
const int month = 12;//const 修饰的常变量
cout << "一年总共有:" << month << "月" << endl;
return 0;
}
5.关键字
关键字是C++中表示特定含义的名称,每一个关键字都用自己的使用意义。
不能用关键字给变量或者常量起名称。
如int int =10;//这个定义变量的方法就是错误的,会产生歧义
下面列举一些常用的关键字:
具体的使用方法在后续都会一一提到。
6.标识符
标识符是对变量,常量命名时的一个名称,方便直接对变量进行操作。
数据类型 标识符 =变量值
标识符命名规则:
1.所有的标识符必须用字母或下划线开头,而不能使用数字或者其他符号作为开头。
2.标识符不能是关键字。
3.标识符是由字母,数字,下划线构成。
4.标识符是区分大小写的。
7.数据类型
C++要求在定义变量或常量时是需要指定变量的类型,否则不能确定该给变量分配多少字节。
不同的数据类型有不同的长度和存储形式。
sizeof关键字
使用sizeof可以计算数据类型或变量在内存中所占空间的大小(单位是字节)。
#include<iostream>
using namespace std;
int main()
{
cout << "char在内存中占用的空间是" << sizeof(char) << endl;
cout << "short在内存中占用的空间是" << sizeof(short) << endl;
cout << "int在内存中占用的空间是" << sizeof(int) << endl;
cout << "long在内存中占用的空间是" << sizeof(long) << endl;
cout << "long long在内存中占用的空间是" << sizeof(long long) << endl;
cout << "float在内存中占用的空间是" << sizeof(float) << endl;
cout << "double在内存中占用的空间是" << sizeof(double) << endl;
return 0;
}
结论:char<short<int<=long<=long long
实型(浮点型)
实型是用于表示小数:
浮点型变量分为两种:
1.单精度 float float可以得到7位有效数字。
2.双精度 double double可以得到15位有效数字。
#include<iostream>
using namespace std;
int main()
{
float f = 3.14f;
cout << "f=" << f << endl;
double d = 3.14;
cout << "d=" << d << endl;
return 0;
}
double 和float都能很好地存放小数,区别在于他们所能表示的有效数字不同。
字符型
字符数据类型char是用来存放字符的。
语法格式:char ch=‘a’;
字符都是以ASCLL码值的形式存储在内存中。
字符变量的定界符是单引号,且一个字符变量中只能存放一个字符。
区别:‘1’ 字符1
1 数字1
字符‘1’是一个字符,只是形状像1,是以ASCLL码值的形式存储在内存中。
而数字1是一个整形类型,整形数据都以二进制的形式存放在计算机的内存中,其数值是以补码的形式表示的。
ASCII码共128个,其中0~31和127都是不可显示字符,如换行符、回车符等,剩下的32~126都是可显示字符。可显示字符由数字、字母、运算符组成,其中48~57是阿拉伯数字0-9,65~90是26个大写英文字母A-Z,97~122是26个小写英文字母a-z。
#include<iostream>
using namespace std;
int main()
{
char ch = 'a';
cout << "ch =" << ch << endl;
cout << "字符a的ASCLL码值是" << (int)ch << endl;
return 0;
}
转义字符
转义字符可以转换一些有特殊的含义的字符,简单来说,就是在一些字符前加上\使它具有特殊的含义。例如:\n代表换行,\t代表一个tab的位置。
所有的转义字符都算作一个字符。
#include<iostream>
using namespace std;
int main()
{
cout << '\\' << endl;
cout << '\32' << endl;
cout << '\x64' << endl;
return 0;
}
程序结果分析:
\则可以输一个
\32是一个八进制的数字,32转换为十进制是26,26作为ASCLL码值对应的字符是→
\x64是一个十六进制的数字,64转换为十进制是97,97作为ASCLL码值对应的字符是d
字符串类型
C++在C语言的基础上增加了字符串类型。字符串可以表示一串字符。
string 变量名=“字符串值”
#include<iostream>
using namespace std;
#include<string>
int main()
{
string str = "abc";
cout << str << endl;
return 0;
}
在使用C++的字符串类型定义一个字符串时,必须要引用头文件#include
布尔(bool)类型
在C++的关系运算和逻辑运算中,用0代表假,非0代表真。
bool数据类型只有两个取值,true(真),false(假)。非0值被转换成true(1),0被转换成false(0)。
bool数据类型占一个字节。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
bool flag = true;
cout << flag << endl;
flag = false;
cout << flag << endl;
flag = a > b;
cout << flag << endl;
return 0;
}
数据的输入
作用:从键盘获取一个数据
关键字:cin
语法:cin>>变量
下面以int整型数据类型举例:
#include<iostream>
using namespace std;
int main()
{
int a = 0;
cout << "给整形变量a赋值:";
cin >> a;
cout << "整形变量a的值是:" << a << endl;
return 0;
}
typedef声明
typedef可以为一个类型创建一个别名。
语法:typedef type newname;
例如:typedef int Aint ;
这个语句告诉编译器,可以用Aint替换int创建整形变量
Aint a;
这个语句是合法的,创建了一个整形变量a。
static关键字
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
#include <iostream>
// 函数声明
void func(void);
static int count = 10; /* 全局变量 */
int main()
{
while (count--)
{
func();
}
return 0;
}
// 函数定义
void func(void)
{
static int i = 5; // 局部静态变量
i++;
std::cout << "变量 i 为 " << i;
std::cout << " , 变量 count 为 " << count << std::endl;
}
输出:
变量 i 为 6 , 变量 count 为 9
变量 i 为 7 , 变量 count 为 8
变量 i 为 8 , 变量 count 为 7
变量 i 为 9 , 变量 count 为 6
变量 i 为 10 , 变量 count 为 5
变量 i 为 11 , 变量 count 为 4
变量 i 为 12 , 变量 count 为 3
变量 i 为 13 , 变量 count 为 2
变量 i 为 14 , 变量 count 为 1
变量 i 为 15 , 变量 count 为 0
8.运算符
C++提供了各式各样的运算符来解决算术运算和逻辑运算。
算术运算符
算数运算符包括 * - + / %(取模 取模得到的是余数)
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 3;
cout << "a+b=" << a + b << endl;//+运算符
cout << "a-b=" << a - b << endl;//-运算符
cout << "a*b=" << a * b << endl;//*运算符
cout << "a/b=" << a / b << endl;//\运算符
cout << "a%b=" << a % b << endl;//%运算符(得到的是两个数相除的余数)
return 0;
}
注意:两个数相除或取模,除数不可以为0,否则会报出异常。
取模运算只能针对整数。
自增和自减运算符
++i 前置递增 i先加1,在参与运算 。先让变量加1,在参与表达式的运算
i++ 后置递增 i先参与运算,i的自身的值在加1。变量先参与表达式的运算,最后变量的值在加1。
–i 前置递减 i先减1,在参与运算。
i-- 后置递减 i先参与运算,i的自身的值在减1。
#include<iostream>
using namespace std;
int main()
{
int i = 3;
int j = ++i;//运算顺序为 i=i+1;j=i;
int x = 3;
int y = x++;//运算顺序为 y=x; x=x+1;
cout << "j = " << j << " i = " << i << endl;
cout << "y = " << y << " x = " << x << endl;
return 0;
}
自减的运算规则也是同理。
赋值运算符
赋值运算符包括:= += -= *= /= %=
#include<iostream>
using namespace std;
int main()
{
// =
int a = 10;//=的作用是将10赋给变量a,变量a中存放的值就是10
cout << "a = " << a << endl;
// +=
a = 10;
a += 2;//等同于 a=a+2
cout << "a = " << a << endl;
// -=
a = 10;
a -= 2;//等同于 a=a-2
cout << "a = " << a << endl;
// *=
a = 10;
a *= 2;//等同于 a=a*2
cout << "a = " << a << endl;
// /=
a = 10;
a /= 2;//等同于 a=a/2
cout << "a = " << a << endl;
// %=
a = 10;
a %= 2;//等同于 a=a%2
cout << "a = " << a << endl;
return 0;
}
total *=sum + i;
total =total*(sum+i);
关系运算符
关系运算符包括: > < == != >= <=
关系运算符是用于对表达式的比较,并返回一个真(1)或假(0)的值。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
// == 的作用
int flag = (a == b);//== 判断a和b是否相等,如果相等就返回一个真的值,否则就返回假
cout << flag << endl;
// != 的作用
flag = (a != b);//== 判断a和b是否不相等,如果不相等就返回一个真的值,否则就返回假
cout << flag << endl;
// > 的作用
flag = (a > b);//> 判断a是否大于b,如果大于就返回一个真的值,否则就返回假
cout << flag << endl;
// < 的作用
flag = (a < b);//< 判断a是否小于b,如果Xuaiyu1就返回一个真的值,否则就返回假
cout << flag << endl;
return 0;
}
逻辑运算符
逻辑运算符包括 :! (非)&&(与)||(或)
逻辑运算符是用于对操作数是否满足条件的一种判断。用于根据表达式的值返回真或假。
#include<iostream>
using namespace std;
int main()
{
// ! 非
int a = 10;
int b = 20;
int c = 0;
int d = 0;
cout << !a << endl;//如果a为真,!a就返回一个假的值。反之如果a为假,则返回一个真的值。
// && 与
cout << (a&&b)<< endl;//如果a和b都为真,a&&b就返回一个真的值。反之如果a或者b为假,则返回假。
cout << (a&&c)<< endl;
// || 或
cout << (a||b)<< endl;//如果a和b中有一个为真,a||b就返回一个真的值。反之如果a和b都为假,则返回假。
cout << (a||c)<< endl;
cout << (c||d)<< endl;
return 0;
}
9.程序的流程结构
C++包含最基本的三种程序运行结构:顺序结构,选择结构,循环结构。
顺序结构:程序依次从上至下的顺序进行,直至程序结束,中途不发生跳转。
选择结构:判定是否满足该条件,如果满足,则执行该语句。
循环结构:判定是否满足该条件,如果满足,则一直循环执行某段代码,直至遇到跳出循环的条件。
顺序结构
顺序结构是各语句自上而下的顺序执行的,执行完上一个语句后无条件自动执行下一语句,直至程序结束。例如,求两个数的和。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
int c = a + b;
cout << "a+b=" << c << endl;
return 0;
}
选择结构
选择结构顾名思义就是需要进行选择,有两种或两种以上的可能性,并根据某个条件是否满足来决定是否执行指定的操作任务。例如,在一个岔路口,左转是去学校,右转是去超市,此时,你就需要判断你是要去学校还是超市,来决定是左转还是右转。
if语句实现选择结构
if语句的三种形式
1.单行if语句
if (表达式)
{
语句块
}
如果表达式为真,则执行语句块,之后继续执行下一语句。
2.多行if语句
if (表达式)
{
语句块1
}
else
{
语句块2
}
如果表达式为真,则执行语句块1,之后继续执行下一语句。
如果表达式为假,则执行语句块2,执行下一语句。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
cout << "请输入您的目的地" << endl;
cin >> str;
cout << "您的目的地是:" << str << endl;
if (str == "school")
cout << "左转" << endl;
else
cout << "右转" << endl;
return 0;
}
3.多条件if语句
if (表达式1)
{
语句块1
}
else if(表达式2)
{
语句块2
}
else if(表达式n)
{
语句块n
}
.
.
.
else
{
语句块n+1
}
满足该表达式则执行该语句块,如果一个都不满足,最后执行else中的语句块。
例如某次考试,90分以上(包括90)为优秀,70~90为良好, 60~70为合格,低于60为不合格,请输入考生成绩来判断考生的等的。
#include<iostream>
using namespace std;
int main()
{
double score = 0;
cout << "请输入您的成绩:" << endl ;
cin >> score;
cout << "您输入的成绩是:" << score << endl;
if (score >= 90)
{
cout << "您的成绩是优秀" << endl;
}
else if (score >= 70 && score < 90)
{
cout << "您的成绩是良好" << endl;
}
else if (score >= 60 && score < 70)
{
cout << "您的成绩是合格" << endl;
}
else
{
cout << "您的成绩是不合格" << endl;
}
return 0;
}
if语句的嵌套
在一个if语句中又包含另一个或者多个if语句称为if语句的嵌套。
if(表达式)
{
if(表达式)
{
语句块1
}
else
{
语句块2
}
}
else
{
if(表达式)
{
语句块3
}
else
{
语句块4
}
}
在一个if语句中,可能又细分为几种不同的选择,这个时候就需要内嵌if来解决问题。
例如,例如某次考试,90分以上(包括90)为优秀且大于98分奖励一本书,大于95分以上奖励一支笔,其他情况奖励一颗糖,70~90为良好, 60~70为合格,低于60为不合格,请输入考生成绩来判断考生的等的。
#include<iostream>
using namespace std;
int main()
{
double score = 0;
cout << "请输入您的成绩:" << endl ;
cin >> score;
cout << "您输入的成绩是:" << score << endl;
if (score >= 90)
{
cout << "您的成绩是优秀" << endl;
if (score >= 98)
{
cout << "您获得了一本书" << endl;
}
else if(score >= 95)
{
cout << "您获得了一支笔" << endl;
}
else
{
cout << "您获得了一颗糖" << endl;
}
}
else if (score >= 70 && score < 90)
{
cout << "您的成绩是良好" << endl;
}
else if (score >= 60 && score < 70)
{
cout << "您的成绩是合格" << endl;
}
else
{
cout << "您的成绩是不合格" << endl;
}
return 0;
}
需要注意的是if和else的语句使用中,else总是匹配距离自己最近的且没有配对的if。通过代码说明:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
if (a == 1)
if (b == 20)
{
cout << "哈哈" << endl;
}
else
cout << "呵呵" << endl;
return 0;
}
本题本质上是如果a= =1为假,就执行else语句,打印呵呵,如果b= =20为真,打印哈哈。但是结果是这样吗?
结果显示什么都没有,这是为什么?因为if(a==1)表达式为假,后面的程序都不会被执行,直接跳到return 0,所以结果什么都不显示。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
if (a == 1)
{
if (b == 20)
{
cout << "哈哈" << endl;
}
}
else
cout << "呵呵" << endl;
return 0;
}
将第二个if语句用大括号括起来,表明这作为if语句的语句块,如果a= =1为真,就执行该语句块,否则就执行else中的语句块。if(a==1)为假,执行else语句,所以程序执行出来是打印呵呵。
三目运算符
通过三目运算符的运算逻辑可以实现简单的判断。
语法:表达式1?表达式2:表达式3
如果表达式1的值为真则执行表达式2,并返回表达式2的结果。
如果表达式1的值为假则执行表达式3,并返回表达式3的结果。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
int max = (a > b ? a : b);
cout << "max=" << max << endl;
return 0;
}
分析:if(a>b)为假,就输出b的值,最终的输出的最大值是b。
switch语句实现多分支选择结构
语法:
switch(整形表达式)
{
case 常量1:语句1; break;
case 常量2:语句2; break;
case 常量N:语句N; break;
default:语句N + 1;
}
例如:某次考试A等为90分以上,B等为70~89分,C等为60 ~69分,D等为为60分一下。可以通过switch语句实现。
#include<iostream>
using namespace std;
int main()
{
char Grade = 0;
cout << "请输入您的等的:";
cin >> Grade;
cout << "您输入的是:" << Grade << endl;
switch (Grade)
{
case 'A':cout << "您的分数是90以上" << endl; break;
case 'B':cout << "您的分数是70~89" << endl; break;
case 'C':cout << "您的分数是60~69" << endl; break;
case 'D':cout << "您的分数是60一下" << endl; break;
default:cout << "输入错误,请重新输入" << endl;
}
return 0;
}
需要注意的是case语句后如果没有break语句,那么程序将会一直执行下去,直至程序结束或遇到break。
循环结构
在程序运行过程中,有些代码需要被重复的运行,这个时候就要通过循环来实现。
C++通过三种方法来实现循环:while语句,do…while语句,for语句。
while循环语句
语法:
while(循环条件表达式)
{
语句块;
}
如果循环条件表达式的结果为真,则一直重复执行语句块,直到表达式为假,就跳出循环,循环结束,执行下一语句。
用while循环打印数字0~9
#include<iostream>
using namespace std;
int main()
{
int i = 0;
while (i < 10)
{
cout << i << endl;
i++;
}
return 0;
}
do…while循环语句
语法:
do
{
循环语句;
}while(循环条件);
do…while语句的特点是先无条件的执行一次循环语句,然后在判断循环语句是否成立,若为真,重复执行循环体语句,直到循环条件为假,若循环条件为假,则最终的结果是执行了一次语句块的结果。
用do…while循环打印数字0~9
#include<iostream>
using namespace std;
int main()
{
int i = 0;
do
{
cout << i << endl;
i++;
} while (i < 10);
return 0;
}
for循环语句
基础语法:
for(循环变量赋初值;循环条件;循环的增减值)
{
循环语句;
}
for循环的执行流程是,先进行第一步循环变量赋初值,在判断循环条件是否为真,为真执行循环语句,在进行循环的增减值,在判定循环条件,直至循环条件为假结束循环。
用for循环打印数字0~9
#include<iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
cout << i << endl;
}
return 0;
}
①循环变量赋初值为0,判断表达式②是否为真,为真就执行循环语句③,循环变量增值④,在判定表达式②是否为真,一直循环执行②③④,直至表达式②为假,跳出循环。
for(i=0;i<n;i++)
循环的次数是n,当循环结束后,i的值是n。
嵌套循环
嵌套循环是一个循环里又嵌套了一个循环。
三种循环可以互相嵌套。
例如我们利用循环打印一个九九乘法表。
#include<iostream>
using namespace std;
int main()
{
int i = 0;//行数
for (i = 1; i <= 9; i++)
{
int j = 0;//列数
for (j = 1; j <= i; j++)
{
cout << j << "*" << i << "=" << i * j << " ";
}
cout << endl;
}
return 0;
}
break语句
break 语句的在循环语句中的作用是跳出整个循环体,结束循环。
在switch语句中,作用是终止case语句跳出当前switch语句。
在嵌套循环中,跳出最近的内层循环语句。
分析下面一段代码
#include<iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
cout << i << endl;
if (i > 5)
{
break;
}
}
return 0;
}
for循环打印数字0~9,但是i大于5时,就中止循环,所以后面的7,8,9都没有被输出。
continue语句
continue语句的作用是在循环语句中,中止当前的这一次循环,继续执行下一个循环直至循环结束。
例如:打印数字0~9中不能被2整除的数
#include<iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
continue;
}
cout << i << endl;
}
return 0;
}
如果i被2整除,就结束本次循环,不会再进行下一语句,能整除2的输出语句都不会被执行,直接跳转到i++这一语句。
goto语句
goto语句可以无条件的跳转到标记处的语句。
语法:goto 标记;
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
int main()
{
char arr[20] = { 0 };
system("shutdown -s -t 60");
again:
cout << "请注意你的电脑将在一分钟内关机,如果输入我是猪就取消" << endl;
cin >> arr;
if (strcmp(arr, "我是猪") == 0)
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
猜数游戏
#include<iostream>
using namespace std;
#include<ctime>
int main()
{
srand((unsigned int)time(NULL));
int num = rand() % 100 + 1;
int a = 0;//玩家猜的数
int max = 10;//设置最多可以猜10次
cout << "请输入一个1~100的整数" << endl;
while ((a != num) && (max > 0))//(a=num)猜对了跳出循环,max<0也跳出循环,10次机会用完,这种是失败了
{
cin >> a;
max--;
if (a > num)
{
cout << "猜大了,您还剩" << max << "次机会" << endl;
}
else if(a < num)
{
cout << "猜小了,您还剩" << max << "次机会" << endl;
}
}
if (a == num)
{
cout << "猜对了,游戏胜利" << endl;
}
else
{
cout << "很遗憾您失败了,这个数是" << num << endl;
}
return 0;
}
水仙花数
水仙花数是指一个 n 位数(n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。
利用for语句,打印出所有的三位数的水仙花数。
第一步:先打印所有的三位数。
第二步:求出这个三位数的个位,十位,百位上的数字。
第三步:判断这个数个位,十位,百位的三次方是否等于这个数本身。
#include<iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 100; i < 1000; i++)
{
int a = i % 10;//个位
int b = i / 10 % 10;//十位
int c = i / 100;//百位
if (a * a * a + b * b * b + c * c * c == i)
{
cout << i << endl;
}
}
return 0;
}
敲桌子
一圈人从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们就要敲桌子,若违法就要受到惩罚。用编程来实现。
#include<iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 1; i <= 100; i++)
{
int a = i % 10;//个位
int b = i / 10;//十位
int c = i % 7;
if (a == 7 || b == 7 || c == 0)//个位或者十位有7,能被7整除
{
cout << "敲桌子" << endl;
}
else
{
cout << i << endl;
}
}
return 0;
}
10.数组
数组是一组有序数据的集合。一批具有同名的同属性的数据就组成一个数组。
数组中的每个元素都应为同一个数据类型且数组中的元素在内存中都是连续存放的。
一维数组
定义一个一维数组:数据类型 数组名[元素个数]
;
一维数组的初始化
(1)在定义数组时就对数组全部元素赋初值
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
(2)不完全初始化,未被赋值的元素都被初始化为0
int arr[10] = { 0,1,2,3 };
(3)在数组中的全部元素都被赋初值时,由于元素的个数都已被确定,因此可以省略数组元素的个数
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
一维数组的引用
引用数组元素的语法为:数组名[下标]
#include<iostream>
using namespace std;
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
cout << arr[2] << endl;//输出数组arr的第三个元素的值
arr[5] = 10;//给数组arr第六个元素赋值10
cout << arr[5] << endl;
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
return 0;
}
需要注意的是数组的下标访问是从0开始的,下标为0表示的是数组的首元素 。
数组元素比大小
例如:在一个一维数组中有五个数,int arr[5]={10,20,30,40,50},找到最大的数并打印
#include<iostream>
using namespace std;
int main()
{
int arr[5] = { 10,20,30,40,50 };
int max = arr[0];
for (int i = 0; i < 5; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
cout << " max=" << max << endl;
return 0;
}
先假设定义一个最大值max,将数组中的首元素的值赋给max,通过循环遍历这个数组,如果数组中的第二个元素的值大于第一个元素的值,就将第二个元素的值赋给max,循环结束后,最终得到的max中存放的值就是数组中的最大值。
数组元素逆置
例如:int arr[5]={1,3,5,7,9},要求逆置后结果为{9,7,5,3,1}
实现思路:
#include<iostream>
using namespace std;
int main()
{
int i = 0;
int arr[5] = { 1,3,5,7,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
//打印未逆置前数组元素的值
cout << "逆置前数组元素的值:" <<" ";
for (i = 0; i < 5; i++)
{
cout << arr[i] << " " ;
}
cout << endl;
//1.确定起始位置元素的下标
int start = 0;
//2.确定最后一个元素的下标
int end = sz - 1;
//3.创建一个中间变量用来将起始位置元素的值放进去,防止逆置后找不到
int temp = 0;
//4.通过循环交换
while (start < end)
{
temp = arr[start];//先将起始位置元素的值赋给中间变量temp
arr[start] = arr[end];//将末尾元素的值赋给起始位置
arr[end] = temp;//将中间变量temp的值赋给末尾元素
start++;//起始位置下标++,指向起始位置的下一个元素
end--;//末尾位置下标--,指向末尾位置的上一个元素
}
//打印逆置后数组元素的值
cout << "逆置后数组元素的值:" << " ";
for (int j = 0; j < sz; j++)
{
cout << arr[j] << " " ;
}
cout << endl;
return 0;
}
冒泡排序
冒泡排序的算法思路是比较相邻的两个元素,如果第一个元素的值大于第二个元素的值,就将这两个数交换,这样大的数就在后面,通过循环在于下个元素的值比较,最终大数就会在最后面。
#include<iostream>
using namespace std;
int main()
{
int arr[] = { 9,8,7,6,5 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz-1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
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 < sz; i++)
{
cout << arr[i] << " ";
}
return 0;
}
二维数组
二维数组是在一维数组的基础上多加了一个维度。本质上是以数组作为数组元素的数组,即数组的数组。
二维数组又称为矩阵,写成行和列的形式更容易理解二维数组的逻辑结构。
定义一个二维数组:数据类型 数组名[常量][常量]
;
int iArray[3][4]表示这是一个三行四列的二维数组。
二维数组的初始化
(1)在定义数组时就对数组全部元素赋初值,这种赋值是把第一个括号内的数据传给第一行的元素,第二个括号内的数据传给第二行的元素,即按行赋值。
int arr[3][4] = { {0,1,2,3},{4,5,6,7},{8,9,10,11}};
(2)在初始化的时候将所有的数据都放在大括号里,系统会自动根据行号和列号进行分行赋值。
int arr[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11};
(3)不完全初始化,未被赋值的元素都被初始化为0
int arr[3][4] = { {0,1},{4,5},{8,9}};
(4)在数组中的全部元素都被赋初值时,可以省略第一维的长度不指定,即行的长度可以不指定,但第二维的长度不能省,即列的长度不能省,列的长度是控制每一行中有几个元素。可以根据总的元素长度和列数,求出一共有多少行。
int arr[][4] = { {0,1,2,3},{4,5,6,7},{8,9,10,11}};
二维数组的引用
二维数组的引用格式:数组名[下标][下标]
#include<iostream>
using namespace std;
int main()
{
int arr[3][4] = { {0,1,2,3},{4,5,6,7},{8,9,10,11} };
cout << arr[0][1] << endl;//输出数组arr的第0行第一列元素的值
arr[2][3] = 20;//给数组第二行第三列的元素赋值
cout << arr[2][3] << endl;
for (int i = 0; i < 3; i++)//行数
{
int j = 0;
for (j = 0; j < 4; j++)//列数
{
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}
下标变量共有3x4个,即arr[0][0],arr[0][1],arr[0][2],arr[0][3],arr[1][0]…arr[2][3]
二维数组是按行排列的,即按行顺序排放,先存放arr[0]行,在存放arr[1]行。每行中的元素也是依次排放的。用三行四列的形式表示二维数组仅仅能够更好地表示,但存储在内存中,各元素是紧挨着连续排放的。
引用数组元素是,arr[2][3]表示序号为2的行中序号为3列的元素。
在引用数组元素时,下标值应在数组大小的范围内。
数组的行和列的下标索引都是从0开始的。
a[0]表示二维数组中第一行数组的首元素地址。
a[0]+1是二维数组中的第一行数组的首元素地址的下一个地址。
arr[i][j]==* (*(arr+i)+j)
二维数组数组元素最大值
3x4的矩阵,编程求出元素的最大值以及所对应的行和列。
#include<iostream>
using namespace std;
int main()
{
int arr[3][4] = { {0,1,2,3},{4,5,6,7},{8,9,10,11} };
int row = 0;
int column = 0;
int max = arr[0][0];
for (int i = 0; i < 3; i++)
{
for (int j = 0;j < 4; j++)
{
if (arr[i][j] > max)
{
max = arr[i][j];
row = i;
column = j;
}
}
}
cout << "max=" << max << endl;
cout << "行号:" << row << endl;
cout << "行号:" << column << endl;
return 0;
}
假设最大的值是a[0][0],通过循环遍历二维数组,将之后的数一一与这个最大值比较,若a[0][1]大于a[0][0],则说明a[0][1]为最大值,将a[0][1]的作为最大值赋给max,循环往复,最终留下的max为最大值。
11.函数
函数(function)指的是在程序设计过程中,用来完成某一项特定的功能。
例如:在完成一个实现计算器功能的程序时,需要分工合作,员工A完成加法的功能,员工B完成减法的功能,员工C完成乘法的功能,员工D完成除法的功能。最终在main函数中调用已经被封装好的函数。使用函数可以减少代码重复量,使代码更好地被维护。
函数又分为自定义函数和库函数。自定义函数是自己定义自己调用的函数。库函数指的是有的程序功能需要被重复的使用,例如数据的输入和输出,为了更方便地使用,这些函数都被封装在库中,需要调用的时候引用头文件即可。
函数的定义
要想成功调用一个函数,必不可少的三部分是:函数的定义,函数的调用,函数申明。
函数定义语法:
返回值类型 函数名(形式参数)
{
函数体语句
}
函数调用语法:
函数名(实际参数)
函数申明语法:
返回值类型 函数名(形式参数);
例如:实现一个加法函数
#include<iostream>
using namespace std;
int main()
{
int Add(int x, int y);//申明
int a = 10;
int b = 10;
int c = Add(a, b);//调用
cout << "a+b=" << c << endl;
return 0;
}
int Add(int x, int y)//定义
{
return x + y;
}
在主函数中调用已经被封装好的Add函数,把实参a,b的值传给形参x,y,通过return返回x+y,在主函数中定义一个变量c来接收函数Add的返回值,变量c中存放的就是a和b的和。
值传递
在调用函数时,实参将数值传递给形参,称为值传递,且只能有实参传递给形参。
形参是实参的一份临时拷贝,改变形参的值并不会影响到实参,且形参在函数完成之后就被销毁了。
通过程序说明:
#include<iostream>
using namespace std;
void Swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a = 10;
int b = 20;
cout << "交换前a=" << a << "b=" << b << endl;
Swap(a, b);
cout << "交换后a=" << a << "b=" << b << endl;
return 0;
}
通过函数想要交换a和b的值,但是观察结果发现并没有实现交换
这就说明了改变形参的值并不会影响到实参
传址调用
#include<iostream>
using namespace std;
void Swap(int* px, int* py)
{
int temp = *px;
*px = *py;
*py = temp;
}
int main()
{
int a = 10;
int b = 20;
cout << "交换前a=" << a << "b=" << b << endl;
Swap(&a, &b);
cout << "交换后a=" << a << "b=" << b << endl;
return 0;
}
函数定义的四种类型
1.无参数无返回值
#include<iostream>
using namespace std;
void Test1()
{
cout << "this is test1";
}
int main()
{
Test1();
return 0;
}
void意为函数无返回值类型,即函数无返回值,调用这个函数不会把任何值带回main函数。
2.无参数有返回值
#include<iostream>
using namespace std;
int Test2()
{
cout << "this is test2" << endl;
return 100;
}
int main()
{
int a=Test2();
cout << a << endl;
return 0;
}
3.有参数无返回值
#include<iostream>
using namespace std;
void Test3(int a)
{
cout << "this is test3 a=" << a << endl;
}
int main()
{
int a = 10;
Test3(a);
return 0;
}
4.有参数有返回值
#include<iostream>
using namespace std;
int Test4(int a,int b)
{
return a > b ? a : b;
}
int main()
{
int a = 10;
int b = 20;
int c = Test4(a, b);
cout << c << endl;
return 0;
}
函数的分文件编写
在创建.h为后缀名的头文件中写函数的声明
在源文件中写函数的定义
11.指针
内存中的每一个字节单元都有一个编号,这个编号就是这个字节单元的地址。可以通过地址找到这个内存单元,这个地址指向这个内存单元,所以将地址形象化的称为“指针”,意思是通过它能找到以他为地址的内存单元。
指针就是个变量,只不过这个变量里存放的是地址。平时口语中所说的指针通常指的是指针变量,用来存放内存地址的变量。
总结:指针就是地址,口语中所说的指针通常指的是指针变量。
指针在内存中也是需要占用空间的,在32位平台是四个字节,64位平台是8个字节。
对于32位的机器,假设有32根地址线,每根地址线在寻址的时候都会产生高电平(1)或低电平(0)。
32位平台就有2的32次方个地址可以被使用。32位平台就会产生32个由0或者1组成的二进制序列,所以需要四个字节大小的空间来存储。
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111
指针变量
定义一个指针变量:数据类型* 变量名;
#include<iostream>
using namespace std;
int main()
{
int a = 10;//在内存中开辟四个字节的空间存放数字10
int* pa;//定义一个整形指针变量
pa = &a;//取出a的地址放入指针变量pa中
cout << &a << endl;
cout << pa << endl;
return 0;
}
那么该如何通过这个变量的地址找到这个变量呢 需要通过*解引用操作符
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int* pa;
pa = &a;
cout << a << endl;
*pa = 100;
cout << *pa << endl;
return 0;
}
指针类型的意义
任何数据类型的的指针变量都是占四个字节,都能够很好地存放一个变量的地址,那为什么还需要分char*,int* 这些指针类型呢
因为指针类型决定指针解引用能访问几个字节的空间
int* 的指针变量解引用能访问四个字节。
char*的指针变量解引用能访问一个字节。
决定指针+1跳过几个字节的地址
指针+1并不是简单地在地址上加1,而是指向下一个整形变量的地址。
可以看到int整形指针变量解引用能够修改四个字节的内容,而char指针变量解引用只能够修改一个字节的内容。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int* pa = &a;
char c = 'a';
char* pc = &c;
cout << pa << endl;
cout << pa + 1 << endl;
cout << (void*)pc << endl;
cout << (void*)(pc + 1) << endl;
return 0;
}
指针类型决定了指针+1一步能走多远,int整形指针变量加1跳过了四个地址,即跳过了一个int整形变量的地址,而char整形指针变量加1跳过了一个地址,即跳过了一个char整形变量的地址。
空指针
空指针NULL意为一个指针变量指向内存中编号为0的空间,将空指针NULL赋给一个指针变量等同于将0赋给指针变量。
空指针用于给指针变量进行初始化,空指针是不可以被访问的。
#include<iostream>
using namespace std;
int main()
{
int* pa = NULL;
*pa = 10;
cout << *pa << endl;//程序崩溃
return 0;
}
野指针
野指针意味指针在定义的时候没有被初始化,导致指针所指向的位置是随机的,是无法被预知的。使用野指针会导致程序错误。
#include<iostream>
using namespace std;
int main()
{
int* pa;//野指针 指针未初始化,指向了一块随机的内存
*pa = 20;
cout << *pa << endl;
return 0;
}
const修饰指针
const修饰指针 常量指针的特点是指针的指向可以修改,但是指针指向的值不可以被修改
#include<iostream>
using namespace std;
int main()
{
//const 修饰指针 常量指针
int a = 10;
int b = 20;
const int* p = &a;
//指针指向的值不可以改,指针的指向可以改
//*p = 20;错误
p = &b;//正确
return 0;
}
const修饰常量 指针常量的特点是指针的指向不可以修改,但是指针指向的值可以被修改
#include<iostream>
using namespace std;
int main()
{
//const 修饰常量 指针常量
int a = 10;
int b = 20;
int* const p = &a;
//指针指向的值可以改,指针的指向不可以改
*p = 20;//正确
//p = &b;错误
return 0;
}
const修饰既修饰指针,又修饰常量 特点是指针的指向和指针指向的值都不可以被修改
#include<iostream>
using namespace std;
int main()
{
//const 修饰指针和常量
int a = 10;
int b = 20;
const int* const p = &a;
//指针的指向和指针指向的值都不可以被修改
//*p = 20;错误
//p = &b;错误
return 0;
}
指针和数组
不仅仅是变量有地址,一个数组中有若干个元素,每个元素存储在内存中也有相对应的地址。指针变量可以指针变量,也可以指向数组的元素。可利用指针访问数组中的元素。
#include<iostream>
using namespace std;
int main()
{
int arr[] = { 1,2,3,4,5 };
int* p = arr;
cout << p << endl;
cout << &arr[0] << endl;
return 0;
}
通过代码可以说明数组名就是数组首元素的地址,代码int* p = arr的含义是把数组的首元素地址赋给了指针变量p,而不是把数组的整个数组地址赋给p。
指针的运算
#include<iostream>
using namespace std;
int main()
{
int arr[] = { 1,2,3,4,5 };
int* p = arr;
cout << arr[0] << endl;
cout << "利用指针访问第一个元素:" << *p << endl;
//cout << "利用指针访问第二个元素:" << *(++p) << endl;
cout << "利用指针访问第五个元素:" << *(p + 4) << endl;
for (int i = 0; i < 5; i++)
{
cout << *(p + i) << " ";
}
cout << endl;
return 0;
}
若指针变量p已指向数组中的某个元素,p+1意为指向数组中的下一元素的地址,p-1意为指向数组中的上一元素的地址
*(p + i)是p+i所指向的数组元素的值,等价于arr[i]。
指向函数的指针
指向函数的指针顾名思义就是指针指向一个函数,指针中存放了一个函数的地址。
函数名是函数地起始地址。
例如:int(*p)(int, int);
这表示指针指向一个函数,这个函数有两个整形的参数,且返回值也是整形。
#include<iostream>
using namespace std;
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int(*p)(int, int) = Add;
int c = (*p)(a, b);
cout << c << endl;
return 0;
}
指针数组函数案例
创建一个函数实现冒泡排序
#include<iostream>
using namespace std;
void Bubble_sort(int* arr, int len)
{
for(int i = 0; i < len-1; i++)
{
for(int j = 0; j < len - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int arr[] = { 9,5,1,2,6,7,3,4,8,0 };
int len = sizeof(arr) / sizeof(arr[0]);
Bubble_sort(arr, len);
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
指针更多内容:指针详解
12.结构体
结构体是指由一系列具有相同类型或不同类型的数据构成的数据集合。例如,描述一个学生,这个学生是由姓名,性别,年龄,学校,家庭地址等等信息构成,这个时候就需要用到结构体。
语法:
struct 结构体名
{
结构体成员列表
};
定义结构体变量
1.先声明结构体类型,在定义该类型变量
#include<iostream>
#include<string>
using namespace std;
struct Student
{
string name;
string sex;
int age;
string school;
string address;
};
int main()
{
struct Student s1;
struct Student s2;
}
2.在声明结构体类型的同时定义该类型变量
#include<iostream>
#include<string>
using namespace std;
struct Student
{
string name;
string sex;
int age;
string school;
string address;
}s3, s4;
3.不指定结构体类型而直接定义结构体类型变量
#include<iostream>
#include<string>
using namespace std;
struct
{
string name;
string sex;
int age;
string school;
string address;
}s5;
结构体变量的初始化和引用
引用结构体成员变量的值语法:结构体变量名:成员名
#include<iostream>
#include<string>
using namespace std;
struct Student//定义Student结构体
{
string name;
string sex;
int age;
string school;
string address;
};
int main()
{
struct Student s1 = {"张三","男",18,"xx学校","北京"};//初始化结构体
cout << "姓名:" << s1.name << " 性别:" << s1.sex << " 年龄:" << s1.age << " 学校:" << s1.school << " 地址:" << s1.address << endl;
s1.name = "李四";//给结构体元素赋值
cout << "姓名:" << s1.name << endl;
return 0;
}
结构体数组
假设有十个学生需要用学生类型的结构体变量来定义,这个时候需要用到数组。
#include<iostream>
#include<string>
using namespace std;
struct Student//定义Student结构体
{
string name;
string sex;
int age;
};
int main()
{
struct Student arr[3] = { {"张三","男",18},{"李四","女",19},{"王五","男",20} };//初始化结构体
for (int i=0;i < 3; i++)
{
cout << "姓名:" << arr[i].name << " 性别:" << arr[i].sex << " 年龄:" << arr[i].age << endl;
}
return 0;
}
结构体指针
结构体指针意为指针变量指向一个结构体,即指针变量中存放的是结构体的变量。
通过指针访问结构体变量中的数据:指针变量名->成员名
#include<iostream>
#include<string>
using namespace std;
struct Student//定义Student结构体
{
string name;
string sex;
int age;
};
int main()
{
struct Student s = { "张三","男",18 };
struct Student* p = &s;
cout << "姓名:" << p->name << " 性别:" << p->sex << " 年龄:" << p->age << endl;
return 0;
}
结构体嵌套
结构体嵌套是一个结构体变量中又嵌套定义了一个结构体变量。
例如:公司中的员工,公司的结构体中又包含一个员工的结构体
#include<iostream>
#include<string>
using namespace std;
struct Staff//定义Staff结构体
{
string name;
int id;
int age;
};
struct Company//定义Company结构体
{
string name;
long telephone;
string address;
struct Staff staff;
};
int main()
{
struct Company company = { "xx公司",5205455,"北京",{"张三",10000,20} };
cout << "员工姓名:" << company.staff.name << endl;
cout << "公司名:" << company.name << " 公司电话:" << company.telephone << " 公司地址:" << company.address
<< " 员工姓名:" << company.staff.name << " 员工编号:" << company.staff.id << " 员工年龄:" << company.staff.age << endl;
return 0;
}
结构体做函数参数
结构体作为函数参数
#include<iostream>
#include<string>
using namespace std;
struct Student//定义Student结构体
{
string name;
string sex;
int age;
};
void Init(struct Student* ps)
{
ps->name = "张三";
ps->sex = "男";
ps->age = 20;
}
void PrintStudent(const struct Student* ps)
{
cout << "姓名:" << ps->name << " 性别:" << ps->sex << " 年龄:" << ps->age << endl;
}
int main()
{
struct Student s ;
Init(&s);
PrintStudent(&s);
return 0;
}
结构体案例
学校正在做毕业设计,总共三名老师,每名老师带五个学生,设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放五名学生的数组作为成员
学生的结构体成员有姓名,考试分数。
创建结构体数组存放三名老师,通过函数给每个老师及所带的学生赋值。
最终打印出老师数据以及老师所带的学生数据。
#include<iostream>
#include<string>
#include<ctime>
using namespace std;
//定义学生结构体
struct Student
{
//学生姓名
string sName;
//学生分数
int score;
};
//定义老师结构体
struct Teacher
{
//老师姓名
string tName;
//学生数组
struct Student sArray[5];
};
//给老师和学生赋值的函数
void Init(struct Teacher tArray[],int len)
{
string nameSeed = "ABCDE";
//给老师赋值
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));
//1.创建3名老师的结构体数组
struct Teacher tArray[3];
//2.通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
Init(tArray, len);
//3.打印所有老师及所带的学生信息
PrintInfo(tArray, len);
return 0;
}
案例2
将结构体中的数据按照年龄升序排列并打印
#include<iostream>
#include<string>
using namespace std;
struct People
{
string name;
int age;
string sex;
};
//按照年龄的升序排序
void Bubble_sort(struct People pArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (pArray[j].age > pArray[j + 1].age)
{
struct People temp = pArray[j];
pArray[j] = pArray[j + 1];
pArray[j + 1] = temp;
}
}
}
}
int main()
{
struct People pArray[5] = { {"张三",20,"男"},
{"李四",18,"男"},
{"王五",23,"女"},
{"赵四",25,"男"},
{"宋五",24,"女"} };
int len = sizeof(pArray) / sizeof(pArray[0]);
cout << "排序前" << endl;
for (int i = 0; i < len; i++)
{
cout << "姓名:" << pArray[i].name << " 年龄" << pArray[i].age << " 性别" << pArray[i].sex << endl;
}
cout << "排序后" << endl;
Bubble_sort(pArray, len);
for (int i = 0; i < len; i++)
{
cout << "姓名:" << pArray[i].name << " 年龄" << pArray[i].age << " 性别" << pArray[i].sex << endl;
}
}
通讯录管理系统
通讯录是用于记录亲人、好友信息的工具。
通讯录主要有以下功能:
添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人
显示联系人:显示通讯录所有联系人信息
删除联系人:按照姓名删除指定联系人
查找联系人:按照姓名查看指定联系人信息
修改联系人:按照姓名重新修改指定联系人信息
清空联系人:清空通讯录中所有信息
退出通讯录:退出当前使用的通讯录
#include<iostream>
#include<string>
#define Max 2000
using namespace std;
//设计联系人结构体
struct Person
{
//姓名
string Name;
//性别(1 男 2 女 )
int Sex;
//年龄
int Age;
//电话
string Phone;
//住址
string Address;
};
//设计通讯录结构体
struct AddressBooks
{
//通讯录中保存的联系人数组
struct Person personArray[Max];
//通讯录中当前记录联系人个数
int Size;
};
//1.添加联系人
void addPerson(struct AddressBooks* abs)
{
//判断通讯录是否已满,如果满了就不在添加
if (abs->Size == Max)
{
cout << "通讯录已满 无法添加!" << endl;
}
else
{
//添加具体的联系人
//姓名
string name;
cout << "请输入姓名:" << endl;
cin >> name;
abs->personArray[abs->Size].Name = name;
//性别
int sex = 0;
cout << "请输入性别:" << endl;
cout << "1 --- 男" << endl;
cout << "2 --- 女" << endl;
while (true)
{
cin >> sex;
if (sex == 1 || sex == 2)
{
abs->personArray[abs->Size].Sex = sex;
break;
}
else
{
cout << "输入有误,请重新输入" << endl;
}
}
//年龄
cout << "请输入年龄:" << endl;
int age = 0;
cin >> age;
abs->personArray[abs->Size].Age = age;
//电话
cout << "请输入联系电话:" << endl;
string phone;
cin >> phone;
abs->personArray[abs->Size].Phone = phone;
//住址
cout << "请输入家庭住址:" << endl;
string address;
cin >> address;
abs->personArray[abs->Size].Address = address;
//更新通讯录人数
abs->Size++;
cout << "添加成功" << endl;
system("pause");
system("cls");
}
}
//2.显示联系人
void showPerson(struct AddressBooks* abs)
{
//判断通讯录中人数是否为0,如果为0,提示记录为空
if (abs->Size == 0)
{
cout << "当前记录为空" << endl;
}
else
{
for (int i = 0; i < abs->Size; i++)
{
cout << "姓名:" << abs->personArray[i].Name << "\t";
cout << "性别:" << (abs->personArray[i].Sex == 1 ? "男" : "女") << "\t";
cout << "年龄:" << abs->personArray[i].Age << "\t";
cout << "电话:" << abs->personArray[i].Phone << "\t";
cout << "住址:" << abs->personArray[i].Address << endl;
}
}
system("pause");
system("cls");
}
//查找是否存在此人
int isExist(struct AddressBooks* abs, string name)
{
for (int i = 0; i < abs->Size; i++)
{
if (abs->personArray[i].Name == name)//找到了
{
return i;
}
}
return -1;//没找到
}
//3.删除联系人
void DeletePerson(struct AddressBooks* abs)
{
cout << "请输入你要删除的联系人" << endl;
string name;
cin >> name;
int ret = isExist(abs, name);//先查找此人是否存在
if (ret != -1)
{
//找到此人,进行删除
for (int i = ret; i < abs->Size; i++)
{
//数据前移
abs->personArray[i] = abs->personArray[i + 1];
}
abs->Size--;
cout << "删除成功" << endl;
}
else
{
cout << "查无此人" << endl;
}
system("pause");
system("cls");
}
//4.查找联系人
void findPerson(struct AddressBooks* abs)
{
cout << "请输入查找联系人姓名:" << endl;
string name;
cin >> name;
int ret = isExist(abs, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
cout << "找到此人" << endl;
cout << "姓名:" << abs->personArray[ret].Name << "\t";
cout << "性别:" << (abs->personArray[ret].Sex == 1 ? "男" : "女") << "\t";
cout << "年龄:" << abs->personArray[ret].Age << "\t";
cout << "电话:" << abs->personArray[ret].Phone << "\t";
cout << "住址:" << abs->personArray[ret].Address << endl;
}
system("pause");
system("cls");
}
//5.修改联系人
void modifyPerson(struct AddressBooks* abs)
{
cout << "请输入你要修改的联系人" << endl;
string name;
cin >> name;
int ret = isExist(abs, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
//姓名
string name;
cout << "请重新输入姓名:" << endl;
cin >> name;
abs->personArray[ret].Name = name;
//性别
int sex = 0;
cout << "请输入性别:" << endl;
cout << "1 --- 男" << endl;
cout << "2 --- 女" << endl;
while (true)
{
cin >> sex;
if (sex == 1 || sex == 2)
{
abs->personArray[ret].Sex = sex;
break;
}
else
{
cout << "输入有误,请重新输入" << endl;
}
}
//年龄
cout << "请重新输入年龄:" << endl;
int age = 0;
cin >> age;
abs->personArray[ret].Age = age;
//电话
cout << "请重新输入联系电话:" << endl;
string phone;
cin >> phone;
abs->personArray[ret].Phone = phone;
//住址
cout << "请重新输入家庭住址:" << endl;
string address;
cin >> address;
abs->personArray[ret].Address = address;
cout << "修改成功" << endl;
}
system("pause");
system("cls");
}
//6.清空联系人
void cleanPerson(struct AddressBooks* abs)
{
cout << "您是否决定清空通讯录(是>否)?" << endl;
string ret ;
while (true)
{
cin >> ret;
if (ret == "是" || ret == "否")
{
if (ret == "否")
{
cout << "操作被中止" << endl;
break;
}
else
{
abs->Size = 0;//将当前记录联系人数量置为0,做逻辑清空操作
cout << "通讯录已清空" << endl;
break;
}
}
else
{
cout << "输入错误,请重新输入" << endl;
}
}
system("pause");
system("cls");
}
//显示菜单
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;
}
int main()
{
//创建通讯录结构体变量
struct AddressBooks abs;
abs.Size = 0;
int select = 0;//创建用户选择输入的变量
while (true)
{
showMenu();
cin >> select;
switch (select)
{
case 1:// 1.添加联系人
addPerson(&abs);
break;
case 2://2.显示联系人
showPerson(&abs);
break;
case 3: //3.删除联系人
DeletePerson(&abs);
break;
case 4://4.查找联系人
findPerson(&abs);
break;
case 5://5.修改联系人
modifyPerson(&abs);
break;
case 6://6.清空联系人
cleanPerson(&abs);
break;
case 0://0.退出通讯录
cout << "欢迎下次使用" << endl;
return 0;
break;
default:
break;
}
}
return 0;
}