判断语句

if语句

if语句的判断时一个布尔表达式,C语言把任何非零和非空的值假定为true,把零或null假定为false,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
int main()
{
int a = 10;
int b = 20;
if( a < 20 )
{
std::cout << "a 小于 20" << std::endl;
}
std::cout << "a 的值是 " << a << std::endl;
if( b < 20 )
{
std::cout << "b 小于 20" << std::endl;
}
std::cout << "b 的值是 " << b << std::endl;
return 0;
}

执行结果:

if else语句

一个if语句后可跟一个可选的else语句,else语句在布尔表达式为假时执行,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
int main()
{
int a = 100;
if( a < 20 )
{
std::cout << "a 小于 20" << std::endl;
} else {
std::cout << "a 大于 20" << std::endl;
}
std::cout << "a 的值是 " << a << std::endl;
return 0;
}

执行结果:

类似于循环嵌套,条件判断也可以叠加,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
int main()
{
int a = 100;
if(a == 10)
{
std::cout << "a 的值是 10" << std::endl;
} else if(a == 20) {
std::cout << "a 的值是 20" << std::endl;
} else if(a == 30) {
std::cout << "a 的值是 30" << std::endl;
} else {
std::cout << "没有匹配的值" << std::endl;
}
std::cout << "a 的准确值是 " << a << std::endl;
return 0;
}

执行结果:

switch语句

(没错,是NS的那个switch)

switch语句可以测试一个变量等于多个值时的情况,每个值称为一个case,且被测试的变量会对每个switch case进行检查,语法:

1
2
3
4
5
6
7
8
9
10
11
12
switch(expression)
{
case constant-expression:
statement(s);
break; // 可选的
case constant-expression:
statement(s);
break; // 可选的
// 可以有任意数量的case语句
default : // 可选的
statement(s);
}

switch语句必须遵循下面的规则:

  • switch语句中的expression必须是一个整型或枚举类型,或者是一个class类型,其中class有一个单一的转换函数将其转换为整型或枚举类型
  • 在一个switch中可以有任意数量的case语句,每个case后跟一个要比较的值和一个冒号
  • case的constant-expression必须与switch中的变量具有相同的数据类型,且必须是一个常量或字面量
  • 当被测试的变量等于case中的常量时,case后跟的语句将被执行,直到遇到break语句为止
  • 当遇到break语句时,switch终止,控制流将跳转到switch语句后的下一行
  • 不是每一个case都需要包含break,如果case语句不包含break,控制流将会 继续 后续的case,直到遇到break为止。
  • 一个switch语句可以有一个可选的default case,出现在switch的结尾。default case可用于在上面所有case都不为真时执行一个任务,default case中的break语句不是必需的

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
int main() {
char grade = 'D';
switch(grade) {
case 'A':
std::cout << "很棒!" << std::endl;
break;

case 'B':

case 'C':
std::cout << "做得好" << std::endl;
break;
case 'D':
std::cout << "您通过了" << std::endl;
break;
case 'F':
std::cout << "最好再试一下" << std::endl;
break;

default:
std::cout << "无效的成绩" << std::endl;
}
std::cout << "您的成绩是 " << grade << std::endl;
return 0;
}

执行结果:

