2022考研机试复习——C/C++学习笔记(一)

2022考研机试复习——C/C++学习笔记(一)

起步

// C++向下兼容C,在练习过程中,请将代码保存为.cpp文件
/*
 * 头文件
 * 1. ".h"为头文件的文件格式
 * 2. C++等价写法:#include <cstdio>
 */
#include <stdio.h>
/*
 * 主函数
 * 1. 程序入口
 * 2. 程序从主函数开始执行
 * 3. 一个程序最多只能有一个主函数
 */
int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d",a+b);
    return 0;
}

一、基本数据类型

变量类型

整型

常用整型(int)和长整型(long long)。

说明:

  1. 绝对值在109范围以内的整数都能定义成int型。
  2. 如果给long long型赋一个大于231-1的初值,请在数字后加LL。如:long long bigNum = 1234567890123345LL。
  3. 题目要求109以内或32位整数时,用int存放;若是1018以内(如1010)或者说64位整数,使用long long存放。
浮点型

浮点型就是小数,氛围单精度(float)和双精度(double)。

说明:

  1. float有效精度6~7位,少用。
  2. 碰到浮点型的数据使用double来存储。
字符型

说明:

  1. C语言中,字符常量统一使用ASCII码统一编码(范围0~127)。
  2. 小写字母比大写字母的ASCII码值大32(a->97,A->65,空格->32)。
  3. 字符常量(必须是单个字符)必须使用单引号标注(‘z’,‘h’,‘r’)。
  4. 可以将整数的ASCII码值赋给字符变量,因为在计算机内部,字符就是按ASCII码存储的。
  5. 转义字符"\0"代表空字符NULL(注意不是空格),其ASCII码为0。
