C++初识
命名空间
解决名字冲突using namespace std;
(标准命名空间,std是standard的缩写)
用来给cout 和endl加作用域,提前声明作用域,就不用每个都打作用域
让程序访问std命名空间的方法:
void simon(int n);
int main() { simon(3); cout << “Pick an integer: “; int count; cin >> count; simon(count); cout << “Done!” << endl;
system("pause");
return 0;
}
void simon(int n) { cout << “Simon says touch your toes “ << n << “times.” <<endl; }
- 写在函数里,只有写了命名空间的函数才能调用
```cpp
#include<iostream>
void simon(int n);
int main()
{
using namespace std;
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
system("pause");
return 0;
}
void simon(int n)
{
using namespace std;
cout << "Simon says touch your toes " << n << "times." <<endl;
}
- 在特定的函数中使用类似using std::cout的指令,给在特定的元素使用,例如cout
- 完全不使用,而是在每个元素前加作用域std::,例如std::cout,std::endl
头文件
函数是集成在系统中的,用头文件相当于是拷贝系统中的对应函数到代码文件中,接下来的代码才有效
语法:#include<iostream>
这种语句叫prepocessor statement(预处理指令),因为发生在真正编译之前,所以叫预处理指令
任何#开头的就是预处理指令
头文件有下面两种写法
#include
#include”iostream”:自己写的在工程里的用这种写法
注释
在代码中加一些解释和说明,方便别的程序员解读
VS快捷键:
- 启用注释:
Ctrl+k+c
- 取消注释:
Ctrl+k+u
两种格式
单行注释//:对单行代码的说明
- 多行注释/**/对整体代码的说明
主函数
函数体是程序进行指定目标的运算的模块,其中以 main 命名的函数被称为 主函数,有且只有一个,是程序运行的入口,代码开始执行的地方
int main()
{
std::cin.get() ;
float a = 1.0, b = 2.0;
std::cout << a << std::endl;
std::cout << a/b << std::endl;
std::cout << std::sqrt(a) << std::endl;
std::cout << std::acos(-1) << std::endl;
std::cout << std::sin(30.0/180.0*acos(-1)) << std::endl;
return 0;
}
(上述代码的作用是在三行分别输出 a, a/b , √a, arccos(_−_1), sin(30) 的计算结果)
cout:显示器
cin:键盘
endl=end line就是换行
int不会返回任何值,是因为main函数会返回一个0,代表运行结束,只有main才会这样,这里的返回值是返回给系统的
return 0退出系统
这里的输出用std::cout << a << std::endl;来写是因为没有用using namespace std;所以每个都要加上std::的作用域
标准输入输出
标准输出(显示屏)
cout
cout << a;
cout << b;
cout << c;
cout << a << b << c << endl;
printf(C风格)
是一个格式输出函数
格式:printf("格式控制字符串",输出列表)
格式控制字符串:是用双引号括起来的一个字符串,包括”格式声明”和”普通字符”
普通字符:是需要在字符串中原样输出的字符,
格式声明:是由%开头和格式字符组成的,表示指定数据输出的格式.如:%d
d格式符:用来输出一个有符号的十进制整数
- %d
- %5d 指定输出的数据占5列,数据显示在5列的右侧
int a = 3; printf("a=%d\n",a); printf("a=%5d\n",a);//会空五行再输出a的值
c格式符:用来输出一个字符
char a = 'x'; printf("这是一个字符:%c\n", a);
f格式符:用来输出浮点型;lf是double
printf("这个数是:%f\n", 3.1415926897535); printf("这个数是:%lf\n", 3.1415926897535);//这是double类型 printf("这个数是:%.2f\n", 3.1415926897535);//精度到小数点后两位
标准输入(键盘)
cin
一次获取一个数据
int a, b, c; cin >> a; cin >> b; cin >> c; cout << a << " " << b << " " << c << endl;
小记:连续输入的多个数据可以通过空白符(空格,tab,回车)来间隔
一次获取多个数据
int a, b, c; cin >> a >> b >> c; cout << a << " " << b << " " << c << endl;
注意:>> 是会过滤掉不可见的字符(如 空格 回车,TAB 等)
cin>>noskipws>>input[j];//不想略过空白字符,那就使用 noskipws 流控制scanf
格式化输入函数
注意:因为scanf已经被抛弃了,所以使用时会报错要给文件关掉报错要加上#pragma ```cpp int a; // scanf(“%d”, &a); // printf(“%d\n”, a);
// scanf(“a的值是:%d”, &a); //a的值是:12 // printf(“a:%d\n”, a);
float b;
int c;
scanf("%d%f%d", &a, &b, &c); //多个数据输入默认以空白符间隔
printf("a=%d b=%f c=%d\n", a, b, c);
<a name="xbtSZ"></a>
## 变量
**作用:**给一段指定的内存空间命名,方便操作这段内存,变量的值是可以暴露出来,可以修改的<br />**语法:**`数据类型 变量名 = 初始值`,`数据类型 变量名(初始值)`,`数据类型 变量名{ 初始值 }`<br />**示例:**
```cpp
#include<iostream>
using namespace std;
int main()
{
int a = 10;
//C++写法
int b(20);
//C++11新增写法,新增写法能避免一些错误
int c = { 30 };
int d{ 40 };
int e{}; //大括号不写值,会初始变量为0
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << "e = " << e << endl;
}
局部变量
1.定义在函数内的变量
2.作用的范围只限于定义它的函数体内,它的生命周期只限于该函数体内,出该函数它的内存就会被释放,该变量就不能用
3.不同的函数可以定义同名的变量,因为都是局部变量,所以相互不影响
4.定义的时候如果没有赋初值则为随机值
全局变量
1.定义在函数外面的变量
2.作用域是整个程序,对在他定义之后的任何地方都能够使用它,包含函数体内,其他文件中也可以
3.如果函数体内定义了和全局变量同名的局部变量,则起作用的是局部变量,否则就是全局变量
4.全局变量如果没有赋值则初始化为0
静态变量
定义一个变量的时候用static修饰的变量,在程序执行的时候会一直存在,生存周期伴随整个程序,但是如果它是定义在函数体内的局部变量则作用域仍只限于该函数体内(静态局部变量)
静态全局变量
- 限制了该全局变量只能在当前文件中使用
- 不管是静态全局变量还是静态局部变量没有赋初始值都是默认为0
常量
作用:用于记录程序中不可更改的数据,比如一周7天是约定熟成的不可改变的参数
语法:c++中有两种方式
1.#define宏常量:#define 常量名 常量值;#define day 7
通常跟着头文件后面,主函数之前写,表示一个常量
2.const修饰的变量:const 数据类型 常量名 = 常量值;const int month = 12
或 int const month = 12
通常在变量定义前加关键字const,修饰该变量为常量,该变量不可修改
关键字
作用:是c++预先保留的单词,定义常量和变量时不能使用,因为c++已经优先占用了
asm | do | if | return | typedef |
---|---|---|---|---|
auto | double | inline | short | typeid |
bool | dynamic_cast | int | signed | typename |
break | else | long | sizeof | union |
case | enum | mutable | static | unsigned |
catch | explicit | namespace | static_cast | using |
char | export | new | stuct | virtual |
class | extern | operator | switch | void |
const | false | private | template | volatile |
const_cast | float | protected | this | wchar_t |
continue | for | public | throw | while |
default | friend | register | true | |
delete | goto | reinterpret_cast | try |
标识符命名规则
作用:c++规定标识符(常量,变量)命名,有一套自己的规则
- 标识符不能是关键字(因为系统已经占用了)
- 标识符只能由字母,数字,下划线组成
- 第一个字符必须为字母或下划线
- 标识符中字母区分大小写
- 标识符最好做到见名知意的效果,方便阅读
数据类型
c++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存;是给变量分配一个合适的内存空间,优化代码,否则浪费内存
字节
1个字节 == 8位 二进制
0000 0000 == 0
0000 0001 == 1
…
1111 1111 == 2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0 ==255
2个字节 == 16位 二进制
0000 0000 0000 0000 == 0
…
1111 1111 1111 1111 ==
二进制最前面一位是代表正负
0是负,1是正
sizeof关键字
作用:利用sizeof可以统计数据类型占内存大小
语法:sizeof(数据类型/变量)
示例:
cout<< "short类型所占内存空间为:" << sizeof(short/a) << endl;
整型
作用:整形变量表示的是整数类型的数据
有一下几种表示整形的类型,区别在于占用内存空间大小不同
[int]是可以省略的意思
数据类型 | 占用空间 | 取值范围 |
---|---|---|
short(短整型) | 2字节 | (-2^15~2^15-1) |
int(整型) | 4字节 | (-2^31~2^31-1) |
long [int](长整型) | windows为4字节,linux为4字节(32),8字节(64位) | (-2^31~2^31-1) |
longlong [int](长长整型) | 8字节 | (-2^63~2^63-1) |
实型(浮点型)
作用:用于表示小数
浮点型变量分为两种:两种区别在于表示有效数字范围不同
- 单精度float:精确到小数点后六位,第七位开始会乱码
双精度double:精确到小数点后15位 | 数据类型 | 占用空间 | 有效数字范围 | | —- | —- | —- | | float | 4字节 | 7位有效数字 | | double | 8字节 | 15~16位有效数字 | | long double | 8字节 | 15~16位有效数字 |
两种类型都会输出六位有效数字,如果最后一位四舍五入为0,0会被省略掉
- 如果直接输出小数不赋予类型,默认是double型
- 键盘输入默认也是double型,如果用float类型接收会降低精度,输出的位数越多越容易出错
示例:
float f1 = 3.14f; //默认小数是双精度,再转换成单精度,值后面的f直接定义小数为单精度,省去转换步骤
double d1 = 3.14;
//科学计数法
float f2 = 3e2; //3*10^2
float f2 = 3e-2; //3*0.1^2
控制输出浮点型数据精度:
函数格式:fixed << setprecision(8)
#include<iomanip>//一定要有这个头文件
cout << fixed << setprecision(3) << 3.1415;//这样就能输出小数,并且会进行四舍五入计算
解释:
fixed:被固定;setprecision:设置精度;(3):括号里是精确到小数点后几位,3表示小数点后三位
无符号类型
不能存储负值的无符号变体
作用:增大变量存储的最大值;如:short表示范围为-32768 ~+32768,无符号版本范围为0~65535
注意:值没有负数的时候才用
示例:
unsigned short a;
unsigned int b;
unsigned c; //这个也是int的无符号;因为unsigned本身就是unsigned int的缩写
unsigned long d;
unsigned long long e;
字符型
作用:字符型变量用于表示单个字符
语法:char ch = ‘ a ‘ ;
注意:
- 字符型变量只能用单引号
- 单引号内只能有一个字符,而不是字符串
字符型变量只占用1个字节
字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放到存储单元
示例:
char ch = 'a';
cout << (int)ch << endl; //字符型变量转对应ASCII编码
//得出结果97就是a的ASCII编码
ASCII码值:
为了方便运算和存储,给每个字符对应定一个整数做为等价存在,就是ASCII码值
比较重要的ASCII码值,这两个就可以往后推算出bcd等
a:97
A:65
推算方式:相同字符小写比大写大32,相隔字符相差1
其他ASCII编码及解释:
ASCII编码大致分为以下两部分:
ASCII非打印控制字符:ASCII表上的数字0-31分配给了控制字符,用于控制像打印机等一些外围设备。
ASCII打印字符:数字32-126分配给了能在键盘上找到的字符,当查看或者打印文档时候就会发现。
字符和整型的转换:
a+3,结果为68;因为a是字符型占一个字节,3是整型占四个字节,由于字节占用空间少的会往占用空间多的进行转换,所以a被转换为整型直接使用a的ASCII码值,要转为字符型(char)(a+3)就行
转义字符
作用:用于表示一些不能显示出来的ASCII字符
现阶段常用转义字符:\n \\ \t
示例:
cout << " hello world " << endl; //endl就是换行
cout << " hello world \ n "; //输出效果和上面一样\n就是换行
cout << " \\ " << endl; //这样才能输出反斜杠
cout << " aa\t hello world " << endl; //水平制表符 \t 可以整齐输出数据,有八个字符
字符串型
作用:表示一串字符,给字符串起个名,方便后期调用
两种风格
c风格字符串:char 变量名[ ] = “ 字符串 “(加[]是为了能使用””否则无法使用),这是一个字符数组
char str1[ ] = " hello world ";
cout << str1 << endl;
c++风格字符串:string 变量名 = “ 字符串值 “
#include<string> //用c++风格要带上这个头文件,否则无法使用
string str2 = " hello world ";
cout << str2 << endl;
布尔类型bool
作用:代表真假判断(c++中只要不是0都为真)
bool有两个值:
真(true)本质是1
假(false)本质是0
bool类型占1个字节大小
示例:
int main(){
bool flag = true;
cout << flag << endl; // 1
flag = false ;
cout << flag << endl; // 0
return 0;
}
数据的输入
作用:用于从键盘获取数据,输入用户自定义数据
关键字:cin
语法:cin >> 变量
(>>右移运算符)
示例:
// 整型输入
int a = 0;
cout << " 请输入整型变量 " << endl;
cin >> a;
cout << "输出变量a=" << a << endl;
// 浮点型输入
double d = 0;
cout << " 请输入浮点型变量 " << endl;
cin >> d;
cout << "输出变量d=" << d << endl;
float b = 3.14f;
cout << " 请输入浮点型变量 " << endl;
cin >> b;
cout << "输出变量b=" << b << endl;
// 字符型输入
char ch = ' a ';
cout << " 请输入字符型变量 " << endl;
cin >> ch;
cout << "输出变量ch=" << ch << endl;
// 字符串型输入
#include<string> // 字符串的头文件不能忘,否则无效
string str = " hello ";
cout << " 请输入字符串型变量 " << endl;
cin >> str;
cout << "输出变量str=" << str << endl;
// 布尔型输入
bool flag = false;
cout << " 请输入布尔型变量 " << endl;
cin >> flag; // 布尔型只能输入1 或 0
cout << "输出变量flag=" << flag << endl;
自动类型转换和强制类型转换
自动类型转换
- 在表达式中,char 和 short 类型的值,无论有符号还是无符号,都会自动转换成 int 或者 unsigned int(如果 short 的大小和 int 一样,unsigned short 的表示范围就大于 int,在这种情况下,unsigned short 被转换成 unsigned int)。因为它们被转换成表示范围更大的类型,故而把这种转换称为“升级(promotion)”。
- 若参与运算的数据类型不一致,则首先线转换成同一个数据类型,然后进行运算,类型转换方向按数据长度增加的方向进行,以保证精度不降低
如:char->short->int->long->float->double,箭头左边的替换成箭头右边的
- 在任何涉及两种数据类型的操作中,它们之间等级较低的类型会被转换成等级较高的类型
- 在赋值过程中,如果” = “两边的数据类型不同,先把右边的表达式转化成左边的类型,再赋值,这个过程可能导致右边的值的类型升级,也可能导致其类型降级(demotion)
- 作为参数传递给函数时,char 和 short 会被转换成 int,float 会被转换成 double。使用函数原型可以避免这种自动升级
强制类型转换
格式:(类型名)(表达式/变量名)
(float) 7/2
;原本两个都是整型,7前面加上float后7变为浮点型
注意事项:
强制类型转换的时候是先运算等号右边,再把右边的结果存储在一个临时变量,再赋值给左边,所以如果强转结果,会出现结果怎么转都是原来没转之前的结果;为了得到正确结果,先让” = “左边的其中一个变量先转为目标类型,之后的值也会更着第一个转,得出的结果就是目标结果
示例:
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
long long int s;
a = 1562345672;
b = 1456789343;
c = 1234567832;
cout << a << " " << b << " " << c << endl;
s=(long long)a + b + c;//先给左边的一个变量强转类型,就能得到转换后的正确结果
cout << (long long)(a + b + c) << endl;//如果没有上边这行代码直接这样转,得出的结果和没强转之前一样
cout << s<<endl;
return 0;
}
运算符
- 运算符是有优先级的,如果等级相等则由左往右算
- 如果不等先算优先级高的
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | -3 | -3 |
+ | 加 | 10+5 | 15 |
- | 减 | 10-5 | 5 |
* | 乘 | 10*5 | 50 |
/ | 除 | 10/5 | 2 |
% | 取模(取余) | 10%3 | 1 |
++ | 前置递增 | a=2; b=++a | a=3; b=3 |
++ | 后置递增 | a=2; b=a++ | a=3; b=2 |
— | 前置递减 | a=2; b=—a | a=1; b=1 |
— | 后置递减 | a=2; b=a— | a=1; b=2 |
示例1:
// 加减乘除
int a1 = 10;
int b1 = 3;
cout << a1 + b1 << endl;
cout << a1 - b1 << endl;
cout << a1 * b1 << endl;
cout << a1 / b1 << endl; // 两个整数相除结果依然是整数,会吧小数部分去除
int a2 = 10;
int b2 = 20;
cout << a2 / b2 << endl; // 结果为0,整数相除,结果为整数,小数部分会省略
int a3 = 10;
int b3 = 0;
cout << a3 / b3 << endl; // 输出错误,因为两数相除,除数不为0
double d1 = 0.5;
double d2 = 0.25;
cout << d1 / d2 << endl; // 小数相除,结果也为小数
示例2:
// 取模(求取余数:余数是除法剩余的数)
int a1 = 10;
int b1 = 3;
cout << a1 % b1 << endl; // 因为取模是除法运算,也同样遵循两数相除,除数不为0,取模运算,两数必须是整数没否则会有语法错误
double d1 = 0.5;
double d2 = 0.25;
cout << d1 / d2 << endl; // 小数不可以做取模运算,结果出错
示例3:
// 前置递增
int a = 10;
++a; // 让变量+1
cout << "a=" << a << endl; // 结果为11
// 后置递增
int b = 10;
a++; // 让变量+1
cout << "b=" << b << endl; // 结果为11
// 前置递增和后置递增的区别
// 前置:先让变量+1,再进行表达式运算
int a2 = 10;
int b2 = ++a2 * 10;
cout << "a2=" << a2 << endl; // 结果为11
cout << "b2=" << b2 << endl; // 结果为110
// 后置先进行表达式运,算再让变量+1
int a3 = 10;
int b3 = a3++ * 10;
cout << "a3=" << a3 << endl; // 结果为11
cout << "b3=" << b3 << endl; // 结果为100
赋值运算符
作用:用于赋值给变量
注意:这里的 = 不是,两变量相等,而是把等号右边的值赋给左边
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a=2 ; b=3 | a=2 ; b=3 |
+= | 加等于 | a=0 ; a+=2 | a=2 |
-= | 减等于 | a=5 ; a-=3 | a=2 |
*= | 乘等于 | a=2 ; a*=2 | a=4 |
/= | 除等于 | a=4 ; a/=2 | a=2 |
%= | 模等于 | a=3 ; a%=2 | a=1 |
示例:
// =
int a = 10;
a = 100;
cout << " a= " << a << endl; // a=100
// +=
int a = 10;
a += 2;
cout << " a= " << a << endl; // a=a+2, a=12
// -=
int a = 10;
a -= 2;
cout << " a= " << a << endl; // a=a-2, a=8
// *=
int a = 10;
a *= 2;
cout << " a= " << a << endl; // a=a*2, a=20
// /=
int a = 10;
a /= 2;
cout << " a= " << a << endl; // a=a/2, a=5
// %=
int a = 10;
a %= 2;
cout << " a= " << a << endl; // a=a%2; 余数为0; a=0
比较运算符
作用:用于表达式的比较,并返回一个真或假值
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | 0 |
!= | 不等于 | 4!=3 | 1 |
< | 小于 | 4<3 | 0 |
> | 大于 | 4>3 | 1 |
<= | 小于等于 | 4<=3 | 0 |
>= | 大于等于 | 4>=3 | 1 |
比较运算符直接输出使用时要加上阔号,否则报错 cout << (a < b) << endl;
这里是优先级问题
优先级:>,<,<=,>=的优先级比==高
void main()
{
int a = 5, b = 4, c =3 , d = 2;
if(a > b > c)//这行不会执行,因为:a与b比较完会变成一个1表示真,1是小于c的所以该项条件不成立。跳过执行
printf(“%d\n”, d);
else if((c - 1 >= d) == 1)
printf(“%d\n”, d+1);
else
printf(“%d\n”, d+2);
}
逻辑运算符
作用:用于根据表达式的值返回真或假值
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
|| | 或 | a||b | 如果a和b有一个为真,则结果为真,二者都为假,结果为假 |
&& | 与 | a&&b | 如果a和b都为真,则结果为真,否则为假 |
! | 非 | !a | 如果a为假,则!a为真;如果a为真,则!a为假,这就是取反 |
优先级:!优先于&&优先级高于||
void main()
{
int i = 1,j = 1,k = 2;
if( (j++ || k++) && i++ )//j和k只要有其中一个达成条件就不会执行另一个,先从左往右判断,这里的j已经被满足条件,所以k会跳过判断导致k的值不变
printf(“%d,%d,%d\n”, i, j, k);
}
示例:
// 非!
int a = 10;
// c++中,除0都为真
cout << !a << endl; // 0
cout << !!a << endl; // 1
// 与&&
int a = 10;
int b = 10;
cout << (a && b) << endl; // 1
int a = 0;
int b = 10;
cout << (a && b) << endl; // 0
int a = 0;
int b = 0;
cout << (a && b) << endl; // 0
// 或||
int a = 10;
int b = 10;
cout << (a || b) << endl; // 1
int a = 0;
int b = 10;
cout << (a || b) << endl; // 1
int a = 0;
int b = 0;
cout << (a || b) << endl; // 0
按位逻辑运算符
作用:位移运算是直接对整数在内的二进制位进行操作
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
& | 按位与 | a & b | 0&0=0;0&1=0;1&0=1;1&1=1;总结:两位同时为1,结果才为1,否则为0 |
| | 按位或 | a | b | 0|0=0;0|1=1;1|0=1;1&1=1;总结:只要由一个为1,其值就为1 |
^ | 异或 | a ^ b | 0^0=0;0^1=1;1^0=1;1^1=0;总结:相同为0,相异为1 |
~ | 按位取反 | ~a | ~1=0;~0=1;对一个二进制数按位取反,即将0变1,1变0 |
操作方式示例:
程序流程结构
c++支持最基本的三种程序运行结构:顺序结构,选择结构,循环结构
- 顺序结构:程序按顺序执行,不发生跳转
- 选择结构:依据条件是否满足,有选择的执行相应功能
-
选择结构
if语句
作用:执行满足条件的语句
if语句的三种形式: 单行格式if语句
- 多行格式if语句
- 多条件的if语句
单行格式if语句
语法:if ( 条件 ) { 条件满足执行的语句; }
示例:
// 用户输入分数,如果分数大于600,为重本,屏幕输出
// 用户输入分数
int main(){
int score = 0
cout << " 输入分数 :" << endl;
cin >> score;
// 打印用户输入分数
cout << " 你输入的分数是 :" << endl;
// 判断分数是否大于600,如果大于,输出
// 注意!!if条件后面不要加分号,否则代码失效
if ( score > 600 ) // if ( score > 600 ); 不能这么写
{
cout << " 恭喜考上重本 " << endl;
}
}
多行格式if语句
语法:if ( 条件 ) { 条件满足执行的语句; }
else { 条件不满足执行的语句; }
示例:
// 用户输入分数,如果分数大于600,为重本,屏幕输出,没考上重本,打印:未考上重本
// 用户输入分数
int main(){
int score = 0
cout << " 输入分数 :" << endl;
cin >> score;
// 打印用户输入分数
cout << " 你输入的分数是 :" << endl;
// 判断分数是否大于600,如果大于,输出考上,反之输出未考上
if ( score > 600 ) // 大于六百分执行下面大括号内容
{
cout << " 恭喜考上重本 " << endl;
}
else// 不大于六百分执行else大括号内容
{
cout << " 下年继续 " << endl;
}
}
多条件的if语句
语法:if ( 条件1 ) { 条件1满足执行的语句; } else if ( 条件2 ) { 条件2满足执行的语句; } …… else { 都不满足执行的语句; }
示例:
// 如果分数大于600,为重本,屏幕输出,大于500考上二本,大于400考上三本,小于等于四百分是为未考上本科
// 用户输入分数
int main(){
int score = 0
cout << " 输入分数 :" << endl;
cin >> score ;
// 打印用户输入分数
cout << " 你输入的分数是 :" << endl;
// 判断分数是否大于600,如果大于,输出考上,反之输出未考上
// 重本
if ( score > 600 )
{
cout << " 恭喜考上重本 " << endl;
}
// 二本
else if ( score > 500 )
{
cout << " 恭喜考上二本 " << endl;
}
// 三本
else if ( score > 400 )
{
cout << " 恭喜考上三本 " << endl;
}
// 未考上
else
{
cout << " 下年继续 " << endl;
}
}
嵌套if语句
在if语句中,可以嵌套使用if语句达到更精准的条件判断
案例需求:
提示用户输入一个分数
分数大于600考上重本,大于500考上二本,大于400考上三本,其余视为未考上本科
本科分数线中,大于700入北大,大于650清华,大于600人大
示例:
int main(){
int score = 0
cout << " 输入分数 :" << endl;
cin >> score;
// 打印用户输入分数
cout << " 你输入的分数是 :" << endl;
// 判断分数是否大于600,如果大于,输出考上,反之输出未考上
// 重本
if ( score > 600 )
{
cout << " 恭喜考上重本 " << endl;
if ( score > 700 )
{
cout << " 北大 " << endl;
}
else if ( score > 650 )
{
cout << " 清华 " <<endl;
}
else
{
cout << " 人大 " << endl;
}
}
else if ( score > 500 )
{
cout << " 恭喜考上二本 " << endl;
}
else if ( score > 400 )
{
cout << " 恭喜考上三本 " << endl;
}
else
{
cout << " 下年继续 " << endl;
}
}
练习案例:三只小猪称体重
#include<iostream>
using namespace std;
int main() {
//1.三只小猪称体重,判断哪只最重
//创建三只小猪的变量
int pig1 = 0;
int pig2 = 0;
int pig3 = 0;
//2.用户分别输入三只小猪的重量
cout << " 输入pig1的体重:";
cin >> pig1;
cout << " 输入pig2的体重:";
cin >> pig2;
cout << " 输入pig3的体重:";
cin >> pig3;
cout << endl;
cout << " pig1的体重:" << pig1 << endl;
cout << " pig2的体重:" << pig2 << endl;
cout << " pig3的体重:" << pig3 << endl;
cout << endl;
//3.判断哪只最重
//先判断pig1,pig2
if (pig1 > pig2)
{
if (pig1 > pig3)
{
cout << " pig1最重" << endl;
}
else//pig3比pig1重
{
cout << " pig3最重" << endl;
}
}
else//pig2比pig1重
{
if (pig2 > pig3)
{
cout << " pig2最重" << endl;
}
else//pig3比pig2重
{
cout << " pig3最重" << endl;
}
}
system("pause");
return 0;
}
三目运算符(条件运算符)
作用:通过三目运算符实现简单判断
语法:表达式1 ? 表达式2 : 表达式3; c = ( a > b ? a : b )
解释:
如果表达式1的值为真,执行表达式2,并返回表达式2的结果;
如果表达式1的值为假,执行表达式3,并返回表达式3的结果;
示例:
#include<iostream>
using namespace std;
int main() {
// 创建三个变量
// 将a与b作比较,将变量大的值赋予给c
int a = 10;
int b = 20;
int c = 0;
c = (a > b ? a : b);
cout << " c=" << c << endl;// 此处表达式1为假,返回表达式3,c赋值为b=20
// c++中三目运算符返回的是变量,可以继续赋值
(a > b ? a : b) = 100;// 根据判断之后,相当于a或者b被赋值100
cout << " a=" << a << endl;
cout << " b=" << b << endl;
system("pause");
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int score;
cin >> score;
char grade = score >= 90 ? 'A' : score >= 60 ? 'B' : 'C';//三目运算符的嵌套使用
cout << grade << endl;
return 0;
}
switch语句
作用:执行多条件分支语句
优缺点:
switch缺点:判断时只能是整型或者字符型,不可以是一个区间
switch有点:结构清晰,执行效率高
语法:
switch ( 表达式 ) // 表达式满足哪个结果,就执行哪个结果的case,前面结果都没出现的话就用default
{
case 结果1 : 执行语句; break ;
case 结果2 : 执行语句; break ;
……
default : 执行语句; break ;
}
//(表达式)的数据类型只能是整型、字符型,浮点型会报错;字符型是能转换为整型
//case的结果只能是一个常量值,不能是表达式
示例:
#include<iostream>
using namespace std;
int main()
{
// 给电影评分
// 10-9 经典
// 8-7 非常好
// 6-5 一般
// 5以下 烂片
// 提示用户给电影评分
cout << "请打分" << endl;
// 用户开始进行打分
int score = 0;
cin >> score;
cout << " 打分为:" << score << endl;
// 根据用户输入的分数来提示最后结果
switch (score)//括号是输入的变量名
{
case 10://10是输入的值
cout << " 经典 " << endl;
break; // 退出当前分支,断开打印
case 9:
cout << " 经典 " << endl;
break;
case 8:
cout << " 非常好 " << endl;
break;
case 7:
cout << " 非常好 " << endl;
break;
case 6:
cout << " 一般 " << endl;
break;
case 5:
cout << " 一般 " << endl;
break;
default:
cout << " 烂片 " << endl;
break;
}
system("pause");
return 0;
}
注意:
- switch语句中表达式类型只能是整型或字符型
- case里如果没有break,那程序会一直执行下去
总结:与if语句比,对于多条件判断时,switch的结构清晰,执行效率高,缺点是switch不可判断区间
循环结构
while循环语句
作用:满足循环条件,执行循环语句
语法:while ( 循环条件 ) { 循环语句;}
解释:只要循环条件为真,就执行循环语句
注意:写循环时候,一定要给循环提供跳的出的出口,避免死循环
示例:
// 在屏幕中打印0~9这10个数字
int num = 0;
// while()中填入循环条件
while (num < 10)
{
cout << num << endl ;
num++ ;
}
while循环案例练习:猜数字
案例描述:系统随机生成1-100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或者过小,如果猜对,恭喜玩家胜利,并推出游戏
#include<iostream>
using namespace std;
//time系统时间头文件,加了这个下面的系统时间time函数才有效
#include<ctime>
int main() {
//添加随机数种子:利用系统时间生成随机数,防止每次随机数都一样
srand((unsigned int)time(NULL));
//1.系统生成随机数
int num = rand() % 100+1; //rand()%100+1 生成0+1-99+1的随机数,但这个是伪随机
//2.玩家进行猜测
int val = 0;//玩家输入的数据
while (1)
{
cin >> val;
//3.判断玩家的猜测
//猜错 提示过大或过小,重返第2步
if (val > num)
{
cout << "猜大了" << endl;
}
else if (val < num)
{
cout << "猜小了" << endl;
}
else
{
cout << "猜对了" << endl;//猜对退出游戏
break;//在循环中,可以利用这个关键字推出当前循环
}
}
system("pause");
return 0;
}
do……while循环语句
作用:满足循环条件,执行循环语句
语法:do{ 循环语句 } while ( 循环条件 );
注意:与while的区别在于do……while会先执行一次循环语句,再判断循环条件
示例:
// 在屏幕中打印0~9这10个数字
int num = 0 ;
// do{}while()
do
{
cout << num << endl ;
num++ ;
}
while ( num < 10 );
总结:与while循环的区别在于,do……while限制性一次循环语句再判断循环条件
do……while循环案例练习:水仙花数
案例描述:水仙花数是指一个三位数,他的每个位上的数的三次幂的和等于它本身
用do while求出所有三位数中的水仙花数
#include<iostream>
using namespace std;
int main() {
//1.先打印所有的三位数
int num = 100;
do
{
//2.从所有的三位数找到水仙花数
int a = 0; //个位
int b = 0; //十位
int c = 0; //百位
a = num % 10; //获取数字的个位
b = num / 10 % 10; //获取数字十位
c = num / 100; //获取数字百位
if (a*a*a + b*b*b + c*c*c == num)//如果是水仙花数才打印
{
cout << num << endl;
}
num++;
}
while (num < 1000);//do{}while();的冒号要记得
system("pause");
return 0;
}
for循环
作用:满足循环条件,执行循环语句
语法:for(起始表达式,条件表达式,末尾循环体){ 循环语句; }
for(int i = 0; i < 10; i++){cout << i << endl;}
示例:
// 在屏幕中打印0~9这10个数字
int main() {
for( int i = 0; i < 10; i++)
{
cout << i << endl;
}
}
详解:
注意:for循环中的表达式,要用分号进行分隔
总结:while,do……while,for都是开发中常用的循环语句,for循环结构比较清晰,比较常用
案例练习:敲桌子
案例描述:从1开始数到数字100,如果数字中个位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出
#include<iostream>
using namespace std;
int main() {
//1.先输出1~100
for(int i = 0; i <= 100; i++)
{
//2.从100个数字中找到特殊数字,打印敲桌子
//如果个位有7,7的倍数,十位有7的数,打印为敲桌子
if( i%7==0 || i%10==7 || i/10==7 )//如果是特殊数字,打印敲桌子(||是表示只要达成其中一个条件就可执行)
{
cout << "敲桌子" << endl;
}
else//如果不是特殊数字,打印为数字
{
cout << i << endl;
}
}
system("pause");
return 0;
}
嵌套循环
作用:在循环中再嵌套一层循环,解决一些实际问题(外层执行一次,内层执行一周)
例如下面的图片,就要用到嵌套循环
#include<iostream>
using namespace std;
int main() {
//利用嵌套循环实现星图效果
//打印更多行
for (int i = 0; i < 10; i++)
{
//打印一行
for(int j = 0; j < 10; j++)
{
cout << "* ";
}
cout << endl;//换行
}
system("pause");
return 0;
}
注意事项:两个一样的变量,输出会根据就近原则选择输出里的最近的,所以变量名最好不要一样
for (int i = 0; i < 10; i++)
{
for(int i = 0; i < 10; i++)
cout << "* " << i <<endl;
}
练习案例:九九乘法表
#include<iostream>
using namespace std;
int main() {
//九九乘法表
/*由图可知
列数*行数=结果
列数<=行数*/
//打印行数
for (int i = 1; i <= 9; i++)
{
//cout << i << endl;
//列数 列数<=行数
for(int j = 1; j <= i; j++)
{
cout << j << "*" << i << "=" << j*i << "\t";// "\t"是用来对齐的
}
cout << endl;//换行
}
system("pause");
return 0;
}
跳转语句
break语句
作用:用于跳出选择结构或者循环结构
break使用时机:
- 出现在switch语句中,作用是终止case并跳出switch
- 出现在循环语句中,作用是跳出当前循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
switch语句中
#include<iostream>
using namespace std;
int main()
{
cout << "请选择副本难度" << endl;
cout << "1.普通" << endl;
cout << "2.中等" << endl;
cout << "3.困难" << endl;
int select = 0;//创建输入变量
cin >> select; //用户输入
switch (select)
{
case 1:
cout << "选择普通难度" << endl;
break;//退出switch语句
case 2:
cout << "选择中等难度" << endl;
break;
case 3:
cout << "选择困难难度" << endl;
break;
default:
break;
}
}
循环语句中
#include<iostream>
using namespace std;
int main()
{
for (int i = 0; i < 10; i++)
{
//如果i=5,退出打印,不再打印
if (i == 5)
{
break;//退出循环,直接在这一行停止往下执行
}
cout << i << endl;
}
}
嵌套循环语句中
#include<iostream>
using namespace std;
int main()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (j == 5)
{
break;//退出内循环
}
cout << "* ";
}
cout << endl;
}
}
continue语句
作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
示例:
#include<iostream>
using namespace std;
int main()
{
for (int i = 0; i < 100; i++)
{
//奇数输出,偶数不输出
if (i % 2 == 0)
{
continue; //这之后的代码不再执行,返回继续循环,break是切断不再循环
}
cout << i << endl; //输出结果13579……
}
}
注意:continue并没有是整个循环终止,而break会跳出循环
goto语句
作用:无条件跳转代码
语法:goto 标记;
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
示例:
#include<iostream>
using namespace std;
int main()
{
cout << "1" << endl;
cout << "2" << endl;
goto flag;
cout << "3" << endl;
cout << "4" << endl;
flag: //这个是标记
cout << "5" << endl;
cout << "6" << endl;
//输出结果是:1、2、5、6
}
总结:程序中不建议使用goto语句,避免程序混乱
数组
概述:数组就是一个集合,里面存放了相同的数据元素,方便对一堆数据的取用
特点:
- 数组中的每个数据元素都是相同的数据类型
- 数组是由连续的内存位置组成的,所以可以快速查询指定值
一维数组
一维数组定义方式
定义方式:
数据类型 数组名 [ 数组长度 ];
数据类型 数组名 [ 数组长度 ] = { 值1,值2……};
数据类型 数组名 [ ] = { 值1,值2……};
示例: ```cpp //1.数据类型 数组名 [ 数组长度 ]; int arr[5]; //给数组中的元素进行赋值 arr[0] = 10; arr[1] = 20; arr[2] = 30; arr[3] = 40; arr[4] = 50; //访问数据类型 //数组元素的下标是从0开始索引 cout << arr[0] << endl; cout << arr[1] << endl; cout << arr[2] << endl; cout << arr[3] << endl; cout << arr[4] << endl;
//2.数据类型 数组名 [ 数组长度 ] = { 值1,值2……}; //如果在初始化数据时,值没有全部填写,会用0补充,如:int arr2 [5] = { 10,20,30} ;输出会是:10,20,30,0,0 int arr2 [5] = { 10,20,30,40,50} ; //用循环方式输出数组中的元素 for ( int i = 0; i < 5; i++ ) { cout << arr2 [ i ] << endl;//输出结果和上面一样 }
//3.数据类型 数组名 [ ] = { 值1,值2……};
//输入了多少个值,数据长度会自动计算有多少个
int arr3 [ ] = { 90,80,70,60,50,40,30,20,10} ;
for ( int j = 0; j < 9; j++ )
{
cout << arr3 [ j ] << endl;
}
```cpp
//初始化赋值
int a[5] = {1,2}//没有赋值的元素都默认为0
//有20个字节,每个元素4字节
int a[5];//完全没有赋初值的话,输出的是随机值
//先定义后赋值
int a[5];//输出时,剩下没有赋值的会输出随机值而不是0
a[0] = 1;
a[1] = 2;
总结:
- 数字名的命名规范与变量名命名规范一致,不要和变量重名
- 数组中下标是从0开始索引
一维数组数组名称
一维数组名称的用途:
- 可以统计整个数组在内存中的长度
- 可以获取数组在内存中的首地址
注意:arr是常量不可赋值
示例:
#include<iostream>
using namespace std;
int main()
{
//统计整个数组占空间大小
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "整个数组占用空间为:" << sizeof(arr) << endl; //输出结果为40,因为一个int占用4字节,这里有10个int
cout << "每个元素占用空间为:" << sizeof(arr[0]) << endl; //输出结果为4
cout << "数组中元素个数为:" << sizeof(arr) / sizeof(arr[0]) << endl; //输出结果为10,常用来计算数组的长度
//通过数组名查看数组首地址
cout << "数组首地址为:" << arr << endl; //输出结果为004FFA68(16进制)
cout << "数组首地址为:" << (int)arr << endl; //输出结果为17431292(10进制),内存分配是动态的,每次运行都会不一样
cout << "数组第一个元素地址为:" << (int)&arr[0] << endl; //输出结果为17431292(10进制),第一个元素就是数组的首地址
cout << "数组第二个元素地址为:" << (int)&arr[1] << endl; //输出结果为17431296(10进制),与第一个元素相差四个字节刚好是一个int的占用
//arr[0]是一个数,所以要在前面加&取址符才能输出arr[0]的地址
return 0;
}
案例练习
案例1描述:
在一个数组中记录了五只小猪的体重,如:int arr[5] = {300,350,200,400,250};
并打印最重的小猪体重
#include<iostream>
using namespace std;
int main() {
//创建5只小猪体重的数组
int arr[5] = { 300,350,200,400,250 };
//从数组中找到最大值
int max = 0;//先认定一个最大值为0
for(int i = 0; i < 5; i++ )
{
if(arr[i]>max)
{
//如果访问的数组中的元素比认定的最大值还大,更新最大值
max = arr[i]
}
}
//打印最大值
cout << "最重的小猪体重为:" << max << endl;
system("pause");
return 0;
}
案例2描述:数组元素逆置
请声明一个5个元素数组,并且将元素逆置
(如元素组为:1,3,2,5,4;逆置后:4,5,2,3,1)
#include<iostream>
using namespace std;
int main() {
//创建数组
int arr[5] = { 1,3,2,5,4 };
cout << "数组逆置前:";
for (int i = 0; i < 5; i++)
{
cout << arr[i];
}
cout << endl;
/*实现逆置
1.记录起始下标位置
2.记录结束下标位置
3.其实下标与结束下标元素互换
4.起始位置++,结束位置--
5.执行循环操作,直到起始位置>=结束位置*/
int start = 0;//起始下标
int end = sizeof(arr) / sizeof(arr[0])-1;// 结束下标
while (start < end)
{
//元素互换代码
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
//下标更新
start++;
end--;
}
cout << "数组逆置后:";
//打印逆置后的数组
for (int i = 0; i < 5; i++)
{
cout << arr[i];
}
cout << endl;
system("pause");
return 0;
}
冒泡排序法
作用:最常用的排序算法,对数组内元素进行排序
推导:
- 比较相邻的元素,如果第一个比第二个打,就交换他们
- 对每个相邻元素做同样的工作,执行完后,找到第一个最大值
- 重复以上步骤,每次比较次数减1,直到不需要比较
结论:
排序的总轮数 = 元素个数 - 1
每轮对比次数 = 元素个数 - 排序轮数 - 1
#include<iostream>
using namespace std;
int main() {
//利用冒泡排序实现升序序列
int arr[] = { 4,2,8,0,5,7,1,3,9,13,11,12,10 };
//数组中元素个数
int p = sizeof ( arr ) / sizeof ( arr[ 0 ] );
cout << "排序前:";
for ( int i = 0; i <p; i++ )
{
cout << arr[ i ] << " ";
}
cout << endl;
//开始冒泡排序
//总共轮数为:元素个数-1
for ( int i = 0; i < p - 1; i++ )
{
//内层循环对比:每轮对比次数 = 元素个数 - 排序轮数 - 1
for ( int j = 0; j < p - i - 1; 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 < p; i++ )
{
cout << arr[ i ] << " ";
}
cout << endl;
system("pause");
return 0;
}
二维数组
二维数组定义方式
二维数组就是比一维数组多了一个维度,多了一列,本质就是一维数组
二维数组定义的四种方式:
数据类型 数组名[ 行数 ][ 列数 ];
数据类型 数组名[ 行数 ][ 列数 ] = { { 数据1,数据2 },{ 数据3,数据4 } };
数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4 };
数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4 };
建议:第二种最直观,更易懂
示例:
#include<iostream>
using namespace std;
int main()
{
//1.数据类型 数组名 [ 数组长度 ];
int arr[2][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j];
}
cout << endl;
}
cout << endl;
//2.数据类型 数组名[ 行数 ][ 列数 ] = { { 数据1,数据2 },{ 数据3,数据4 } };
int arr[2][3] = { {1,2,3},{4,5,6} };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j];
}
cout << endl;
}
cout << endl;
//3.数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4 };
int arr[2][3] = { 1,2,3,4,5,6 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j];
}
cout << endl;
}
cout << endl;
//4.数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4 };
int arr[][3] = { 1,2,3,4,5,6 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j];
}
cout << endl;
}
cout << endl;
return 0;
}
二维数组数组名称
作用:
查看二位数组所占空间
获取二维数组首地址
示例:
#include<iostream>
using namespace std;
int main()
{
//1.查看占用内存空间大小
int arr[2][3] =
{
{1,2,3},
{4,5,6}
};
cout << "二位数组占用空间为:" << sizeof(arr) << endl;//结果为24字节
cout << "二位数组第一行占用空间为:" << sizeof(arr[0]) << endl;//结果为12字节
cout << "二位数组第一个元素占用空间为:" << sizeof(arr[0][0]) << endl;//结果为4字节
//根据占用空间算出行数和列数
cout << "二位数组行数:" << sizeof(arr) / sizeof(arr[0]) << endl;//结果为2行
cout << "二位数组列数:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;//结果为3列
//2.获取二维数组首地址
cout << "二位数组首地址为:" << arr << endl;//16进制数
cout << "二位数组首地址为:" << (int)arr << endl;//10进制数
cout << "二位数组第一行首地址为:" << (int)arr[0] << endl;
cout << "二位数组第二行首地址为:" << (int)arr[1] << endl;
cout << "二位数组第一个元素首地址为:" << (int)&arr[0][0] << endl;
cout << "二位数组第二个元素首地址为:" << (int)&arr[0][1] << endl;
cout << endl;
return 0;
}
二维数组应用案例
考试成绩统计:
案例描述,有三名同学(张三,李四,王五),在一次考试中的成绩分别为如下表,请分别输出三名同学的总成绩
语文 | 数学 | 英语 | |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
#include<iostream>
using namespace std;
#include<string>
int main() {
int score[][3] = { 100,100,100,90,50,100,60,70,80 };
string name[3] = { "张三","李四","王五" };
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += score[i][j];
//cout << score[i][j] << " ";//这个是输出每个人每科的分数
}
cout << name[i] << "的总分为:" << sum << endl;
}
system("pause");
return 0;
}
函数
作用:将一段经常使用的代码封装起来,减少重复代码
一个比较大的程序,一般分为若干个程序块,每个模块实现特定的功能
函数是C++程序的模块
函数的定义
函数的定义一般主要有五个步骤:
- 返回值类型:告诉函数最后返回的是什么类型的结果
- 函数名:给函数起名
- 参数列表:使用函数时,传入的数据
- 函数体语句:花括号内的代码,函数内需要执行的语句
- return表达式:和返回值类型挂钩,函数执行完后,返回相应的数据类型
语法:
返回值类型 函数名 (形参列表)
{
函数体语句;
return 表达式;
}
示例:与入口函数main很像
//函数的定义
//语法:
//返回值类型 函数名 (参数列表){ 函数体语句 return表达式 }
//加法函数,实现两个整型相加,并将相加的结果进行返回
int add(int num1, int num2)
{
int sum = num1+num2
return sum;
}
int main()
{
system("pause");
return 0;
}
函数的调用
功能:使用定义好的函数
语法:函数名(形参);
示例:
#include<iostream>
using namespace std;
//函数定义
int add(int num1, int num2)//定义中的num1,num2为形式参数,简称为形参
{
int sum = num1 + num2;
return 0;
}
int main() {
int a = 10;
int b = 10;
//调用add函数
int sum = add(a, b);//调用时的a,b为实际参数,简称实参
//函数调用的时候实参的值会传递给形参
cout << "sum = " << sum << endl;
a = 100;
b = 500;
sum = add(a, b);
cout << "sum = " << sum << endl;
system("pause");
return 0;
}
总结:函数定义里小括号成为形参,函数调用时传入的参数成为实参
//传递数组
#include<iostream>
using namespace std;
int Print(int a[], int n)
{
for(int i = 0; i < n; i++);
cout << a[i] << " ";
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
Print(a, 10);
return 0;
}
//一些使用案例
#include<graphics.h>
#include<conio.h>
using namespace std;
struct C
{
int x;
int y;
int r;
int v;
int i;
};
struct R
{
int x;
int y;
int v;
};
void c(C& c)
{
c.y += c.v;
if (c.y >= 480)
{
c.v = -c.v;
}
circle(c.x, c.y, c.r);
Sleep(10);
}
void control(R& r)
{
if (_kbhit())
{
char input = _getch();
if (input == ' ')
{
r.v = -r.v;
}
}
}
void r(R& r)
{
r.x += r.v;
rectangle(r.x, r.y, r.x + 100, r.y + 20);
}
int main()
{
initgraph(600, 600);
C c1 = { 300,100,10,5,1 };
R r1 = { 20,30,5 };
BeginBatchDraw();
while (1)
{
/*if (_kbhit())
{
char input
if ()
}*/
cleardevice();
//b();
control(r1);
c(c1);
r(r1);
c1.i++;
FlushBatchDraw();
}
EndBatchDraw();
system("pause");
return 0;
}
值传递
- 值传递,就是函数调用时实参将数值传入给形参
- 值传递时,如果形参发生改变,并不会影响实参
示例:
#include<iostream>
using namespace std;
//如果函数不需要返回值,声明的时候可以写void,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;
//return;返回值不需要的时候可以不用写return
}
int main() {
int a = 10;
int b = 10;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//当函数的形参发生改变,不会影响实参
swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//由于函数的值传递性质,void函数里的形参怎么改变都不会影响实参的结果
system("pause");
return 0;
}
总结:值传递时,形参修饰不了实参
函数常见样式
四种:
- 无参无返
- 有参无返
- 无参有返
- 有参有返
示例
#include<iostream>
using namespace std;
//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 " << endl;
return 1000;
}
//4.有参有返
int test04(int a)
{
cout << " this is test04 a = " << a << endl;
return a;
}
int main() {
//无参无返函数调用
test01();//结果:字符串:this is test01
//有参无返函数调用
test02(100);//结果:实参赋予形参的值:100
//无参有返函数调用
int num1 = test03();
cout << " num1 = " << num1 << endl;//结果:返回值:1000
//有参有返函数调用
int num2 = test04(10000);
cout << " num2 = " << num2 << endl;//结果:10000
system("pause");
return 0;
}
函数的声明
作用:告诉编译器函数名称及如何调用函数,函数的实际主体可以单独定义
//定义:定义的函数不能写在main函数后面,因为自上而下运行的原理 int max(int a,int b) { return a > b ? a : b; }
int main() {
int a = 10; int b = 20;
cout << max(a,b) << endl;
system("pause");
return 0;
}
//声明 //提前告诉函数存在,就是声明的作用;可以吧定义写在后面 //只需要:返回值类型 函数名 (参数列表) int max(int a,int b)
int main() {
int a = 10; int b = 20;
cout << max(a,b) << endl;
system("pause");
return 0;
}
int max(int a,int b) { return a > b ? a : b; }
<a name="bBqJ6"></a>
## 函数的分文件编写
**作用:**让代码结构更加清晰<br />函数分文件编写一般又4个步骤
- 创建后缀为.h的头文件
- 创建后缀为.cpp的源文件
- 在头文件中写函数声明
- 在源文件中写函数定义
**示例:**<br />在头文件文件夹创建:swap.h
```cpp
//头文件
#include<iostream>
using namespace std;
//函数的声明
void swap(int a, int b);
在源件文件夹创建:swap.cpp
#include"swap.h"
//函数的定义
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "a=" << a << endl;
cout << "b=" << a << endl;
}
其他cpp文件通过自己创建的头文件,来引用自己创建的函数
#include<iostream>
#include"swap.h"//引用自己创建的头文件,调用函数
using namespace std;
int main(){
int a =10;
int a =20;
swap(a,b);
system("pause");
return 0;
}
指针
指针的作用:可以通过指针间接访问内存
- 内存编号是从0开始记录的,一般都用十六进制表示
- 可以利用指针变量保存地址
- 指针无论什么类型都是4个字节,因为保存的是地址
指针变量的定义和使用
指针变量定义语法:数据类型* 指针变量名;
```cppinclude
using namespace std;
int main() {
//1.定义指针
//先初始化一个变量
int a = 10;
//指针定义语法:数据类型*指针变量名
int* p;//一般用p(pointer)代表指针,其他也行,但最好用p,好理解
//让指针记录变量a的地址
p = &a;//&就是取址符
cout << "a的地址为:" << &a << endl;//打印的是一个16进制
cout << "a的地址为:" << p << endl;//和上面结果一样,都是一个地址
//2.使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加个*代表解引用,找到指针指向的内存中的数据
*p = 1000;
cout << "a =" << a << endl;
cout << "*p =" << *p << endl;
system("pause");
return 0;
}
<a name="GESId"></a>
## 指针所占内存空间
指针也是种数据类型<br />不管什么类型的指针,32位系统下占用内存空间为4字节,64位占用8字节<br />因为指针不管指向什么数据都是读取一窜地址,一串地址的空间大小就是4字节<br />**示例:**
```cpp
#include<iostream>
using namespace std;
int main() {
int a = 10;
int* p = &a;
//不管什么类型的指针,32位系统下占用内存空间为4字节,64位占用8字节
cout << "sizeof int * = " << sizeof(int*) << endl;
cout << "sizeof int * = " << sizeof(float*) << endl;
cout << "sizeof int * = " << sizeof(double*) << endl;
cout << "sizeof int * = " << sizeof(char*) << endl;
system("pause");
return 0;
}
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
示例
#include<iostream>
using namespace std;
int main() {
//空指针
//1.空指针用于给指针变量进行初始化
int* p = NULL
//2.空指针不可以进行访问
//0~255之间的内存编号是系统占用的,因此不可以访问
cout << *p << endl;//无法输出
system("pause");
return 0;
}
野指针:指针变量指向非法的内存空间
#include<iostream>
using namespace std;
int main() {
//野指针
//程序中要避免野指针
int * p = (int*)0x1100;
cout << *p << endl;//无法输出
system("pause");
return 0;
}
总结:空指针和野指针都不是我们申请的空间,因此不要访问
const修饰指针
const修饰指针有三种情况
- const修饰指针 — 常量指针
- const修饰常量 — 指针常量
- const即修饰指针,又修饰常量
记忆方法:
const修饰谁,谁就不能改,忽略类型来记忆
const p(常量指针)
const p(指针常量)
const const p(即修饰指针,又修饰常量)
*示例:
#include<iostream>
using namespace std;
int main() {
int a = 10
int b = 10
//1.常量指针
const int * p1 = &a;
//指针指向的值不可以改,指针的指向可以改
*p1 = 20;//错误
p1 = &b;//正确
//2.指针常量
int * const p2 = &a;
//指针指向的值可以改,指针的指向不可以改
*p2 = 100;//正确
p2 = &b;//错误
//3.const即修饰指针,又修饰常量
//指针指向的值和指针的指向都不可以改
const int * const p3 = &a;
*p3 = 100;//错误
p3 = &b;//错误
system("pause");
return 0;
}
指针和数组
作用:利用指针访问数组中的元素
示例:
#include<iostream>
using namespace std;
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素:" << arr[0] << endl;
int* p = arr;//指向数组的指针,因为arr就是数组首地址,所以数组不需要取址符&
cout << "指针访问数组第一个元素:" << *p << endl;//这行和上面的输出是一样的
p++;//就是地址往后移动四个字节,就是读取了第二个数据
cout << "指针访问数组第二个元素:" << *p << endl;
//输出整个数组含有的数据
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << *p2;
p2++;
}
cout << endl;
system("pause");
return 0;
}
指针和函数
作用:利用指针做函数参数,可以修改实参的值
示例:
#include<iostream>
using namespace std;
//两个数字进行交换
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 temp = *p1;
*p1 = *p2;
*p2 = temp;
cout << "swap02 *p1 = " << *p1 << endl;
cout << "swap02 *p2 = " << *p2 << endl;
}
int main()
{
int a = 10;
int b = 20;
//1.值传递
swap01(a, b);
//实参没有改变,main函数里的a和b的值都没变
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << endl;
//2.地址传递
//地址传递可以修饰实参
swap02(&a, &b);
//a和b的值互换了,因为swap02这个函数用的是指针,地址传递能修饰实参
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
指针,数组,函数
案例描述:封装一个函数是,利用冒泡排序,实现对整型数组的升序排序
如数组:int arr[10] = {4,3,6,9,1,2,10,8,7,5};
#include <iostream>
using namespace std;
//冒泡排序函数
//参数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()
{
//1.创建数组
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
//数组长度
int len = sizeof(arr) / sizeof(arr[0]);
//2.创建函数,实现冒泡排序
BubbleSort(arr, len);
//3.打印排序后的数组
PrintArray(arr, len);
system("pause");
return 0;
}
结构体
结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
结构体的定义和使用
语法:struct 结构体名称 { 结构体成员列表 };
这是定义
通过结构体创建变量的方式有三种:这是创建变量
- struct 结构体名 变量名
- struct 结构体名 变量名 = { 成员1值,成员2值……}
- 定义结构体时顺便创建变量:struct 结构体名称 { 结构体成员列表 } 变量名;
```cpp
include
include
using namespace std;
//1.创建学生数据类型:学生包括(姓名,年龄,分数);这步是定义 //创建定义的关键字不可以省略 //自定义数据类型,一些类型集合成一个类型 struct student { //成员列表 //姓名 string name;
//年龄
int age;
//分数
int score;
}s3;//顺便创建结构体变量
//2.通过学生类型创建具体学生;这步是创建变量 int main() { //2.1 struct student s1 //struct关键字c++可以省略,如果要c语言也可以使用最好不要省略 struct student s1;
//给s1属性赋值,通过.访问结构体变量中的属性
s1.name = " 张三 ";
s1.age = 18;
s1.score = 100;
cout << " 姓名:" << s1.name << " 年龄:" << s1.age << " 成绩:" << s1.score << endl;
//2.2 struct student s2 = {……}
struct student s2 = { " 李四 ",19,80 };
cout << " 姓名:" << s2.name << " 年龄:" << s2.age << " 成绩:" << s2.score << endl;
//2.3 在定义结构体时顺便创建结构体变量
s3.name = " 王五 ";
s3.age = 20;
s3.score = 60;
cout << " 姓名:" << s3.name << " 年龄:" << s3.age << " 成绩:" << s3.score << endl;
system("pause");
return 0;
}
**总结:**
1. 定义结构体的关键字是struct,不可省略
1. 创建结构体变量时,C++中关键字struct可以省略,C不能省略
1. 结构体变量利用操作符“.”访问成员
<a name="Iw9ls"></a>
## 结构体数组
**作用:**将自定义的结构体放到数组中方便维护<br />**语法:**`struct 结构体名 数组名 [ 元素个数 ] = { {},{}……{} };`<br />**示例:**
```cpp
#include <iostream>
#include <string>
using namespace std;
//结构体数组
//1.定义结构体
struct student
{
string name; //姓名
int age; //年龄
int score; //成绩
};
int main()
{
//2.创建结构体数组
struct student stuArray[3] =
{
{ "张三",12,100 },
{ "李四",28,99 },
{ "张飞",38,66 },
};
//3.给结构体数组中的元素赋值
stuArray[3].name = "赵六";
stuArray[3].age = 80;
stuArray[3].score = 60;
//4.遍历结构体数组
for(int i = 0; i<3; i++)
{
cout << "姓名:" << stuArray[i].name
<< "年龄:" << stuArray[i].age
<< "成绩:" << stuArray[i].score << endl;
}
system("pause");
return 0;
}
结构体指针
作用:将通过指针访问结构体中的成员
用操作符->
可以通过结构体指针访问结构体属性
示例:
#include <iostream>
#include <string>
using namespace std;
//1.定义结构体
struct student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//2.创建结构体变量
struct student s = { " 张三 ", 18, 100 };
//3.通过指针指向结构体变量
struct student* p = &s;
//4.通过指针访问结构体变量中的数据
//通过结构体指针,访问结构体中的属性,需要用"->"
cout << " 姓名:" << p->name
<< " 年龄:" << p->age
<< " 成绩:" << p->score << endl;
system("pause");
return 0;
}
总结:结构体指针可以通过“->”操作来访问结构体中的成员
结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:将每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
示例:
#include <iostream>
#include <string>
using namespace std;
//定义学生结构体
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
};
//定义老师结构体
struct teacher
{
int id; //教师编号
string name; //教师姓名
int age; //年龄
struct student stu; //辅导的学生,嵌套再老师结构体里
};
int main()
{
//结构体嵌套结构体
//创建老师变量
struct teacher t;
t.id = 10000;
t.name = " 老王 ";
t.age = 50;
//创建学生变量
t.stu.name = " 小王 ";
t.stu.age = 20;
t.stu.score = 60;
cout << " 老师编号:" << t.id
<< " 老师姓名:" << t.name
<< " 老师年龄:" << t.age << endl;
cout << " 老师辅导学生姓名:" << t.stu.name
<< " 学生年龄:" << t.stu.age
<< " 学生成绩:" << t.stu.score << endl;
system("pause");
return 0;
}
结构体做函数参数
作用:结将结构体作为参数向函数中传递
传递方法有两种:
- 值传递:不想修改主函数的数据就用值传递
- 地址传递:想同时修改用地址传递
示例:
#include <iostream>
#include <string>
using namespace std;
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
};
//打印学生信息的函数
//1.值传递
void printStudent1(struct student s)
{
s.age = 100;//子函数中的值被修改,main函数中的值不变,因为形参无法修饰实参的原因,无法把值传给实参
cout << "子函数中 姓名:" << s.name
<< " 年龄:" << s.age
<< " 成绩:" << s.score << endl;
}
//2.地址传递
void printStudent2(struct student* p)
{
p->age = 200;//地址传递原理,会改变实参,所以main函数输出也会受影响
cout << "子函数2中 姓名:" << p->name
<< " 年龄:" << p->age
<< " 成绩:" << p->score << endl;
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印打印学生所有信息
//创建结构体变量
struct student s;
s.name = " 张三 ";
s.age = 20;
s.score = 85;
//值传递输出函数
printStudent1(s);
//地址传递输出函数
printStudent2(&s);//地址传递记得给参数加上取址符
//根据上面变量打印输出
cout << " main函数中打印 姓名:" << s.name
<< " 年龄:" << s.age//年龄会被地址传递的值改变
<< " 成绩:" << s.score << endl;
system("pause");
return 0;
}
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递
结构体中const使用场景
作用:用const来防止误操作
示例:
#include <iostream>
#include <string>
using namespace std;
//const的使用场景
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
};
//将函数中的形参改用指针,可以减少内存的消耗。因为指针只占用四个字节,而且不会复制新的副本
void printStudenet1(const struct student* s)
{
//s->age = 150;//用const之后,这个参数失效
cout << " 姓名:" << s->name
<< " 年龄:" << s->age
<< " 成绩:" << s->score << endl;
}
int main()
{
//创建结构体变量
struct student s = { " 张三 ",15,70 };
//通过函数打印结构体变量信息
printStudenet1(&s);
system("pause");
return 0;
}
总结:在结构体中可以定义另一个结构体作为成员,用来解决实际问题
结构体案例
案例1
学校做毕设项目,每名老师带领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 sarray[5]; //学生数组,这里相当于每个老师带五个学生
};
//给老师和学生赋值的函数
void allocatespace(struct teacher tarray[], int len)
{
string nameseed = "ABCDE";//字符数组
//给老师开始赋值
for (int i = 0; i < len; i++)
{
tarray[i].tname = "teather_";
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));
//创建3名老师的数组
struct teacher tarray[3];
//通过函数给三个老师的信息赋值,并且给老师带的学生信息赋值
int len = sizeof(tarray) / sizeof(tarray[0]);
allocatespace(tarray, len);
//打印所有老师及学生信息
printinfo(tarray, len);
system("pause");
return 0;
}
案例2
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序法,将数组中的英雄按照年龄进行升序排列,最终打印排序后的结果
#include <iostream>
#include <string>
using namespace std;
//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 - i - 1; 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]);
//3.对数组进行排序,按照年龄进行升序排序
bubbleSort(heroArray, len);
cout << "排序后的打印为:" << endl;
//4.将排序结果打印输出
printHero(heroArray, len);
system("pause");
return 0;
}