C++基础第二弹
-
- 2.C++运算
- 3.C++循环
- 4.C++判断
-
- 4.1C++if语句
- 4.2C++if...else语句
- [4.3C++if...else if...else语句](#4.3C++if...else if...else语句)
- 4.4C++嵌套if语句
- 4.5C++switch语句
- 4.6C++嵌套switch语句
- 4.7C++?:运算符
- 5.C++函数
- 6.C++数字
2.C++运算
2.1运算符
- 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 杂项运算符
2.1.1算术运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
-- | 自减运算符,整数值减少 1 | A-- 将得到 9 |
2.1.2关系运算符
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
2.1.3逻辑运算符
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都 true,则条件为 true。 | (A && B) 为 false。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个 true,则条件为 true。 | (A || B) 为 true。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态,如果条件为 true 则逻辑非运算符将使其为 false。 | !(A && B) 为 true。 |
2.1.4位运算符
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
运算符 | 描述 | 实例 (A为60(0011 1100), B为13(0000 1101)) |
---|---|---|
& | 按位与操作,按二进制位进行"与"运算。 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; |
(A & B) 将得到 12,即为 0000 1100 |
| | 按位或运算符,按二进制位进行"或"运算。 运算规则:`0 | 0=0; 0 |
^ | 异或运算符,按二进制位进行"异或"运算。 运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0; |
(A ^ B) 将得到 49,即为 0011 0001 |
~ | 取反运算符,按二进制位进行"取反"运算。 运算规则:~1=-2; ~0=-1; |
(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
<< | 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 | A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 | A >> 2 将得到 15,即为 0000 1111 |
2.1.5赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
2.1.6杂项运算符
运算符 | 描述 |
---|---|
sizeof | sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。 |
Condition ? X : Y | 条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。(三目运算符) |
, | 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。 |
.(点)和 ->(箭头) | 成员运算符用于引用类、结构和共用体的成员。 |
Cast | 强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。 |
& | 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。 |
* | 指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。 |
2.1.7运算符优先级
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 AND | & | 从左到右 |
位异或 XOR | ^ | 从左到右 |
位或 OR | | | 从左到右 |
逻辑与 AND | && | 从左到右 |
逻辑或 OR | || | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
逗号 | , | 从左到右 |
2.1.8注意
-
任何数异或^0得到的值不变(a ^0 = a)
-
任何书异或同一个数两次得到的值不变(a ^b ^b = a)
-
对取模运算符 % 的优化(比如%8 == &7,%9 == &8,%22 == &21)
c++int a,b,c; a=53; b=a%8; //给a取模8 c=a&7; //让a和7进行位运算"与" std::cout<<"b="<<b<<std::endl; //b=5 std::cout<<"c="<<c<<std::endl; //c=5
-
先算右一后左一,①
乘除加减移位比。②
与异或或位逻辑,③
三目赋值逗号稀。④
①先算右面的一元运算符,后算左面的。
②乘除代表*/%,加减就是+和-,移位就是<<和>>,比就是比较运算符,注意比较运算符先算<、>、<=和>=这4个含不等号的,后算==和!=这两个。
③先算按位逻辑运算符,再算普通的逻辑运算符;按位逻辑运算符的顺序是&^|,逻辑运算符先算&&再算||,只是少了逻辑异或。
④先算三目运算符,再算赋值运算符,逗号运算符的优先级最低,所以说它"稀"。
3.C++循环
-
允许多次执行一个语句或语句组
循环类型 描述 while 循环 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。 for 循环 多次执行一个语句序列,简化管理循环变量的代码。 do...while 循环 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。 嵌套循环 可以在 while、for 或 do...while 循环内使用一个或多个循环。
3.1C++while循环
3.1.1语法
c++
while(条件表达式){
循环体代码块;
}
如果条件为true 如果条件为false 开始 条件表达式判断 循环内的代码块 结束
- while循环的关键点是循环可能一次都不会执行
- 当条件被测试且结果为假时,会跳过循环主体,直接执行while循环后的下一条语句
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
int main(void){
//局部变量声明
int a = 10;
//while循环执行
while(a < 20){
cout << "a的值为: " << a << endl;
a++;
}
cout << "循环结束,a的值为:" << a << endl;
return 0;
}
3.2C++for循环
c++
for(初始化语句; 条件语句; 自增或自减语句){
循环体代码块;
}
- 初始化语句 会首先被执行,且只会执行一次。可以声明并初始化任何循环控制变量,也可以不在这里写任何语句,只要有一个分号出现即可。
- 接下来,会判断 条件语句。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。
- 在执行完 for 循环主体后,控制流会跳回上面的 自增或自减 语句。该语句允许更新循环控制变量,该语句可以留空,只要在条件后有一个分号出现即可。
- 条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后自增或自减,再然后重新判断条件)。在条件变为假时,for 循环终止。
如果条件为true 如果条件为false 开始 初始化语句 条件表达式判断 循环内的代码块 自增或自减语句 结束
c++
//局部变量声明
int a = 10;
//while循环执行
while(a < 20){
cout << "a的值为: " << a << endl;
a++;
}
cout << "循环结束,a的值为:" << a << endl;
3.2.1基于范围的for循环方式1
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
int main(void){
int my_array[5] = {1,2,3,4,5};
//每个数组元素乘以2
for(int &x : my_array){
x *= 2;
cout << x << endl;
}
cout << "--------------------------" << endl;
//auto自动获取变量的类型
for(auto &x : my_array){
cout << x << endl;
x *= 2;
}
return 0;
}
3.2.2基于范围的for循环方式2
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
#include <array>
using namespace std;
int main(void){
int my_array[5] = {1,2,3,4,5};
cout << "--------------------------" << endl;
for(int x: my_array){
x *= 2;
cout << x << endl;
}
return 0;
}
3.2.3基于范围的for循环方式3
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
int main(void){
cout << "--------------------------" << endl;
string str("some string");
//range for语句
for(auto &c : str){
cout << c << endl;
c = toupper(c);
}
cout << str << endl;
return 0;
}
3.2.4基于范围的for循环方式4
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
int main(void){
cout << "--------------------------" << endl;
for(int x: {1,2,3,4,5}){
x *= 2;
cout << x << endl;
}
return 0;
}
3.3C++do...while循环
c++
do{
循环体代码块;
}while(条件语句);
- 条件表达式出现在循环的尾部,所以循环体中代码块会在条件语句判断前至少执行一次
- 若条件为真,会跳转回上面的do,然后重新执行循环中的循环体代码块,过程会不断重复,直到给定条件变假为止
如果条件为true 如果条件为false 开始 循环内的代码块 条件表达式判断 结束
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
#include <array>
using namespace std;
int main(void){
//局部变量声明
int a = 10;
//do循环执行
do{
cout << "a的值为: " << a << endl;
a=a+1;
}while(a < 20);
return 0;
}
3.4C++嵌套循环
3.4.1C++嵌套for循环
c++
for ( 初始化语句; 条件语句表达式; 自增或自减语句 )
{
for ( 初始化语句; 条件语句表达式; 自增或自减语句 )
{
循环体代码块;
}
循环体代码块; // 可以放置更多的语句
}
3.4.2C++嵌套while循环
c++
while(条件语句表达式)
{
while(条件语句表达式)
{
循环体代码块;
}
循环体代码块; // 可以放置更多的语句
}
3.4.3C++嵌套do...while循环
c++
do
{
循环体代码块; // 可以放置更多的语句
do
{
循环体代码块;
}while( 条件语句表达式 );
}while( 条件语句表达式 );
3.5循环控制语句
3.5.1break语句
- 当break语句出现在一个循环内时,循环会立即终止,且程序将继续执行循环后的下一条语句
- 可用于终止switch语句中的case
- 若是嵌套循环,则break会停止执行最内层的循环,然后开始执行该块之后的下一行代码
如果条件为true 如果条件为false 开始 条件语句 循环内代码块 结束 break
3.5.2continue语句
- 是跳过当前循环中的代码,强迫开始下一次循环
如果条件为true 如果条件为false 开始 条件语句 循环内代码块 结束 continue
3.5.3goto语句
-
goto语句允许把控制无条件转移到同一函数内的被标记的语句
c++goto label; ...... ... label: 代码块;
c++// // Created by 16690 on 2024/4/18. // #include <iostream> #include <array> using namespace std; int main(void) { //局部变量声明 int a = 10; //do循环执行 LOOP: do { if (a == 15) { //跳过迭代 a = a + 1; goto LOOP; } cout << "a = " << a << endl; a = a + 1; } while (a < 20); return 0; } //打印11-14,16-20
3.6无限循环
- 若条件永远不为假,则循环将变成无限循环
for( ; ; ){}
表示一个无限循环
4.C++判断
- 指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)
4.1C++if语句
c++
if(布尔表达式语句){
//若布尔表达式为真就执行的语句
}
- 如果布尔表达式为 true ,则 if 语句内的代码块将被执行。如果布尔表达式为 false,则 if 语句结束后的第一组代码(闭括号后)将被执行。
- 任何非零 和非空 的值假定为 true ,把零 或 null 假定为 false。
若布尔表达式为true 若布尔表达式为false 开始 布尔表达式语句 需要执行的代码 结束
c++
#include <iostream>
using namespace std;
int main ()
{
// 局部变量声明
int a = 10;
// 使用 if 语句检查布尔条件
if( a < 20 )
{
// 如果条件为真,则输出下面的语句
cout << "a 小于 20" << endl;
}
cout << "a 的值是 " << a << endl;
return 0;
}
4.2C++if...else语句
c++
if(布尔表达式语句){
//若布尔表达式为真就执行的语句
}
else{
//若布尔表达式为真就执行的语句
}
若布尔表达式为true 若布尔表达式为false 开始 布尔表达式语句 if内的代码块 结束 else内的代码块
c++
#include <iostream>
using namespace std;
int main ()
{
// 局部变量声明
int a = 100;
// 检查布尔条件
if( a < 20 )
{
// 如果条件为真,则输出下面的语句
cout << "a 小于 20" << endl;
}
else
{
// 如果条件为假,则输出下面的语句
cout << "a 大于 20" << endl;
}
cout << "a 的值是 " << a << endl;
return 0;
}
4.3C++if...else if...else语句
c++
if(布尔表达式语句1)
{
// 当布尔表达式 1 为真时执行
}
else if( 布尔表达式语句2)
{
// 当布尔表达式 2 为真时执行
}
else if( 布尔表达式语句3)
{
// 当布尔表达式 3 为真时执行
}
else
{
// 当上面条件都不为真时执行
}
- 一个if后可以跟0个或1个else,else必须在所有else if之后
- 一个if后可以跟0个或多个else if,else if必须在else之前
- 一旦某个else if匹配成功,其它的else if 或else 就不会被测试
c++
#include <iostream>
using namespace std;
int main ()
{
// 局部变量声明
int a = 100;
// 检查布尔条件
if( a == 10 )
{
// 如果 if 条件为真,则输出下面的语句
cout << "a 的值是 10" << endl;
}
else if( a == 20 )
{
// 如果 else if 条件为真,则输出下面的语句
cout << "a 的值是 20" << endl;
}
else if( a == 30 )
{
// 如果 else if 条件为真,则输出下面的语句
cout << "a 的值是 30" << endl;
}
else
{
// 如果上面条件都不为真,则输出下面的语句
cout << "没有匹配的值" << endl;
}
cout << "a 的准确值是 " << a << endl;
return 0;
}
4.4C++嵌套if语句
c++
if( 布尔表达式语句1)
{
// 当布尔表达式 1 为 true 时执行
if(布尔表达式语句2)
{
// 当布尔表达式 2 为 ture 时执行
}
}
- 可以在一个if 或else if语句内使用另一个if 或else if语句
c++
if (布尔表达式语句1) {
// 如果 布尔表达式语句1 为 true,则执行此处的代码块
if (布尔表达式语句2) {
// 如果 布尔表达式语句2 也为 true,则执行此处的代码块
}
else {
// 如果 布尔表达式语句2 为 false,则执行此处的代码块
}
}
else {
// 如果 布尔表达式语句1 为 false,则执行此处的代码块
}
4.5C++switch语句
c++
switch(表达式){
case 比较的值1 :
代码块1;
break; // 可选的
case 比较的值2 :
代码块2;
break; // 可选的
// 可以有任意数量的 case 语句
default : // 可选的
其它代码块;
}
- 允许测试一个变量等于多个值时的情况,每个值称为一个case,且被测试的变量会对每个switch case进行检查
- switch语句中的表达式必须是一个整型或枚举类型,或是一个class类型,class有一个单一的转换函数将其转换为整型或枚举类型
- 在 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号。
- case 的 比较的值 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量或字面量。
- 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止。
- 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
- 不是每一个 case 都需要包含 break 。如果 case 语句不包含 break ,控制流将会 继续 后续的 case,直到遇到 break 为止。
- 一个 switch 语句可以有一个可选的 default case,出现在 switch 的结尾。default case 可用于在上面所有 case 都不为真时执行一个任务。default case 中的 break 语句不是必需的。
case1 case2 case3 default 开始 表达式 代码块1-break 代码块2-break 代码块3-break 其它代码块-break 结束
c++
#include <iostream>
using namespace std;
int main ()
{
// 局部变量声明
char grade = 'D';
switch(grade)
{
case 'A' :
cout << "很棒!" << endl;
break;
case 'B' :
case 'C' :
cout << "做得好" << endl;
break;
case 'D' :
cout << "您通过了" << endl;
break;
case 'F' :
cout << "最好再试一下" << endl;
break;
default :
cout << "无效的成绩" << endl;
}
cout << "您的成绩是 " << grade << endl;
return 0;
}
4.6C++嵌套switch语句
- 可以在一个switch语句内使用另一个switch语句
c++
switch(ch1) {
case 'A':
cout << "这个 A 是外部 switch 的一部分";
switch(ch2) {
case 'A':
cout << "这个 A 是内部 switch 的一部分";
break;
case 'B': // 内部 B case 代码
}
break;
case 'B': // 外部 B case 代码
}
c++
#include <iostream>
using namespace std;
int main ()
{
// 局部变量声明
int a = 100;
int b = 200;
switch(a) {
case 100:
cout << "这是外部 switch 的一部分" << endl;
switch(b) {
case 200:
cout << "这是内部 switch 的一部分" << endl;
}
}
cout << "a 的准确值是 " << a << endl;
cout << "b 的准确值是 " << b << endl;
return 0;
}
4.7C++?:运算符
Exp1 ?Exp2 :Exp3;
,?表达式的值由Exp1决定,若Exp1为真,则计算Exp2的值,否则就计算Exp3的值
5.C++函数
- 函数是一组一起执行一个任务的语句,每个C++程序都至少有一个函数,即主函数
- 可以将代码划分到不同的函数中
- 函数声明告诉编译器函数的名称、返回类型、参数
- 函数定义提供了函数的实际主体
5.1定义函数
c++
返回类型 函数名(参数列表){
函数体代码块;
}
- 返回类型,一个函数可以返回一个值,若不需要返回,则返回类型设为void
- 函数名,函数的实际名称,与参数列表构成了函数签名
- 参数,参数是可选的,当函数被调用时,就向参数传递一个值,这个值被称为实际参数,参数列表包含函数参数的类型、顺序、个数
- 函数体代码块,包含一组该函数需要执行的代码块
5.2函数声明
- 函数声明包括
返回类型 函数名(参数列表)
返回类型 函数名(参数类型 参数1,参数类型 参数2)
返回类型 函数名(参数类型,参数类型)
,参数名不是必须的,参数类型是必须的
5.3调用函数
- 通过定义函数做什么,然后通过调用函数来完成已定义的任务
- 调用函数时,传递所需参数,若函数返回一个值,则可以存储返回值
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
//函数声明
int max(int num1,int num2);
//int max(int,int);
int main(void){
//局部变量声明
int a = 100;
int b = 200;
int ret;
//调用函数来获取最大值
ret = max(a,b);
cout << "最大值 : " << ret << endl;
return 0;
}
int max(int num1,int num2){
int result;
if(num1>num2){
result = num1;
}else{
result = num2;
}
return result;
}
5.4函数参数
- 函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
- 形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值赋值给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用赋值给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
传值调用(x,y)
- 将参数的实际值复制给函数的形式参数
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
void swap1(int, int);
void swap2(int, int);
void swap3(int, int);
int main(void) {
int num1, num2;
num1 = 10;
num2 = 20;
cout << "交换前的值" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
swap1(num1, num2);
swap2(num1, num2);
swap3(num1, num2);
cout << "交换后的值" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
return 0;
}
//中间变量处理
void swap1(int num1, int num2) {
int temp;
temp = num1;
num1 = num2;
num2 = temp;
return;
}
//算术处理
void swap2(int num1, int num2) {
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2;
}
//异或处理
void swap3(int num1, int num2) {
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
}
指针调用(*x,*y)
- 将参数的地址复制给形式参数,在函数内,地址用于访问调用中要用到的实际参数
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
void swap(int *a, int *b);
int main(void) {
int a = 10;
int b = 20;
cout << "交换前的值" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
swap(a, b);
cout << "交换后的值" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
引用调用(&x,&y)
- 将引用的地址复制给形式参数,在函数内,引用用于访问调用中要用到的实际参数
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
void swap1(int &x, int &y);
void swap2(int &x, int &y);
void swap3(int &x, int &y);
int main(void) {
int x = 10;
int y = 20;
cout << "swap1交换前的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
swap1(x, y);
cout << "swap1交换后的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "swap2交换前的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
swap2(x, y);
cout << "swap2交换后的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "swap3交换前的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
swap3(x, y);
cout << "swap3交换后的值" << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
return 0;
}
void swap1(int &x, int &y) {
int temp;
temp = x;
x = y;
y = temp;
}
void swap2(int &x, int &y) {
int temp;
temp = x ^ y;
x = temp ^ x;
y = temp ^ y;
}
void swap3(int &x, int &y) {
x^=y^=x^=y;
}
5.5参数的默认值
-
当定义函数时,可以为参数列表中的每一个参数都指定默认值,当调用函数时,若实际的参数值为空,则使用这个默认值
-
调用函数时,若未传递参数的值,则会使用默认值,若指定了值,则会忽略默认值,使用传递的值
c++// // Created by 16690 on 2024/4/18. // #include <iostream> using namespace std; int sum(int x, int y = 20) { int result; result = x + y; return (result); } int main(void) { int a =100; int b =200; int result; //不能声明函数,需要将函数放在main函数前 result = sum(a,b); cout << "result = " << result << endl; result = sum(a); cout << "result = " << result << endl; return 0; }
5.6Lambda函数与表达式
- Lambda 表达式把函数看作对象,Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值
- 语法:
- 有返回值:
[capture](parameters)->return-type{...}
- 无返回值:
[capture](parameters){...}
- 有返回值:
[capture]
:捕获子句,用于指定如何在lambda内部访问外部变量。可以是值捕获、引用捕获或默认捕获([]
、&
、=
)。(parameters)
:参数列表,可以是空的,如果lambda不需要参数。-> return-type
:返回类型。如果所有返回语句都返回相同的类型,或者没有返回语句,可以指定返回类型。在C++14及以后的版本中,可以省略返回类型,让编译器自动推断。{...}
:函数体,包含lambda表达式的代码。
- []:默认不捕获任何变量;
- [=]:默认以值捕获所有变量;
- [&]:默认以引用捕获所有变量;
- [x]:仅以值捕获x,其它变量不捕获;
- [&x]:仅以引用捕获x,其它变量不捕获;
- [=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
- [&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
- [this]:通过引用捕获当前对象(其实是复制指针);
- [*this]:通过传值方式捕获当前对象;
- 有/无参数、有/无捕获、值捕获、引用捕获、默认捕获、有/无返回值
c++
//
// Created by 16690 on 2024/4/18.
//
#include <iostream>
using namespace std;
int main(void) {
//无参数,无捕获
auto lambda1 = []() {
cout << "无参数,无捕获" << endl;
};
//有参数,无捕获
auto lambda2 = [](int x, int y) {
cout << "x+y=" << x + y << endl;
cout << "有参数,无捕获" << endl;
};
//有参数,无捕获
auto lambda3 = [](int x, int y = 20) {
cout << "x+y=" << x + y << endl;
cout << "有参数,无捕获" << endl;
};
//值捕获
int result1 = 10;
auto lambda4 = [result1](int x) {
cout << "值捕获" << endl;
return result1 * x;
};
//值捕获
int result2;
auto lambda5 = [result2 = 20](int x) {
cout << "值捕获" << endl;
return result2 * x;
};
//引用捕获,有返回值
int result3 = 10;
auto lambda6 = [&]() {
result3 = 99;
};
//默认捕获
class MyClass {
public:
int value;
MyClass(int val) : value(val) {}
void getLambda() {
auto lambda = [this]() {
this->value *= 2;
};
//调用lambda表达式
lambda();
}
};
//泛型lambda (c++14引入)
// auto lambda = [](auto x, auto y) {
// return x + y;
// };
lambda1();
lambda2(1, 2);
lambda3(1);
cout << lambda4(2) << endl;
cout << lambda5(2) << endl;
cout << result3 << endl;
lambda6();
cout << result3 << endl;
MyClass myClass(10);
myClass.getLambda();
cout << myClass.value << endl;
return 0;
}
-
无参数,无捕获:
c++auto noParamNoCapture = []() { return 42; };
-
有参数,无捕获:
c++auto withParamsNoCapture = [](int x, int y) { return x + y; };
-
无参数,值捕获:
c++int a = 10; auto noParamValueCapture = [a]() { return a * 2; };
-
无参数,引用捕获:
c++int b = 20; auto noParamRefCapture = [&b]() { b *= 2; return b; };
-
默认捕获(所有外部变量以值捕获):
c++int c = 30; auto defaultCaptureByValue = [=]() { int localC = c; // 值捕获变量c return localC; };
-
默认捕获(所有外部变量以引用捕获):
c++auto defaultCaptureByRef = [&]() { int localC = c; // 引用捕获变量c c = 50; // 修改外部变量c return localC; };
-
有参数,值捕获:
c++int x = 5; auto withParamsValueCapture = [x](int y) { return x + y; };
-
有参数,引用捕获:
c++int y = 3; auto withParamsRefCapture = [&](int z) { y += z; return y; };
-
捕获列表中有显式值捕获和引用捕获:
c++int a = 1, b = 2; auto mixedCapture = [a, &b]() { return a + b; };
-
有返回值的lambda:
c++auto lambdaWithReturn = [](int x) -> int { return x * x; };
-
无返回值的lambda(在C++14及以后,可以省略返回类型):
c++auto lambdaWithoutReturn = [](int x) { // 执行操作,但不返回任何值 };
-
泛型lambda(C++14引入):
c++auto genericLambda = [](auto x, auto y) { return x + y; };
-
使用
this
指针的lambda(在类的成员函数中):c++class MyClass { public: void someMethod() { auto lambda = [this]() { this->someOtherMethod(); }; } void someOtherMethod() {} };
-
lambda作为函数参数:
c++void doSomething(auto lambda) { lambda(); }
-
lambda作为函数返回值:
c++auto makeLambda() -> auto { return [](int x) { return x * 2; }; }
-
带有异常处理的lambda:
c++auto lambdaWithException = [](int x) -> int { if (x < 0) throw std::runtime_error("Negative value"); return x * x; };
6.C++数字
6.1C++定义数字
c++
//
// Created by 16690 on 2024/4/19.
//
#include <iostream>
using namespace std;
int main(void) {
// 数字定义
short s;
int i;
long l;
float f;
double d;
// 数字赋值
s = 10;
i = 1000;
l = 1000000;
f = 230.47;
d = 30949.374;
// 数字输出
cout << "short s :" << s << endl;
cout << "int i :" << i << endl;
cout << "long l :" << l << endl;
cout << "float f :" << f << endl;
cout << "double d :" << d << endl;
return 0;
}
6.2C++内置数学函数
序号 | 函数 & 描述 |
---|---|
1 | double cos(double); 该函数返回弧度角(double 型)的余弦。 |
2 | double sin(double); 该函数返回弧度角(double 型)的正弦。 |
3 | double tan(double); 该函数返回弧度角(double 型)的正切。 |
4 | double log(double); 该函数返回参数的自然对数。 |
5 | double pow(double, double); 假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。 |
6 | double hypot(double, double); 该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。 |
7 | double sqrt(double); 该函数返回参数的平方根。 |
8 | int abs(int); 该函数返回整数的绝对值。 |
9 | double fabs(double); 该函数返回任意一个浮点数的绝对值。 |
10 | double floor(double); 该函数返回一个小于或等于传入参数的最大整数。 |
6.3C++随机数
-
先调用srand()函数设置随机种子,然后调用rand()函数返回一个伪随机数
-
生成指定区间内的随机数
rand()%(m-1+n)%m
c++
//
// Created by 16690 on 2024/4/19.
//
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main(void) {
int x;
//设置种子
//通过系统时间作为随机种子,防止随机生成的数字相同
srand((unsigned)time (NULL));
//生成10个随机数
for(int i=0;i<10;i++){
//生成实际的随机数
x=rand();
cout << "随机数=" << x << endl;
//输出1-100的随机数:rand()%(m-1+n)+m;
int num = rand()%(1-1+100)+1;
cout << "模除+加法的随机数=" << num << endl;
}
return 0;
}