字符串常量
#include <cstdio>
int main(){
/*
* 字符数组
* 1. 字符串常量为""标记的字符集。
* 2. 不能把字符串常量赋值给字符变量(不允许char c = "zhanghaoran";)
* 3. 字符串常量可以作为初值赋值给字符数组,使用%s的格式输出。
*/
char str[50] = "2022,kaoyanbisheng!";
printf("%s",str);
return 0;
布尔型
#include <cstdio>
int main(){
    bool flag1 = 10;
    bool flag2 = -10;
    bool flag3 = 0;
    printf("%d\n%d\n%d",flag1,flag2,flag3);
    /**
       /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        1
        1
        0
        Process finished with exit code 0
     */
    return 0;
}

说明:

  1. 布尔型(bool)在cpp文件中直接使用,在C语言中要添加stdbool.h头文件才能使用。
  2. 给布尔型变量赋值的时候可以使用true、false或者整型常量。整型常量在赋值给bool变量时,会自动转换成true(非0)和false(0)。
  3. bool中,true使用1存储,false使用0存储,%d打印时会输出数字。

常量定义

常用的定义常量的方式有两种:

#define PI 3.1415 // 宏定义
const double PI = 3.1415; // const关键字

二、顺序结构

scanf与printf

#include <cstdio>
int main(){
    /*
      n = n + 2 <=> n += 2 后者称为符合赋值运算符,可以加快编译速度和提高可读性,应常用这种方式。
    */
    int n = 0;
    n += 2;
    printf("%d",n);
    int age;
    /* 关于scanf()
     * 1. scanf("格式控制",变量地址)
     * 2. "&"——取地址运算符
     * 3. 特别的数据类型变量的scanf格式符:
     *  - long long: %lld
     *  - double: %lf
     * 4. scanf中,char数组整个输入的情况下不加&,因为数组名称本身就代表了数组第一个元素的地址
     * 5. 字符数组读入时以空格和换行符为读入结束的标志,因此当输入"zhang haoran"想赋值给name时,name只会保存"zhang"
     * 6. scanf的%c格式可以读入空格和换行。
     */
    scanf("%d",&age);
    char name[20];
    scanf("%s",name);
    /*
     * 关于printf():
     * 1. 对于double类型的变量,在printf中的输出格式为%f,而在scanf中是%lf
     * 2. 输出%和\时,需要转义,即"%%"和"\\"
     */
    printf("姓名:%s\n年龄:%d",name,age);
    /*
     * /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        20
        zhanghaoran
        姓名:zhanghaoran
        年龄:20
        Process finished with exit code 0
     */
    // 补充三种常用的输出格式
    {
        int num = 720;
        // 1. %md 使不足m位的int型变量以m位进行右对齐输出,高位空格补齐
        printf("%5d",num);
        // 2.  区别于%md,%0md高位0补齐
        printf("%05d",num);
        double d = 1.1234567;
        // 3. 让浮点数保留m位小数输出
        printf("%.2f",d);
    }
    return 0;
}

getchar与putchar

#include <cstdio>
int main(){
    char c1,c2,c3;
    // 1. getchar()能识别空格和换行符
    // 2. getchar()用来输入单个字符,putchar用来输出单个字符
    c1 = getchar();
    c2 = getchar();
    c3 = getchar();
    putchar(c1);
    putchar(c2);
    putchar(c3);
    return 0;
    /*
     * /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        z hr
        z h
        Process finished with exit code 0
     */
}

typedef

typedef关键字用于给复杂的一个数据类型取别名。

// 给long long数据类型取一个别名Long
typedef long long Long;
Long l = 123456789LL;

常用的math函数

在使用数学函数前,要使用#include<math.h>引入头文件。

  • fabs(double x)
    对double型变量取绝对值。
  • floor(double x) 和 ceil(double x)
    对double型的变量进行向下取整和向上取整。
  • pow(double r,double p)
    返回rp
  • sqrt(double x)
    返回double型变量的算数平方根。
  • log(double x)
    返回double型变量以自然对数为底的对数
  • sin(double x)、cos(double x)、tan(double x)
    返回对应的三角函数值,参数要求是弧度制。
  • round(double x)
    将double型变量x四舍五入后取整然后返回double类型。

三、选择结构

下面这种写法在许多数据结构算法的书上经常出现。

#include "cstdio"
int main(){
    int a = 100;
    int b = 0;
    if(a){
        printf("a is not zero!");
    } else {
        printf("a is zero!");
    }
    if(!b){
        printf("a is zero!");
    } else {
        printf("a is not zero!");
    }
}

技巧

  1. 在if条件中,如果表达式是"!=0",可以省略。
  2. 在if条件中,如果表达式是"==0",可以省略,然后在表达式前加取反运算符"!"。

四、循环结构

对于以下这种写法:

for(int i = 0; i < 10 ; i ++){
    // ···
}

说明:
在C语言中是不允许在for语句的表达式A中定义变量的,但是在C++中可以,因此以上这种写法需要把文件保存为.cpp后缀才能通过编译。

五、数组

一维数组初始化

基本方法
#include <cstdio>

int main(){
    /*
     * 一维数组初始化
     * 1. 数组对部分元素进行赋值操作,未被赋值的元素默认为0。
     * 2. 当数组没有被赋初值,每个元素可能是0,也有可能是一个随机数。
     * 3. 如果想给数组的每一个元素赋初值0,只需要把第一个元素赋为0,或者只用一个{}表示:
     *    a. int nums[10] = {0};
     *    b. int nums[10] = {};
     */
    int nums[10] = {11,22,33,44,55};
    for(int i = 0; i < 10 ; i ++){
        printf("nums[%d]=%d\n",i,nums[i]);
    }
    return 0;
    /*
        /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        nums[0]=11
        nums[1]=22
        nums[2]=33
        nums[3]=44
        nums[4]=55
        nums[5]=0
        nums[6]=0
        nums[7]=0
        nums[8]=0
        nums[9]=0

        Process finished with exit code 0
     */
}
使用memset对数组中每一个元素赋相同的值
#include "cstdio"
#include "cstring"
#define n 5
int main(){
/*
 * 使用memset给数组赋初值
 * 1. 添加string.h头文件
 * 2. memset按字节赋值
 * 3. 一般使用memset赋初值0或-1
 */
int arr[n];
memset(arr,-1,sizeof(arr));
for(int i = 0; i< n; i ++){
printf("%2d ",arr[i]);
}
memset(arr,0,sizeof(arr));
printf("\n");
for(int i = 0; i< n; i ++){
printf("%2d ",arr[i]);
}
return 0;
/*
 *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
    -1 -1 -1 -1 -1 
     0  0  0  0  0 
    Process finished with exit code 0
 */
}

数组顺推

#include <cstdio>
// 数组递推包括:
// 1. 顺推 
// 2. 逆推
int main(){
    int nums[10];
    scanf("%d",nums);
    for(int i = 1; i < 10 ;i ++){
        nums[i] = nums[i - 1] * 2;
    }
    for(int i = 0; i < 10 ;i ++){
        printf("nums[%d]=%d\n",i,nums[i]);
    }
    return 0;
    /*
        /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        1
        nums[0]=1
        nums[1]=2
        nums[2]=4
        nums[3]=8
        nums[4]=16
        nums[5]=32
        nums[6]=64
        nums[7]=128
        nums[8]=256
        nums[9]=512
        
        Process finished with exit code 0
     */
}

冒泡排序

#include <cstdio>
/*
 * 冒泡排序:
 * 1. 进行若干趟排序,每趟排序将数组元素的最大值移动到最右边
 * 2. 当剩余元素为0时,排序结束
 */
const int n = 10;
int main(){
    int nums[n] = {1,4,3,2,7,6,5,9,8};
    for(int i = 0 ;i < n - 1; i ++){
        for(int j = 0; j < n - i - 1; j ++){
            if(nums[j] > nums[j + 1]){
                int tmp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = tmp;
            }
        }
    }
    for(int i = 0; i< n ; i ++){
        printf("%d ",nums[i]);

    }
    return 0;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        0 1 2 3 4 5 6 7 8 9 
        Process finished with exit code 0
     */
}

二维数组

#include <cstdio>
#define n 3
int main(){
    /*
     * 二维数组初始化
     */
    int arr[n][n] = {{1,2},{2}};
    for(int i = 0; i< n ;i ++){
        for(int j = 0; j< n ;j ++){
            printf("%02d ",arr[i][j]);
        }
        printf("\n");
    }
    /*
     * 两个三阶矩阵对应位置元素相加,并将结果存放到另外一个三阶矩阵
     */
    int a[n][n];
    int b[n][n];
    int c[n][n];
    for(int i = 0; i < n ; i ++){
       for(int j = 0; j< n ; j ++){
           scanf("%d",&a[i][j]);
           scanf("%d",&b[i][j]);
           c[i][j] = a[i][j] + b[i][j];
       }
    }
//    for(int i = 0; i < n ; i ++){
//        for(int j = 0; j< n ; j ++){
//            scanf("%d",&b[i][j]);
//        }
//    }
//    for(int i = 0; i < n ; i ++){
//        for(int j = 0; j< n ; j ++){
//            c[i][j] = a[i][j] + b[i][j];
//        }
//    }
    for(int i = 0 ;i < n ; i++){
        for(int j = 0; j < n ; j ++){
            printf("%d ",c[i][j]);
        }
        printf("\n");
    }
/*
 *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
    01 02 00 
    02 00 00 
    00 00 00 
    1 9 2 8 3 7 4 6 5 5 6 4 7 3 8 2 9 1
    10 10 10 
    10 10 10 
    10 10 10 
    
    Process finished with exit code 0

 */
}

字符数组

字符数组的初始化
#include <stdio.h>
int main(){
    // 字符数组初始化方式1——普通数组初始化方式
    char str1[] = {'z','h','r'};
    for(int i = 0 ; i < 3 ; i ++){
        printf("%c",str1[i]);
    }
    printf("\n");
    // 字符数组初始化方式2——赋值字符串(仅限初始化)
    char str2[] = "zhanghaoran";
    for(int i = 0 ; i< 11; i ++ ){
        printf("%c",str2[i]);
    }
    printf("\n");
    return 0;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        zhr
        zhanghaoran
        
        Process finished with exit code 0
     */
}
字符数组的输入输出
#include "cstdio"
int main(){
    /*
     * 字符数组输入输出方式1——printf()和scanf()
       1. scanf()的%c格式能够识别空格和换行符并将其输入
       2. %s通过空格和换行符来识别一个字符串的结束
       3. scanf()在使用%s时,对应数组名前不用加取地址运算符"&"
     */
//    char name[20] = {};
//    scanf("%s",name);
//    printf("%s",name);
    /*
        /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        zhanghaoran
        zhanghaoran
        Process finished with exit code 0
     */
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        zhang haoran
        zhang
        Process finished with exit code 0
     */

    /*
     * 字符数组输入输出方式2——getchar()和putchar()
     * 注意:getchar()能识别空格和换行符
     */
//    const int n = 4;
//    char twoDimensionArr[n][n];
//    for(int i = 0 ; i < n - 1 ;i ++){
//        for(int j = 0 ;j < n - 1 ; j ++){
//            twoDimensionArr[i][j] = getchar();
//        }
//        getchar(); // 把输入中每行末尾的换行符吸收掉
//    }
//    for(int i = 0 ; i < n - 1; i ++){
//        for(int j = 0 ; j < n - 1; j ++){
//            putchar(twoDimensionArr[i][j]);
//        }
//        putchar('\n');
//    }
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        ^_^
        _^_ ^_^
        ^_^
        _^_
        ^_^

        Process finished with exit code 0
     */
    /*
     * 字符数组输入输出方式3——gets()和puts()
     * 说明:
     * 1. gets()识别换行符\n作为输入结束,scanf()后如要用gets(),需要先用getchar()把换行符吸收掉。
     * 2. gets()输入的字符串可以包含空格
     * 3. puts()输出会自动换行。
     */
//    int a = 0;
//    char str[20];
//    scanf("%d",&a);
//    getchar();
//    gets(str);
//    puts(str);
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        1
        warning: this program uses gets(), which is unsafe.
        zhanghaoran
        zhanghaoran

        Process finished with exit code 0
     */
    // 使用gets()和puts()操作二维数组
    const int row = 3;
    char strs[row][20];
    for(int i = 0 ; i < row ; i ++ ){
        gets(strs[i]);
    }
    for(int i = 0 ; i < row ; i ++){
        puts(strs[i]);
    }
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        warning: this program uses gets(), which is unsafe.
        zhang
        hao
        ran
        zhang
        hao
        ran
        
        Process finished with exit code 0
     */
    return 0;
}

字符数组的存放方式

说明:

  1. 在一维数组(或二维数组的第二维)末尾都有一个空字符’\0’,表示存放字符串的结尾。
  2. '\0’在使用gets()或者scanf()输入字符串时会自动添加在输入的字符串后面,并占用一个字符位。
  3. puts()和printf()通过识别’\0’作为字符串的结尾来输出的。
  4. 结束符’\0’的ASCII值为0,即空字符NULL,占用一个字符位,因此,在创建一个字符数组时,字符数组的长度至少要比实际存储的字符串的长度多1。
  5. 只有char数组末尾会加’\0’,int等类型的数组末尾不加。
  6. '\0’和空格不是一个东西,它表示空字符NULL,空格的ASCII值为32。
string.h头文件

string.h头文件包含了许多用于字符数组的函数。

#include "cstdio"
// 引入string.h头文件
#include "cstring"

/*
 * strlen()——用于获取字符数组中第一个'\0'前的字符的个数。
 * 格式:strlen(字符数组)
 */
void strlen_test(){
    char str[20];
    // gets()可以输入包含空格的字符串
    gets(str);
    int len = strlen(str);
    printf("%d",len);
    printf("\n");
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        warning: this program uses gets(), which is unsafe.
        zhang hao ran
        13

        Process finished with exit code 0
     */
}
/*
 * strcmp()——以字典序为比较原则,返回两个字符串大小的比较结果。
 * 格式:strcmp(字符数组1,字符数组2)
 * 说明:
 * 1. 若字符数组1<字符数组2,则返回一个负整数(不一定是-1)。
 * 2. 若字符数组1=字符数组2,则返回0。
 * 3. 若字符数组1>字符数组2,则返回一个正整数(不一定是1)。
 */
void strcmp_test(){
    char str1[30];
    char str2[30];
    gets(str1);
    gets(str2);
    int res = strcmp(str1,str2);
    if(res < 0){
        printf("str1 < str2\n");
    }else if(res == 0){
        printf("str1 = str2\n");
    }else{
        printf("str1 > str2\n");
    }
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        warning: this program uses gets(), which is unsafe.
        nanchang
        beijing
        str1 > str2

        Process finished with exit code 0
     */
}
/*
 * strcpy()——把第二个字符串复制给第一个字符串,包括结束符"\0"
 * 格式:strcpy(字符数组1,字符数组2)
 */
void strcpy_test(){
    char str1[30];
    char str2[30];
    gets(str2);
    strcpy(str1,str2);
    puts(str1);
    /*
    /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
    warning: this program uses gets(), which is unsafe.
    zhanghaoran
    zhanghaoran

    Process finished with exit code 0
     */
}
/*
 * strcat()——把字符串2拼接到字符串1的后面
 * 格式:strcat(字符数组1,字符数组2)
 */
void strcat_test(){
    char str1[30];
    char str2[30];
    gets(str1);
    gets(str2);
    strcat(str1,str2);
    puts(str1);
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        warning: this program uses gets(), which is unsafe.
        zhanghaoran
         like coding!
        zhanghaoran like coding!
        
        Process finished with exit code 0
     */
}
int main(){
//    strlen_test();
//    strcmp_test();
//    strcpy_test();
    strcat_test();
    return 0;
}
sscanf()和sprintf()

sscanf()和sprintf()属于stdio.h头文件下的函数,用于处理字符串,可以理解为"string+scanf"和"string+printf"。

#include "cstdio"
#include "cstring"
int main(){
    char str[10] = "1234";
    int num;
    sscanf(str,"%d",&num);
    printf("%d\n",num);
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        1234
        Process finished with exit code 0
     */
    num = 12345;
    sprintf(str,"%d",num);
    for(int i = 0 ; i < strlen(str); i ++){
        printf("%c ", str[i]);
    }
    printf("\n");
//    printf("%s\n",str);
/*
    /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
    1234
    1 2 3 4 5 
    
    Process finished with exit code 0
 */
    return 0 ;
}

理解:

  • 我们常写的scanf()和printf()可以写成:
  scanf(screen,"%d",&n);
  printf(screen,"%d",n);

这里的screen就看成是电脑屏幕。scanf的输入其实就是把screen中的内容以%d的格式传到变量n中(从左到右);而printf的输出就是把变量n中的内容以"%d"的格式传到screen。

  • 类比到sscanf和sprintf,唯一的改变就是把screen换成了字符数组,使用格式如下:
  char str[20];
  sscanf(str,"%d",&n);
  sprintf(str,"%d",n);
  • sprintf()也可以做字符串的复制
#include "cstdio"
int main(){
   char str1[20];
   char str2[20] = "zhanghaoran";
   sprintf(str1,"%s",str2);
   puts(str1);
   return 0;
  /*
   /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
   zhanghaoran

   Process finished with exit code 0
   */
 }
  • sscanf支持正则表达式

六、函数

再谈main函数:

int main(){ 
    //···
    return 0;
}

说明:

  1. 主函数对于一个程序来说只能有一个,无论主函数写在哪个位置,整个程序一定是从主函数的第一个语句开始执行,然后在需要调用其他函数的时候才回去调用。
  2. main函数返回0的意义在于告知系统程序正常终止。

七、指针

指针的相关概念

变量的存放:

  1. 变量存放在内存中。
  2. 每个字节都会有一个地址。
  3. 计算机通过地址找到某个变量。
  4. 变量的地址指的是它占用的字节中的第一个字节的地址。

指针:

  1. 在计算机中,一个地址"指向"一个变量,可以通过地址来找到变量。
  2. 在C语言中,使用"指针"表示内存地址(或称指针指向了内存地址)。
  3. 如果一个指针指向的内存地址恰好是某个变量的地址,就称"这个指针指向了该变量"。
  4. “&“为取地址运算符,在变量前加上”&”,就表示变量的地址。
  5. 指针是一个unsigned类型的整数。

指针变量

指针变量用于存放指针(或者说地址)。

指针变量的定义与初始化
// 1. 数据类型后加"*"
int* p;
double* p;
char* p;
// 说明:"*"的位置在数据类型后或者变量名称之前都OK的,编译器不会对此进行区分。
//2. 同时定义多个指针变量
int *a,*b,*c;
//3. 以下方式只有p1会被定义为指针类型,p2不会
int* p1,p2;
//4. 给指针变量赋值的方式一般是把变量的地址使用取地址运算符"&"取出后赋值给对应类型的指针变量。
int a = 10;
int* pa = &a;

说明:

  • int* 才是指针变量的类型,而后面的p才是变量名,用来存储变量的地址值。
  • 地址值&a是赋值给p而不是*p的。
  • 请记住,对指针变量来说,星号"*"是类型的一部分。

获取地址所指的元素:

  • 在指针变量前加"*"。
  • 指针变量p表示的是地址,*p是这个地址中存放的内容。
  • 对指针变量来说,把其存储的地址的类型称为基类型

指针与数组

#include "cstdio"

int main(){
    // 1. C语言中,数组名称也作为数组的首地址使用。
//    int a[5] = {1};
//    int* pa = a;
//    printf("%d",*pa);
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        1
        Process finished with exit code 0
     */
    // 2. 使用指针对数组进行赋值和遍历输出
    const int n = 10;
    int a[n];
    for( int i = 0; i< n;i ++ ){
        scanf("%d",a+i);
    }
    // 遍历方式1
//    for(int i = 0 ; i < n ; i ++){
//        printf("%d ",*(a+i));
//    }
//    printf("\n");
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        0 1 2 3 4 5 6 7 8 9
        0 1 2 3 4 5 6 7 8 9

        Process finished with exit code 0
     */
    // 遍历方式2
    for(int* pa = a ; pa < a+n ; pa ++){
        printf("%d ",*pa);
    }
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        9 8 7 6 5 4 3 2 1 0
        9 8 7 6 5 4 3 2 1 0 
        Process finished with exit code 0

     */
    return 0;
}

在函数参数中使用指针

#include "cstdio"
void swap(int* a, int * b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
int main(){
    int a = 10;
    int b = 20;
    swap(&a,&b);
    printf("%d %d",a,b);
    return 0;
}

引用

#include "stdio.h"

void change1(int x){
    x = 10;
}
// 形参为引用
void change2(int &x){
    x = 10;
}

int main(){
    int x = 0 ;
    change1(x);
    printf("%d\n",x);
    change2(x);
    printf("%d\n",x);
    return 0 ;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        0
        10
        
        Process finished with exit code 0
     */
}

关于引用:

  1. 引用是C++中的语法,文件必须保存为.cpp类型。
  2. 引用不产生副本,只是给原变量取了一个别名,对引用变量的操作就是对原变量的操作。
  3. 使用方法:在函数的参数名前加"&"(或者参数类型之后,因为引用是别名的意思,所以一般加在变量名前面)
  4. 不管是否使用引用,函数的参数名(形参名)和实际传入的参数名(实参名)可以不同。
  5. 注意:把引用的"&“和取地址符”&"区分开,引用不是取地址的意思,它是C++中的一种语法。
  6. 强调:由于引用是产生变量的别名,因此常量不可使用引用。

下面是swap方法的另一种实现方式,这里使用到了指针的引用:

#include "cstdio"
void swap(int* &pa,int* &pb){
    int* tmp = pa;
    pa = pb;
    pb = tmp;
}
int main(){
    int a = 10, b = 20;
    int *pa = &a;
    int *pb = &b;
    printf("%d %d\n",*pa,*pb);
    swap(pa,pb);
    printf("%d %d\n",*pa,*pb);
    return 0;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        10 20
        20 10
        
        Process finished with exit code 0
     */
}

八、结构体

定义结构体的基本格式:

struct struct_name{
    // 一些基本的数据结构或者自定义的数据类型
};

结构体变量和结构体数组的2种定义方式:

// 方式1
struct studentInfo{
    int id;
    char gender;
    char name[20];
    char major[20];
}ZHANGHAORAN,stu[38];
// 方式2
struct studentInfo{
    int id;
    char gender;
    char name[20];
    char major[20];
};
studentInfo ZHANGHAORAN;
studentInfo stu[38];

结构体元素的访问:

说明:

结构体内部可以定义除了自己本身的任意数据类型(定义自己本身会引起循环定义问题),但是可以定义自身类型的指针变量。

struct studentInfo{
    int id;
    char gender;
    char name[20];
    studentInfo* next;
}stu,*p;
// 结构体普通变量访问结构体内部元素
stu.id
stu.name
stu.next
// 结构体指针变量访问结构体内部元素
// 说明:方式1和方式2等价
// 方式1
(*p).id
(*p).name
(*p).next
// 方式2
p->id
p->name
p->next

结构体的初始化:
这里介绍结构体的构造函数:

struct studentInfo{
    int id;
    char gender;
    char name[20];
    // 默认构造函数,在定义了新的构造函数后被覆盖,如需使用要单独定义。
    studentInfo(){}
    // 自定义构造函授
    // 方式1
    studentInfo(int _id,char* _name){
        id = _id;
        name = _name;
    }
    // 方式2 简化版
    studentInfo(int _id,char _gender, char* _name):id(_id),gender(_gender),name(_name){
        
    }
};

实例:

#include "cstdio"
struct Point{
    int x;
    int y;
    Point(){}
    Point(int _x,int _y):x(_x),y(_y){}
};
Point pt[10];
int main(){
    for(int i = 0 ;i < 10; i ++ ){
        pt[i] = Point(i+1,i+1);
    }
    for(int i = 0 ; i < 10 ; i ++){
        printf("(%d,%d) ",(*(pt+i)).x,(*(pt+i)).y);
    }
    return 0;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        (1,1) (2,2) (3,3) (4,4) (5,5) (6,6) (7,7) (8,8) (9,9) (10,10) 
        Process finished with exit code 0

     */
}

九、补充

cin与cout(不建议使用)

cin和cout是C++中的输入与输出函数,需要添加头文件#includeusing namespace std;后才能使用。

#include "iostream"
using namespace std;
int main(){
    char name[20];
    int age;
    char gender;
    char desc[200]={};
    /* cin函数:
     * 1. cin采用输入运算符">>"进行输入,输入不用指定格式,也不需要加取地址运算符"&"。
     * 2. cin可同时读入多个变量,只需往后面使用>>进行扩展即可。
     * 3. 当需要读入一整行时,可以使用cin.getline()函数
     */
    cin >> name >> age >> gender;
    getchar(); // 吸收换行符
    cin.getline(desc, 200);
    /*
     * cout函数:
     * 1. 使用方法和cin几乎一致,只不过使用的是输出运算符"<<"。
     * 2. 两种换行方式:
     *     a. "\n"
     *     b. endl(means 'end of line')
     */
    cout<<"name:"<<name<<"\n"<<"age:"<<age<<"\n"<<"gender:"<<gender<<"\n"<<"desc:"<<desc<<endl;
    return 0 ;
    /*
     *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
        zhanghaoran
        20
        M
        The monitor of class 1821801z
        name:zhanghaoran
        age:20
        gender:M
        desc:The monitor of class 1821801z

        Process finished with exit code 0
     */
}

说明:

在考试中,不推荐使用cin和cout进行输入输出,因为在数据量较大的情况下,有可能数据还没有输入完就超时了,因此只有在十分必要的情况下再去用cin和cout函数,推荐优先使用C语言的scanf()和printf()函数。

浮点数的比较

由于计算机中采用有限位的二进制编码,因此浮点数在计算机中的存储并不总是精确的,并且再经过大量计算后,误差会更加明显,这样就会对比较操作造成极大的干扰。

于是,为了提高浮点数比较结果的准确性,我们需要引进一个极小数eps来对误差进行修正。

这样,当一个数a落在[b-eps,b+eps]时,我们就应判断a==b是成立的。

实际上,eps可以任取,但经验表明,eps取108最合适。

const double eps = 1e-8;

我们把比较操作写成宏定义的形式:

#define equ(a,b) ((fabs((a)-(b)))<(eps))

于是,我们可以这样对两个浮点数进行比较(注意观察两种方式的结果):

#include <cmath>
#include <cstdio>
const double eps = 1e-8;
#define Equ(a,b) ((fabs((a)-(b)))<(eps))

int main(){
    double d1 = 4 * asin(sqrt(2.0) / 2);
    double d2 = 3 * asin(sqrt(3.0) / 2);
    // 方式1
    printf("%d\n",(d1==d2));
    // 方式2
    printf("%d\n",Equ(d1,d2));
    return 0;
/*
 *  /Users/zhr/CLionProjects/untitled/cmake-build-debug/untitled
    0
    1

    Process finished with exit code 0
 */
}

我们可以写出其他运算符的宏定义形式:

// 大于(<)
#define More(a,b) ((a)-(b)) > (eps)
// 小于(<)
#define Less(a,b) ((a)-(b)) < (-eps)
// 不大于(<=)
#define LessEqu(a,b) ((a)-(b)) < (eps)
// 不小于(>=)
#define MoreEqu(a,b) ((a)-(b)) > (-eps)

关于圆周率π

圆周率π不需要死记,由 “cos(π) = -1” 得 “arccos(-1) = π”,即const double Pi = acos(-1.0);

END

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值