和if语句一样,switch也可以嵌套,语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
switch(ch1) {
case 'A':
cout << "这个 A 是外部 switch 的一部分";
switch(ch2) {
case 'A':
cout << "这个 A 是内部 switch 的一部分";
break;
case 'B': // 内部 B case 代码
}
break;
case 'B': // 外部 B case 代码
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
int main() {
int a = 100;
int b = 200;
switch(a) {
case 100:
std::cout << "这是外部 switch 的一部分" << std::endl;
switch(b) {
case 200:
std::cout << "这是内部 switch 的一部分" << std::endl;
}
}
std::cout << "a 的准确值是 " << a << std::endl;
std::cout << "b 的准确值是 " << b << std::endl;
return 0;
}

执行结果:

函数

函数是一组一起执行一个任务的语句,每个C++程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

函数声明告诉编译器函数的名称、返回类型和参数,函数定义提供了函数的实际主体

一般函数的结构如下:

1
2
3
return_type function_name( parameter list ) {
body of the function
}
  • return_type 返回类型:一个函数可以返回一个值,return_type是函数返回的值的数据类型,有些函数执行所需的操作而不返回值,那么return_type就是关键字 void
  • function_name 函数名称:这是函数的实际名称,函数名和参数列表一起构成了函数签名
  • parameter list 参数列表:参数就像是占位符,当函数被调用时,向参数传递一个值,这个值被称为实际参数,参数列表包括函数参数的类型、顺序、数量,函数也可以不包含参数
  • 函数主体:函数主体包含一组定义函数执行任务的语句

函数可以先声明后定义,例如:

1
2
3
4
5
int test();
...
int test() {
...
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
// 函数声明
int myMax(int num1, int num2);
// 主函数
int main() {
int a = 100;
int b = 200;
int ret;

// 调用函数,将a和b的值传入myMax()函数,并将该函数的返回值赋给ret变量
ret = myMax(a, b);

std::cout << "Max value is : " << ret << std::endl;
return 0;
}
// myMax()函数实现返回两个数中较大的那个数
int myMax(int num1, int num2) {
int result;
if(num1 > num2) {
result = num1;
} else {
result = num2;
}
// 返回较大值
return result;
}

执行结果:

如果函数要使用参数,则必须声明接受参数值的变量,这些变量就是函数的形式参数,形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

当调用函数时,有三种向函数传递参数的方式

传值调用

向函数传递参数的传值调用方法,把参数的实际值复制给函数的形式参数,在这种情况下,修改函数内的形式参数不会影响实际参数

默认情况下,C++使用传值调用方法来传递参数,一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
// 函数声明
void mySwap(int x, int y); // 无返回值函数用void

int main() {
int a = 100;
int b = 200;
std::cout << "交换前,a 的值:" << a << std::endl;
std::cout << "交换前,b 的值:" << b << std::endl;

// 调用函数来交换值
mySwap(a, b);

std::cout << "交换后,a 的值:" << a << std::endl;
std::cout << "交换后,b 的值:" << b << std::endl;
return 0;
}

// 函数定义
void mySwap(int x, int y) {
int temp;
temp = x; // 保存 x 的值 */
x = y; // 把 y 赋值给 x
y = temp; //把 x 赋值给 y
return;
}

执行结果:

为什么没有成功交换呢?是因为虽然 mySwap() 函数交换了a和b的值,但是并没有返回,也就是主函数并没有获得 mySwap() 函数交换后的值,这个函数只是进行了交换,并没有返回结果

指针调用

实际参数地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数,这意味着,修改形式参数会影响实际参数

把上面的那个示例稍稍修改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
void swap(int *x, int *y);
int main() {
int a = 100;
int b = 200;
std::cout << "交换前,a 的值:" << a << std::endl;
std::cout << "交换前,b 的值:" << b << std::endl;
// 调用函数来交换值
// &a 表示指向 a 的指针,即变量 a 的地址
// &b 表示指向 b 的指针,即变量 b 的地址
swap(&a, &b);
std::cout << "交换后,a 的值:" << a << std::endl;
std::cout << "交换后,b 的值:" << b << std::endl;
return 0;
}

void swap(int *x, int *y) {
int temp;
temp = *x; // 保存地址 x 的值
*x = *y; // 把 y 赋值给 x
*y = temp; // 把 x 赋值给 y
return;
}

执行结果:

可以看到,这里即使 swap() 函数没有返回交换后的值,但是a和b的值也成功交换了,这是因为交换的并不是a和b的值,而是他们的内存地址,这样在函数外也能成功访问到

引用调用

把参数的引用赋值给形式参数,在函数内,该引用用于访问调用中要用到的实际参数,这意味着,修改形式参数会影响实际参数

和指针调用类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
void swap(int &x, int &y);
int main() {
int a = 100;
int b = 200;
std::cout << "交换前,a 的值:" << a << std::endl;
std::cout << "交换前,b 的值:" << b << std::endl;
// 调用函数来交换值
swap(a, b);
std::cout << "交换后,a 的值:" << a << std::endl;
std::cout << "交换后,b 的值:" << b << std::endl;
return 0;
}
// 函数定义
void swap(int &x, int &y) {
int temp;
temp = x; // 保存地址 x 的值
x = y; // 把 y 赋值给 x
y = temp; // 把 x 赋值给 y
return;
}

执行结果:

参数的默认值

当定义一个函数,可以为参数列表中后边的每一个参数指定默认值,当调用函数时,如果实际参数的值留空,则使用这个默认值,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
int sum(int a, int b = 20) {
int result; // 函数内局部变量
result = a + b;
return (result);
}

int main() {
int a = 100;
int b = 200;
int result; // 函数内局部变量
// 调用函数来添加值
result = sum(a, b);
std::cout << "Total value is :" << result << std::endl;
// 再次调用函数,result重新被赋值
result = sum(a);
std::cout << "Total value is :" << result << std::endl;
return 0;
}

执行结果:

Lambda函数与表达式

C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式)

Lambda表达式把函数看作对象,让函数可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值,Lambda表达式本质上与函数声明非常类似,例如:

1
2
3
4
5
6
7
8
9
10
// 标准格式
[capture](parameters)->return-type{body}
// 示例
[](int x, int y){ return x < y ; }
// 无返回值标准格式
[capture](parameters){body}
// 示例
[]{ ++global_x; }
// 复杂示例
[](int x, int y) -> int { int z = x + y; return z + x; }

如果Lambda函数没有传回值(例如 void),其返回类型可被完全忽略,在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别,可以通过前面的 [ ] 来指定:

1
2
3
4
5
6
[]      // 沒有定义任何变量。使用未定义变量会引发错误
[x, &y] // x以传值方式传入(默认),y以引用方式传入
[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用
[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用
[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用

另外有一点需要注意,对于 [=][&] 的形式,lambda表达式可以直接使用this指针,但是对于 [ ] 的形式,如果要使用this指针,必须显式传入:

1
[this]() { this->someFunc(); }();

数字与数学运算

C++中的几个基本数字类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
int main() {
short s;
int i;
long l;
float f;
double d;

s = 10;
i = 1000;
l = 1000000;
f = 230.47;
d = 30949.374;

std::cout << "short s :" << s << std::endl;
std::cout << "int i :" << i << std::endl;
std::cout << "long l :" << l << std::endl;
std::cout << "float f :" << f << std::endl;
std::cout << "double d :" << d << std::endl;

return 0;
}

输出结果:

C++中可以通过引用数学头文件 <cmath> 来引用下面一些内置的数学函数:

1
2
3
4
5
6
7
8
9
10
double cos(double);		// 该函数返回弧度角(double型)的余弦
double sin(double); // 该函数返回弧度角(double型)的正弦
double tan(double); // 该函数返回弧度角(double型)的正切
double log(double); // 该函数返回参数的自然对数
double pow(double, double); // 假设第一个参数为x,第二个参数为y,则该函数返回x的y次方
double hypot(double, double); // 该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度
double sqrt(double); // 该函数返回参数的平方根
int abs(int); // 该函数返回整数的绝对值
double fabs(double); // 该函数返回任意一个浮点数的绝对值
double floor(double); // 该函数返回一个小于或等于传入参数的最大整数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cmath>

int main() {
// 数字定义
short s = 10;
int i = -1000;
long l = 100000;
float f = 230.47;
double d = 200.374;
// 数学运算
std::cout << "sin(d) :" << sin(d) << std::endl;
std::cout << "abs(i) :" << abs(i) << std::endl;
std::cout << "floor(d) :" << floor(d) << std::endl;
std::cout << "sqrt(f) :" << sqrt(f) << std::endl;
std::cout << "pow( d, 2) :" << pow(d, 2) << std::endl;

return 0;
}

执行结果:

在许多情况下,需要生成随机数,可以使用 rand() 函数,它只返回一个伪随机数,且生成随机数之前必须先调用 srand() 函数

示例:使用了 time() 函数来获取系统时间的秒数,通过调用 rand() 函数来生成随机数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <ctime>
#include <cstdlib>

int main() {
int i,j;
// 设置种子
srand((unsigned)time(NULL));
// 生成 10 个随机数
for(i = 0; i < 10; i++) {
// 生成实际的随机数
j= rand();
std::cout <<"随机数: " << j << std::endl;
}
return 0;
}

输出结果:

可以自己试试哦,每次执行生成的数字都是不一样的