• 算法笔记——C/C++语言基础篇(已完结)


    开始系统学习算法,希望自己能够坚持下去,期间会把常用到的算法写进此博客,便于以后复习,同时希望能够给初学者提供一定的帮助,手敲难免存在错误,欢迎评论指正,共同学习。博客也可能会引用别人写的代码,如有引用,定会注明。本博客内容主要按照算法笔记内容进行学习。(2018-12-03)

    1.万能头文件

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
      
      ...
      
      return 0;
    }

    2.判断素数

    int IsPrime(int n){
        for(int i=2;i<=sqrt(n+1);i++){
            if(n%i==0){
                return 0;
            }    
        }
        return 1;     
    }
    //返回0代表不是素数,返回1代表是素数    

     3.求一元二次方程的根

    题目链接(点击进入)

    数学内容:

    输出格式:

    补充:%0md(m代表宽度,右对齐),当变量不足m位时,将在前面补0,例如a=123,%05d,则输出结果为00123

    #include<stdio.h>
    #include<math.h>
    int main(){
        double a,b,c;
        double r1,r2;
        scanf("%lf%lf%lf",&a,&b,&c);
        r1 = (-1*b+sqrt(b*b-4*a*c))/(2*a);
        r2 = (-1*b-sqrt(b*b-4*a*c))/(2*a);
        printf("r1=%7.2lf
    r2=%7.2lf",r1,r2);
        return 0;
    } 

     4.特殊符号输出

    想要输出%或,则需要在前面再加一个%或

    #include<stdio.h>
    int main(){
        printf("%%
    ");
        printf("\");
        return 0;
    } 

     5.getchar与putchar的使用

    getchar用来接收输入的单个字符,putchar用来输出单个字符

    #include<stdio.h>
    int main(){
        char a,b,c;
        a = getchar();
        getchar();
        b = getchar();
        c = getchar();
        putchar(a);
        putchar(b);
        putchar(c);
        return 0;
    } 
    /*输入数据:abcd
      输出数据:abd
      原因:字符b虽然被接收,但是没有用变量进行保存,所以丢失
      ps:getchar可以接收Enter键的内容,以
    的形式保存 
      */ 

     6.常用math函数(使用需加头文件#include<math.h>)

    1)fabs(double x)

    该函数用于对double型变量取绝对值

    #include<stdio.h>
    #include<math.h> 
    int main(){
        double db =-12.56;
        printf("%.2f
    ",fabs(db));
        return 0;
    } 
    //输出结果:12.56 

    2)floor(double x)和ceil(double x)

    这两个函数分别用于double型变量的向下取整和向上取整,返回类型为double型

    #include<stdio.h>
    #include<math.h> 
    int main(){
        double db1 = -5.2, db2 = 5.2;
        printf("%.0f %.0f
    ",floor(db1),ceil(db1));
        printf("%.0f %.0f
    ",floor(db2),ceil(db2));    
        return 0;
    } 
    /*输出结果:
    -6 -5
    5 6*/

    3)pow(double r,double p)

    该函数用于返回rp,要求r和p都是double型

    #include<stdio.h>
    #include<math.h> 
    int main(){
        double db = pow(2.0,3.0);
        printf("%f
    ",db);    
        return 0;
        /*int型也可以使用 
        int a=2,b=3;
        int db2 = pow(a,b);
        print("%d
    ",db2)
        */
    } 
    /*输出结果:
    8.000000
    */

    4)sqrt(double x)

    该函数用于返回double型变量的算术平方根

    #include<stdio.h>
    #include<math.h> 
    int main(){
        double db = sqrt(2.0);
        printf("%f
    ",db);
        return 0;
    } 
    /*输出结果:
    1.414214
    */

    5)log(double x)

    该函数用于返回double型变量的以自然对数为底的对数

    ps:C语言中没有对任意底数求对数的函数,因此必须使用换底公式来将不是以自然对数为底的对数转换为以e为底的对数,即logab=loge/ logea

    #include<stdio.h>
    #include<math.h> 
    int main(){
        double db = log(1.0);
        printf("%f
    ",db);
        return 0;
    } 
    /*输出结果:
    0.000000
    */

     6)round(double x)

    该函式用于将double型变量x四舍五入,返回类型也是double型,需进行取整

    #include<stdio.h>
    #include<math.h>
    int main(){
        double db1 = round(3.40);
        double db2 = round(3.45);
        double db3 = round(3.50);
        double db4 = round(3.55);
        double db5 = round(3.60);
        printf("%d, %d, %d, %d, %d
    ",(int)db1,(int)db2,(int)db3,(int)db4,(int)db5);
        return 0;
    } 
    //输出结果:3,3,4,4,4 

    7.switch语句的用法

    格式:

    switch(表达式){
        case 常量表达式1:
            ...
            break;
        case 常量表达式2:
            ...
            break;
            
        ...
        
        case 常量表达式n:
            ...
            break;
        default:
            ... 
    }

    实例:

    #include<stdio.h>
    int main(){
        
        int a = 1, b = 2; 
        switch(a + b){
            case 1:
                printf("%d
    ",a);
                break;
            case 2:
                printf("%d
    ",b);
                break;
            case 3:
                printf("%d
    ",a + b);
                break;
            default:
                printf("None
    ");
        }
        return 0;
    } 
    //输出结果:3

    8.求圆周率π的近似值

    题目链接:圆周率近似值(点击此处)

    由于题目没有给出解法,也没有相关提示,所以我就参考了一下别人的解法,这里的核心就是求圆周率近似值的公式:

    针对本题的代码:

    #include<stdio.h>
    #include<math.h> 
    int main(){//解法:用π/4 ≈ 1 - 1/3 + 1/5 - 1/7 +... 公式
         int n=1;
         double ans;//结果 
         double tmp = 1.0;//分子 
         while(n<=pow(10,6)){//题中要求为某一项绝对值小于10的-6次方,即1/n里的n要大于10的六6次方 
             ans += tmp/n*1.0;
             n = n + 2;
             tmp = tmp*-1.0;
         }
         ans = ans * 4;
         printf("PI=%10.8f
    ",ans); 
    } 

    9.Fibonacci数列

    题目链接:http://www.codeup.cn/problem.php?cid=100000568&pid=7

    1)递归法求解

    #include<stdio.h>
    #include<math.h>
    int Fib(int n){
        if(n==1||n==2){
            return 1;
        }else{
            return Fib(n-1)+Fib(n-2);
        }
    } 
    int main(){
         int n;
         scanf("%d",&n);
         printf("%d",Fib(n));
         return 0;
    } 

    2)概念法求解

    #include<stdio.h>
    #include<math.h>
    int Fib(int n){
        int i;
        int f1 = 1;
        int f2 = 1;
        int f3 = 1;//避免判断n是否大于2 
        for(i = 2;i<n;i++)
        {
            f3 = f1 + f2;
            f1 = f2;
            f2 = f3;
        }
        return f3;
    } 
    int main(){
         int n;
         scanf("%d",&n);
         printf("%d",Fib(n));
         return 0;
    } 

    【转】参考博客地址:https://blog.csdn.net/weixin_40740059/article/details/80012909

    10.分数序列求和

    题目描述:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前 20 项之和。

    #include<stdio.h>
    int main(){
         double n1=2.0,m1=1.0;
         double n2=3.0,m2=2.0;
         double n3,m3;
         double ans=(n1/m1)+(n2/m2);
         for(int i=3;i<=20;i++){
             n3 = n1 + n2;
             m3 = m1 + m2;
             ans+=(n3/m3);
             n1 = n2;
             m1 = m2;
             n2 = n3;
             m2 = m3;
         }
         printf("%.6f
    ",ans);
         return 0;
    } 

     11.冒泡排序

    冒泡排序是排序中最基本的一种方法,虽然在写题时我们一般不会去使用它,但我觉得了解冒泡排序算法的实现原理确实非常必要的。

    冒泡排序的本质在于交换,即每次通过交换的方式把当前剩余元素的最大值移动到一端,当剩余元素为0时,排序结束。

    这里附上一个辅助学习数据结构的网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html(模拟常见数据结构的运行过程)

    #include<stdio.h>
    int main(){
        int a[10]={3,1,4,5,2};
        for(int i=1;i<=4;i++){//进行n-1趟比较 
            for(int j=0;j<5-i;j++){//将剩余的数进行交换,选出最大的那一个 
                if(a[j]>a[j+1]){//交换 
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
        for(int i=0;i<5;i++){
            printf("%d ",a[i]);
        }
        return 0;
    } 
    //输出结果:1 2 3 4 5

     题目链接:http://www.codeup.cn/problem.php?cid=100000569&pid=7

    12.二维数组的初始化

    #include<stdio.h>
    int main(){
        int a[5][6]={{3,1,2},{8,4},{},{1,2,3,4,5}};
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++){
                printf("%d ",a[i][j]);
            }
            printf("
    ");
        }
        return 0;
    } 
    /*输出结果:
    3 1 2 0 0 0
    8 4 0 0 0 0
    0 0 0 0 0 0
    1 2 3 4 5 0
    0 0 0 0 0 0
    */ 

    特别提醒:如果数组大小较大(大概是106),则需要将其定义在主函数外,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外部申请的全局变量

    来自静态存储区,允许申请的空间较大。

    13.memset函数的使用

    memset函数的功能是给数组中的每一个元素都赋予相同的值

    使用格式:memset(数组名,值,sizeof(数组名))

    注意:使用需加头文件 #include<string.h>,另外只建议使用memset赋0或-1

    #include<stdio.h>
    #include<string.h>
    int main(){
        int a[5]={1,2,3,4,5};
        memset(a,0,sizeof(a));
        for(int i=0;i<5;i++){
            printf("%d ",a[i]);
        }
        printf("
    ");
        memset(a,-1,sizeof(a));
        for(int i=0;i<5;i++){
            printf("%d ",a[i]);
        }
        printf("
    ");
        return 0;
    } 
    /*输出结果:
    0 0 0 0 0 0
    -1 -1 -1 -1 -1
    */ 

    14.字符数组初始化

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str[15] = {'G','O','O','D',' ','B','O','Y','!'};
        for(int i=0;i<9;i++){
            printf("%c",str[i]);
        }
        printf("
    ");
        return 0;
    } 
    /*输出结果:
    GOOD BOY!
    
    */ 

    除此之外,字符数组也可以通过赋值字符串来初始化(仅限于初始化,程序其它位置不允许这样直接赋值整个字符串

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str[15] = "GOOD BOY!";
        for(int i=0;i<9;i++){
            printf("%c",str[i]);
        }
        printf("
    ");
        return 0;
    } 
    /*输出结果:
    GOOD BOY!
    
    */ 

    15.字符数组的输入输出

    1)scanf输入,printf输出

    scanf对字符类型有%c和%s两种格式(printf同理),其中%c用来输入输出单个字符,%s用来输入一个字符串并存在数组里或输出一个字符串。

    %c能识别空格和换行,%s将空格和换行识别一个字符串的结束。

    #include<stdio.h>
    int main(){
        char str[10];
        scanf("%s",str);
        printf("%s
    ",str);
        return 0;
    } 
    
    /*
    输入:
    ATA QAQ 
    输出结果:
    ATA 
    */ 

    scanf输入%s不需要加&。

    2)getchar输入,putchar输出

    getchar和putchar分别用来输入输出单个字符

    #include<stdio.h>
    int main(){
        char str[5][5];
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                str[i][j]=getchar();
            }
            getchar();//用来吸收每行结束输入的换行符(enter键) 
        }
        for(int i = 0;i<3;i++){
            for(int j=0;j<3;j++){
                putchar(str[i][j]);
            }
            putchar('
    ');
        } 
        return 0;
    } 
    
    /*
    输入:
    ATA
    QAQ
    ATA
    输出结果:
    ATA
    QAQ
    ATA
    
    */ 

    3)gets输入,puts输出

    gets用来输入一行字符串(注意:gets识别换行符 作为输入结束,因此scanf完一个整数后,如果使用gets,需先用getchar接收输入整数后的换行符),并将其存放于一维数组中;

    puts用来输出一行字符串,并紧跟一个换行

    #include<stdio.h>
    int main(){
        char str1[20];
        char str2[5][10];
        gets(str1);
        for(int i=0;i<3;i++){
            gets(str2[i]);
        } 
        puts(str1);
        for(int i=0;i<3;i++){
            puts(str2[i]);
        }
        return 0;
    } 
    
    /*
    输入:
    abcdefghi
    QAQ
    ATA
    ATA
    输出结果:
    abcdefghi
    QAQ
    ATA
    ATA
    
    */ 

    特别提醒:gets和scanf的输入方式会默认在每个字符串的后面添加一个空字符'',然后puts和printf就是通过识别''作为字符串的结尾输出的。

    所以如果不是使用scanf的%s格式或者gets函数输入字符串,一定要在字符串的结尾加上'',否则使用printf和puts进行输出时会出错。

    #include<stdio.h>
    int main(){
        char str[20]={'a','b','','a','b','c'};
        printf("%s",str);
        return 0;
    } 
    
    /*
    输入:
    
    输出结果:
    ab
    
    */ 

    16.#include<string.h>头文件

    string头文件包含了许多用于字符数组的函数。使用以下函数需要在程序开头田间string.h头文件

    1)strlen()

    strlen函数可以得到字符数组中第一个前的字符的个数

    格式:strlen(字符数组)

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str1[20];
        char str2[20]={'a','b','c','','a','b','c'};
        gets(str1);
        int len = strlen(str1);
        printf("%d
    ",len);
        printf("%d
    ",strlen(str2));
        return 0;
    } 
    
    /*
    输入:
    abcabc
    输出结果:
    6
    3
    */ 

    2)strcmp()

    strcmp函数返回两个字符串大小的比较结果,比较原则是按字典序

    格式:strcmp(字符数组1,字符数组2)

    strcmp的返回结果:

    ①字符数组1<字符数组2,返回一个负整数

    ②字符数组1==字符数组2,返回0

    ③字符数组1>字符数组2,返回一个正整数

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str1[50],str2[50];
        gets(str1);
        gets(str2);
        int cmp = strcmp(str1,str2);
        if(cmp<0){
            printf("str1 < str2
    ");
        }else if(cmp==0){
            printf("str1 = str2
    ");
        }else{
            printf("str1 > str2
    ");
        }
        return 0;
    } 
    
    /*
    输入:
    abc
    def
    输出结果:
    str1 < str2
    */ 

    3)strcpy()

    strcpy函数可以把一个字符串复制给另外一个字符串

    strcpy(字符数组1,字符数组2)

    注意:是吧字符数组2复制给了字符数组1,这里的“复制”包括了结束符

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str1[50],str2[50];
        gets(str1);
        gets(str2);
        strcpy(str1,str2);
        puts(str1);
        return 0;
    } 
    
    /*
    输入:
    abc
    def
    输出结果:
    def
    */ 

    4)strcat()

    strcat()可以把一个字符串拼接到另一个字符串后面

    格式:strcat(字符数组1,字符数组2)

    注意:是把字符数组2的内容拼接到字符数组1的后面

    #include<stdio.h>
    #include<string.h>
    int main(){
        char str1[50],str2[50];
        gets(str1);
        gets(str2);
        strcat(str1,str2);
        puts(str1);
        return 0;
    } 
    
    /*
    输入:
    abc
    def
    输出结果:
    abcdef
    */ 

    17.有序插入

    #include<stdio.h>
    int main(){
        int a[10];
        for(int i=0;i<9;i++){
            scanf("%d",&a[i]);
        }
        int n;
        scanf("%d",&n);
        int k;
        for(int i=0;i<9;i++){
            if(n<a[i]){
                k=i;
                for(int j=9;j>=i;j--){
                    a[j]=a[j-1];
                }
                break;
            }
        }
        a[k]=n;
        for(int i=0;i<10;i++){
            printf("%d
    ",a[i]);
        }
        return 0;
    }

    18.数组元素逆置

    交换法

    #include<stdio.h>
    int main(){
        int a[10];
        for(int i=0;i<10;i++){
            scanf("%d",&a[i]);
        }
        for(int i=0;i<5;i++){
            int temp=a[9-i];
            a[9-i]=a[i];
            a[i]=temp;
        }
        for(int i = 0;i<10;i++){
            printf("%d
    ",a[i]);
        }
        return 0;
    }

    19.解密(字符的规则变换)

    思路:利用ascll码表

    #include<stdio.h>
    #include<string.h>
    int main(){
        char a[100];
        scanf("%s",a);
        int len = strlen(a);
        for(int i=0;i<len;i++){
            if(a[i]>='A'&&a[i]<='Z'){
                a[i]='Z'-a[i]+'A';
            }else if(a[i]>='a'&&a[i]<='z'){
                a[i]='z'-a[i]+'a';
            }
        }
        printf("%s
    ",a);
        return 0;
    }

    20.以数组作为函数参数

    数组作为参数时,参数中数组的第一维不需要填写长度(如果是二维数组,那么第二维需要填写长度),实际调用是也只需要填写数组名。

    特别提醒:数组作为参数时,在函数中对数组元素的修改就等同于是对原数组元素的修改(这与普通的局部变量不同)

    #include<stdio.h>
    #include<string.h>
    void change(int a[],int b[][5]){
        a[0] = 1;
        a[1] = 3;
        a[2] = 5;
        b[0][0] = 1;
    }
    int main(){
        int a[3] = {0};
        int b[5][5] = {0};
        change(a,b);
        for(int i=0;i<3;i++){
            printf("%d
    ",a[i]);
        }
        printf("%d
    ",b[0][0]);
        return 0;
    } 
    /*输出结果
    1
    3
    5
    1
    
    /* 

    虽然数组可以作为参数,但是却不允许作为返回类型的出现。如果想返回数组,只能用上面的方法,将想要返回的数组作为参数传入。

    21.字符串的逆序存放

    利用之前的置换思想,将这些字母首尾对应交换位置即可实现字符串的逆序存放

    #include<stdio.h>
    #include<string.h>
    void turnout(char a[]){
        int len=strlen(a);
        for(int i=0;i<len/2;i++){
            char temp = a[i];
            a[i] = a[len-1-i];
            a[len-1-i] = temp;
        } 
    }
    int main(){
        char a[20];
        gets(a);
        turnout(a);
        puts(a);
        return 0;
    } 

    22.提取字符串中的元音字母

    本题牵扯到数组传参,以及字符串判断结束的条件

    #include<stdio.h>
    #include<string.h>
    void extractV(char a[],char b[]){
        int len=strlen(a);
        int j=0;
        for(int i=0;i<len;i++){
            if(a[i]=='a'||a[i]=='A'||a[i]=='e'||a[i]=='E'||a[i]=='i'||a[i]=='I' 
            ||a[i]=='o'||a[i]=='O'||a[i]=='u'||a[i]=='U'){
                b[j] = a[i];
                j++;
            }
        }
        b[j]='';//这里就要注意结尾的结束符 
    }
    int main(){
        char a[20];
        char b[20];
        gets(a);
        extractV(a,b);
        puts(b);
        return 0;
    } 

    23.指针变量

    又到了这个令人头疼的问题,我大一C语言学习之路就终结在指针部分,之后真的就再也看不下去了,这也直接影响了我对链表的学习,噩梦开始的地方,借此机会,一定攻克这个难关。

    指针变量用来存放指针,指针变量的定义与普通变量有所区别,它在某种数据类型后加星号*来表示这是一个指针变量。

    int* p;
    double* p;
    char* p; 

    注意:*放在数据类型之后或者变量名之前都是可以的。

    其中C程序员习惯于把*放在变量名之前,即“int *p”;C++程序员更习惯于把*放在数据类型之后。

    如果一次需要同时定义几个类型相同的指针变量,则需要在每个变量名之前都加上*。

    int *p1,*p2,*p3;

    指针变量存放的是地址,而&则是取地址运算符,因此给指针变量赋值的方式一般是把变量的地址取出来,然后赋给对应类型的指针变量

    int a;
    int* p = &a;

    这里需要注意的是,int*是指针变量的类型,而后面的p才是变量名,用来存储地址,因此&a是赋给p的而不是赋给*p的

    对于一个指针变量存放的地址,我们可以通过*(可以看作开启地址的钥匙)来获取这个地址所指的元素。

    #include<stdio.h>
    int main(){
        int a;
        int* p = &a;
        a = 3;
        printf("%d
    ",p);//p里面存放a的地址
        printf("%d
    ",*p);//使用*(相当于钥匙),打开p地址里面存放的数据。
        printf("%d
    ",*(&a));//这里就相当于&a是一个地址,然后*是一把打开地址的钥匙,
                          //所以*(&a)就应该是&a里面存储的数据。 
        return 0;
    }
    /*输出结果:
    6487620
    3
    3 
    */ 

    另外,指针变量可以进行加减法,其中减法的结果就是两个地址偏移的距离。对于一个int*型的指针变量p来说,p+1是指p所指的int型变量的下一个int型变量地址

    24.指针与数组

    数组在地址上都是连续的,这样可以在元素前面加上取址运算符&来获取它的地址,例如a[0]的地址为&a[0],即数组a的首地址为&a[0]。在c语言中,数组名称可以当作数组的首地址使用,即a == &a[0]

    #include<stdio.h>
    int main(){
        int a[10]={1,2,3};
        int* p = a;
        printf("%d
    ",*p;
        printf("%d
    ",*p+1);//指针加法的使用 
        printf("%d
    ",*p+2);
        return 0;
    }
    /*输出结果:
    1
    2
    3 
    */ 

    ps:在数组中 a+i == &a[i]

    25.使用指针变量作为函数参数

    指针类型也可以作为函数参数的类型,这时视为把变量的地址传入参数。如果在函数中对这个地址中的元素进行改变,原先的数据就会确实地被改变

    #include<stdio.h>
    void change(int* p){
        *p = 233;
    } 
    int main(){
        int a = 1;
        int* p = &a;
        change(p);
        
        printf("%d
    ",a);
        return 0;
    }
    /*输出结果:
    233
    */ 

    26.引用传递

    引用是c++中的语法,可以不通过指针就能修改传入的参数,对引用变量的操作就是对原变量的操作。使用方法:只需要在函数的参数类型后面加个&就可以了。

    #include<stdio.h>
    void change(int &a){
        a = 123;
    } 
    int main(){
        int a = 10;
        change(a);
        printf("%d
    ",a);
    }
    /*输出结果:
    123
    */ 

    27,将指针类型参数传递与数组相结合的题目

    #include<stdio.h>
    #include<string.h>
    void input(int* p){
        for(int i = 0;i<10;i++){
            scanf("%d",p+i);
        }
        
    }
    void process(int* p){
        int min=9999;
        int max=-1;
        int maxi,mini;
        for(int i = 0;i<10;i++){
            if(*(p+i)>max){
                max = *(p+i);
                maxi = i;
            }
            if(*(p+i)<min){
                min = *(p+i);
                mini = i;
            }
        }
        int temp1 = *p;
        *p = *(p+mini);
        *(p+mini) = temp1;
        int temp2 = *(p+9);
        *(p+9) = *(p+maxi);
        *(p+maxi) = temp2;
    }
    void print(int* p){
        for(int i = 0;i<10;i++){
            printf("%d ",*(p+i));
        }
    }
    int main(){
        int a[10];
        int* p = a;
        input(p);
        process(p);
        print(p);
        return 0;
    }

    28.访问结构体内的元素

    #include<stdio.h>
    struct student{//结构体的定义 
        int id;
        char name[20];
        student* next;
    }stu,*p;//变量的声明 
    int main(){
        p = &stu;
        stu.id = 5; 
        printf("%d
    ",stu.id);//普通变量通过.访问 
        printf("%d
    ",(*p).id);//指针变量可以通过.访问 
        printf("%d
    ",p->id);//也可以通过->访问 
        return 0;    
    } 
    /*
    输出结果:
    5
    5
    5
    */

    29.cout控制double型精度输出

    需要使用头文件#include<iopmanip>

    #include<iostream>
    #include<iomanip>
    using namespace std;
    int main(){
        cout<<setiosflags(ios::fixed)<<setprecision(2)<<123.4567<<endl;
        return 0;
    }
    //输出结果:123.46 

    30.浮点数的比较

    浮点数在计算机里的存储并不总是精确的,这种情况会给比较带来麻烦,因为在C/C++中“==”要完全相同结果才会判定为true,于是需要引用一个极小数eps来对这种误差进行修正。

    经验表明,eps取10-8是一个合适的数字——对于大多数的情况既不会漏判也不会误判,所以可以将eps定义为常量1e-8:

    const double eps = 1e-8; 

    为了使比较更加方便,可以把比较操作写成宏定义的形式:

    #define Equ(a,b) ((fabs((a)-(b)))<eps) //判断相等

    如果想使用不等于,只需要在Equ前面加上一个非运算符“!”即可(!Equ(a,b))。于是就可以在程序中使用Equ函数来对浮点数进行比较了:

    #include<stdio.h>
    #include<math.h>
    const double eps = 1e-8;
    #define Equ(a,b) ((fabs((a)-(b)))<(eps))
    int main(){
        double db = 1.23;
        if(Equ(db,1.23)){
            printf("True
    ");
        }else{
            printf("False
    ");
        }
        return 0;
    }
    //输出结果:True 

    常用的浮点数比较宏定义:

    #define Equ(a,b) ((fabs((a)-(b)))<(eps)) //等于
    #define More(a,b) (((a)-(b))>(esp)) //大于
    #define Less(a,b) (((a)-(b))<(-esp))//小于
    #define MoreEqu(a,b) (((a)-(b))>(-esp))//大于等于
    #define LessEqu(a,b) (((a)-(b))<(esp))//小于等于

    31.圆周率

    圆周率Π不需要死记,因为由cos(Π)=-1可知Π=arccos(-1)。因此把Π写成常量acos(-1.0)即可。

    #include<stdio.h>
    #include<math.h>
    const double Pi = acos(-1.0);
     
    int main(){
        printf("%f
    ",Pi);
        return 0;
    }
    //输出结果:3.141593

    32.多点测试输入方式

    1)While...EOF型

    while(scanf("%d",&n)!=EOF){
        ...
    }
    //字符串
    while(scanf("%s",str)!=EOF){
      ...
    }
    while(gets(str)!=NULL){
      ...
    }

    2)While...break型

    在while...EOF的内部判断,满足条件,break跳出

    3)while(T--)型

    33.结构体指针实例

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    struct student{
        int num;
        char name[20];
        char sex;
        int age;
    };
    int main(){
        int n;
        scanf("%d",&n);
        student s[20];
        student *stu = s;
        for(int i = 0;i < n;i++){
            //scanf("%d%s%c%d",(stu+i)->num,(stu+i)->name,(stu+i)->sex,(stu+i)->age);
            cin>>(stu+i)->num>>(stu+i)->name>>(stu+i)->sex>>(stu+i)->age;
        }
        for(int i=0;i<n;i++){
            //printf("%d %s %c %d
    ",(stu+i)->num,(stu+i)->name,(stu+i)->sex,(stu+i)->age);
            cout<<(stu+i)->num<<' '<<(stu+i)->name<<' '<<(stu+i)->sex<<' '<<(stu+i)->age<<endl;
        }
        return 0;
    }

    仍有一个问题困惑着我,为什么使用scanf和printf输入输出会出错(注释掉的部分)。

    34.%s后输入%c,%c会接收%s后的空格,从而使数据不能正常接收。

    #include<stdio.h>
    int main(){
        int a;
        char b[20];
        char c;
        char d;
        scanf("%d%s%c%c",&a,b,&c,&d);
        printf("%d %s %c %c
    ",a,b,c,d);
        return 0;
    }
    /*
    输入:1 Li c
    输出:1 Li   c   (第三个参数为空格) 
    */ 

    此问题目前可用cin,cout输入输出解决。

     问题原因以及解决方法:https://blog.csdn.net/qq_40977765/article/details/79911312

    35.竞赛及机试中会用到的输入格式练习:http://www.codeup.cn/contest.php?cid=100000574

  • 相关阅读:
    oracle——定时器时间设置
    Servlet上下文监听
    jsp开发中页面数据共享技术
    String类的创建
    Microsoft Enterprise Library 5.0 系列 Configuration Application Block
    How to print only the selected grid rows
    企业库的保存方法
    devexpress pictureedit 按钮调用其菜单功能
    Devexpress IDE 插件 卸载
    修改安装包快捷方式路径
  • 原文地址:https://www.cnblogs.com/nyist0/p/10059571.html
Copyright © 2020-2023  润新知