title: Cpp学习笔记之三
top_img: false
tags:
  - C++
categories:
  - 编程语言
cover: false
abbrlink: e7033a53
date: 2024-01-25 22:20:47
copyright:
comments:

判断语句

if语句

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

#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语句在布尔表达式为假时执行,示例:

#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;
}

执行结果:

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

#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进行检查,语法:

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语句不是必需的

示例:

#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也可以嵌套,语法如下:

switch(ch1) {
    case 'A': 
        cout << "这个 A 是外部 switch 的一部分";
        switch(ch2) {
            case 'A':
                cout << "这个 A 是内部 switch 的一部分";
                break;
            case 'B': // 内部 B case 代码
        }
        break;
    case 'B': // 外部 B case 代码
}

示例:

#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() ,所有简单的程序都可以定义其他额外的函数。

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

一般函数的结构如下:

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

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

int test();
...
int test() {
    ...
}

示例:

#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++使用传值调用方法来传递参数,一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数,示例:

#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() 函数交换后的值,这个函数只是进行了交换,并没有返回结果

指针调用

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

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

#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的值,而是他们的内存地址,这样在函数外也能成功访问到

引用调用

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

和指针调用类似:

#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;
}

执行结果:

参数的默认值

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

#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表达式本质上与函数声明非常类似,例如:

// 标准格式
[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++变量传递有传值和传引用的区别,可以通过前面的 [ ] 来指定:

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

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

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

数字与数学运算

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

#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> 来引用下面一些内置的数学函数:

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);	// 该函数返回一个小于或等于传入参数的最大整数

示例:

#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() 函数来生成随机数:

#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;
}

输出结果:

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