zoukankan      html  css  js  c++  java
  • 12天学好C语言——记录我的C语言学习之路(Day 8)

    12天学好C语言——记录我的C语言学习之路

    Day 8:

    从今天开始,我们获得了C语言中很有力的一个工具,那就是函数。函数的魅力不仅于此,一个程序到最后都是由众多函数组成的,我们一定要用好函数,用熟练。函数掌握了,就会对你的编程水平有不小的提升。

    还是以一个简单的程序开始今天的学习:

    //输入10个数字,要求输出最大值和该值是数组中第几个元素(当然要用到函数思想)

    /*//program 8.1
    #include "stdio.h"
    int main()
    {
        int a[11];
        int i,n=1;
        for (i=1; i<=10; i++) {//为了方便辨识,a[1]就认为是第一个元素,所以我们把i设为从1开始的
            scanf("%d",&a[i]);
        }
        int max(int a,int b);
        int m=a[1];
        for(int i=2;i<=10;i++)
        {
            if(max(m,a[i])>m)//如果m与a[i]之间的最大值比m大,才交换,交换即将a[i]的下标i赋给n,用n来记录第几个数组元素是最大的。当然n初始化为1,因为如果第一个数最大的话,不需要交换,所以n也不用变化了
            {
                m=max(m,a[i]);
                n=i;
            }
        }
        printf("No.%d is max,max is %d",n,m);
        return 0;
    }
    int max(int a,int b)
    {
        return(a>b?a:b);
    }
    */

    //用score[10]来存放10个学生的成绩并输出其平均值,要求用函数去做

    /*//program 8.2
    #include "stdio.h"
    int main()
    {
        int i;
        double aver1,score[10];
        double aver(double score[10]);    //声明一个函数aver,里面传入一个有10个元素的数组
        for (i=0; i<10; i++) {
            scanf("%lf",&score[i]);
        }
        aver1=aver(score);    //调用的时候,是将数组名作为参数传入到函数中的,此时传递的是数组首个元素的地址,这里一定要知道,你要处理求平均值的是整个数组的所有元素,而不是单单一个元素,所以必须传入数组名
        printf("average = %lf",aver1);
        return 0;
    }
    double aver(double score[10])
    {
        double sum=0,aver2;
        int i;
        for(i=0;i<10;i++)
        {
            sum+=score[i];
        }
        aver2=sum/i;
        return aver2;
    }
    */

    //上个题目规定了传入函数的数组长度,那么现在我们自己定义两个不一样长度的数组,然后用一个函数分别求两个数组元素的平均值。

    /*//program 8.3
    #include "stdio.h"
    int main()
    {
        double a1[15]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        double a2[10]={1,2,3,4,5,6,7,8,9,10};
        double aver(double b[],int n);    //这样就已经理解了,定义这个函数,我们可以知道,是传入一个长度为n,类型是double型的数组,而后面b[],只是体现了这是一个没有声明长度数组,函数名也是形参,传入实参数组的时候可以变化。
        double p,q;
        p=aver(a1,15);    //调用的时候切记前面是函数名,不用加中括号了
        q=aver(a2,10);
        printf("数组a1的平均值为%lf 数组a2的平均值为%lf",p,q);
        return 0;
    }
    double aver(double b[],int n)    //函数定义时的函数首部只比函数声明少一个分号,无论是传入的什么形式的参数都这样,不要弄错~
    {
        double sum=0;
        double aver1;
        for (int i=0; i<n; i++) {
            sum+=b[i];
        }
        aver1=sum/n;
        return aver1;
    }
    */

    下面这个程序又带领大家复习了一下选择排序法,其实归根结底还是考差大家对函数的应用是不是熟练

    //将一个数组作为参数传入函数中,此函数为选择排序法排序。(由大到小)
    //选择排序,i是趟数也是该趟需要往下比较的元素的下标。j从i的下一个下标(i+1)开始,与k比较并将符合条件的下标赋给k,直到循环结束,k得到最终的下标,然后再和i交换。整个比较的过程i是不参与的(除了限制循环次数的时候用到),其余全部交给k和j来操作。而交换的时候,是i与k的操作,j不参与。最后输出,是i操作,j、k没有价值了。

    /*//program 8.4
    #include <stdio.h>
    int main()
    {
        int a[10];
        for(int i=0;i<10;i++)
        {
            scanf("%d",&a[i]);
        }
        void sequence(int a[],int n);
        sequence(a,10);
        return 0;
    }
    void sequence(int a[],int n)
    {
        int i,j,k,temp;
        for (i=0; i<=n-2; i++) {//
            k=i;//看到选择排序法就要清楚,选择排序法最多进行n-1次交换,所以说,我们就清楚,需要找一个变量暂时储存较大值的下标k,然后最后交换关键的一次。这样才能交换的尽可能的少。
            for (j=i+1; j<n; j++) {//记住,j表示每一趟的a[i]需要和哪些值比较。自然是和 a[i+1]~a[n-1] 之间的值比较
                if(a[k]<a[j])//a[i]是当前趟数需要往下挨个比较的那一个元素,让k去替代i,然后用k和j比较,将较大的值的下标赋给k,k不断变化,变化的不能再大的时候,k也就是当前趟数比较得出的最大值的下标,然后a[k]就是当前趟数的最大值,最后再和下标i所代表的元素交换。
                {
                    k=j;
                }
            }
            temp=a[k];
            a[k]=a[i];
            a[i]=temp;
        }
        for (i=0; i<10; i++) {
            printf("a[%d]=%d ",i,a[i]);
        }
        
    }
    */


    //多维数组做函数参数。
    //有一个3*4的矩阵,求里面元素的最大值。
    //用多维数组作为函数形参的时候,要记住,一维大小可以省略不填,但是二维大小一定要填上,而且还得和传入的实参数组二维大小一样。
    //函数是很灵活的,函数里面的参数可以按需求定义~

    /*//program 8.5
    #include <stdio.h>
    int main()
    {
        int a[3][4]={{1,2,3,9},{2,4,5,6},{1,2,1,8}};
        int b[5][4]={{1,2,3,9},{2,4,5,6},{1,2,1,8},{1,2},{10,2,19}};
        void max(int a[][4],int x);//x表示的一维大小,这里可以变化,只要是二维大小和声明的函数中保持一直就可以
        max(a,3);
        max(b,5);
        return 0;
    }
    void max(int a[][4],int x)
    {
        int i=0,j=0,max2=a[0][0];
        int x1=0,y1=0;
        for (i=0; i<x; i++) {
            for (j=0; j<4; j++) {
                if(max2<a[i][j])
                {
                    max2=a[i][j];
                    x1=i;
                    y1=j;
                }
            }
        }
        printf("max is [%d][%d]=%d ",x1,y1,max2);
        
    }
    */


    //在函数内(或者复合语句内)声明的变量是局部变量,只在该函数内(或者复合语句内)作用。
    //在函数外声明的变量是全局变量(也称外部变量),但是他们的作用范围不同,作用范围是从定义变量的位置开始到本源文件结束

    //这个程序是错误的,因为输出的时候i已经被程序释放了。i是在for循环中定义的,随着for循环结束而释放。

    /*//program 8.6
    #include <stdio.h>
    int main()
    {
        int sum=0;
        for(int i=0;i<3;i++)
        {
            sum+=i;
        }
        printf(“sum=%d,i=%d",sum,i);    //会显示i没有被定义
        return 0;
    }
    */

    /*//program 8.7
    //用一个一维数组存放10个学生的成绩,写一个函数,当主函数调用这个函数的时候,能求出平均分,最高分,最低分
    #include "stdio.h"
    float MAX,MIN,aver;//定义全局变量
    int main()
    {
        int a[10]={80,81,82,83,84,85,86,87,88,89};
        void abc(int b[10]);
        abc(a);
        return 0;
    }
    void abc(int b[10])
    {
        MAX=b[0];
        MIN=b[0];
        float sum=0;
        for (int i=0; i<10; i++) {
            if(MAX<b[i])
            {
                MAX=b[i];
            }
            if(MIN>b[i])
            {
                MIN=b[i];
            }
            sum=sum+b[i];
            aver=sum/10;
        }
        printf(“MAX=%f,MIN=%f,aver=%f",MAX,MIN,aver);   //aver没有定义成全局变量的时候会有警告,请读者分析一下为什么是这样。
    }
    */

    //在C中,每一个 变量 和 函数 都有两个属性,一个是数据类型(如:int,char等),另一个是数据的存储类别(如:静态存储和动态存储)。
    //C的存储类别包括4种:自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)
    //①自动变量(auto变量):auto存储类别属于 动态 存储方式,在程序中 大多数 变量都属于auto变量。关键字auto一般省略,在函数中定义的变量,其实都隐含指定为自动变量
    //②静态局部变量(static局部变量):函数调用结束后不消失而继续保留原值,即占用的存储单元不释放。比如下面的程序:

    /*//program 8.8
     #include "stdio.h"
    int main()
    {
        int f(int a);
        int a=2,i;
        for(i=0;i<3;i++)
        {
            printf("%d ",f(a));
        }
        return 0;
    }
    int f(int a)
    {
        auto int b=0;
        static int c=3;
        b=b+1;
        c=c+1;
        printf("c=%d ",c);
        return(a+b+c);
    }
     */
    //运行的结果,输出:c=4,7,c=5,8,c=6,9        我们可以看出,c的值是不断增加的,因为c是不随着一次函数结束而释放的,他一直存在,所以每次使用c都是上一次函数调用完之后c的值,而运行结果也只是随着c的变化而变化,这是因为b是不变化的,函数调用完毕,b释放,所以b永远是从0开始去执行b=b+1的。
    //输出n!,要求用静态变量。

    /*//program 8.9
    #include <stdio.h>
    int main()
    {
        int n;
        scanf("%d",&n);
        int f(int n);
        printf("%d",f(n));
        return 0;
    }
    int f(int n)
    {
        static int f=1;
        while(n>=1)
        {
            f=f*n;
            n--;
        }
        return f;
    }
    */

    //③寄存器变量(register):适用于大次数循环,直接将变量存储到CPU中的寄存器中,这样的存取速度远远高于对内存的存取速度。
    //④外部变量(extern):可以给其他文件引用

    //写出两个函数,分别求最大公约数和最小公倍数,用主函数调用这两个函数,整数a、b由键盘输入。

    /*//program 8.10
    #include <stdio.h>
    int main()
    {
        printf("请输入两个数字: ");
        int yue(int x,int y);
        int bei(int x,int y);
        int a,b;
        //int c,d;
        scanf("%d%d",&a,&b);
        //c=yue(a,b);
        //d=bei(a,b);
        //printf("%d %d",c,d);
        printf("%d ",yue(a,b));//这样输出或者是上面的先把值赋给变量再输出都行。
        printf("%d ",bei(a,b));
        return 0;
    }
    int yue(int x,int y)
    {
        int temp,yueshu;
        if(x>y)
        {
            temp=x;
            x=y;
            y=temp;
        }
        for(int i=x;i>=1;i--)
        {
            if(x%i==0&&y%i==0)
            {
                yueshu=i;
                break;
            }
        }
        return yueshu;
    }
    int bei(int x,int y)
    {
        int temp,beishu;
        if(x>y)
        {
            temp=x;
            x=y;
            y=temp;
        }
        for(int i=y;i<=x*y;i++)//i是循环的变量,x、y只是控制i循环的次数。前面的i不要写成别的。
        {
            if(i%x==0&&i%y==0)
            {
                beishu=i;
                break;
            }
        }
        return beishu;
    }
    */

    //输入一个4位数字,要求在每两个数之间加一个空格输出

    /*//program 8.11
    #include <stdio.h>
    int main()
    {
        int n;
        scanf("%d",&n);
        void ab(int n);
        ab(n);
        return 0;
    }
    void ab(int n)
    {
        int g,s,b,q;
        q=n/1000;
        b=n%1000/100;
        s=n%100/10;
        g=n%10;
        char cc[4]={'0'+q,'0'+b,'0'+s,'0'+g};//将数字转化为相对应的字符型的妙招,要知道一个数字字符('0'~'9')和字符'0'之间的距离正好是这个数字字符所代表的数字的大小。当然这个地方用整型输出也一样~ = =
        for (int i=0; i<4; i++) {
            printf("%c ",cc[i]);
        }
    }
    */

    //将一个整数n转化为字符串n,n的位数不确定。

    /*//program 8.12
    #include "stdio.h"
    int main()
    {
        int n;
        printf("请输入一个整数: ");
        scanf("%d",&n);
        void dc(int n);//int→char型的函数
        dc(n);
        return 0;
    }

    void dc(int n)
    {
        void d(int n);
        if (n==0) {
            char a=0+'0';
            printf("%c",a);
        }
        else
        {
            d(n);
        }
    }

    void d(int n)
    {
        int a[100],i=0;
        while(n>0)
        {
            a[i]=n%10;
            n=n/10;
            i++;
        }
        int k=i;
        char c[k];
        for (i=0; i<k; i++) {
            c[i]=a[k-i-1]+'0';//一般由整型的数字转化为字符型的该数字(如 5 转化成 '5'),转化的时候可以在整型后面加一个字符'0',那么表示的就是和字符'0'相差该数字长度的字符了,正好就是该数字字符。   相反的,如果是字符型的数字转化为整型的该数字(如 '5' 转化成 5),可以减去'0',表示的是该数字字符与字符'0'之间的距离,这个距离所表示的数值也正好是该数字。
        }
        printf("%s",c);
    }
    */

    //一些小验证

    /*//program 8.13
    #include "stdio.h"
    int main()
    {
        int a=1%10;//结果为1
        int b=1/10;//结果为0
        
        int x=98,y=99,z=100;
        char c[3]={x,y,z};//直接把整型的数字赋给字符型数组,那么输出的字符型数组中的元素 并不是 这三个数字字符,而是在ASCII码表中数字代表的字符。
        printf("%d  %d ",a,b);
        for(int i=0;i<3;i++)
        {
            printf("c[%d]=%c ",i,c[i]);
        }
        return 0;
    }
    */


    //n个人报数,报123,报到3的出去,剩下的人再报数,问最后剩下几号?

    /*//program 8.14
    #include<stdio.h>
    int main()
    {
        int i=0;
        int n=0;
        int out=0;//已经退出了out个人
        int num=0;//报数的号码
        int a[1000]={0};//a [i]=0表示该序号的人退出,等于1留下
        printf("请输入n: ");
        scanf("%d",&n);
        for (i=0; i<n; i++) {
            a[i]=1;
        }
        i=0;
        while (out!=n-1) {//n为1时不执行while语句
            if(a[i]==1)//如果是1,就将报数的序号+1;
            {
                num++;
            }
            if(num==3)//序号一旦到3,序号就清零,继续从1开始报数,此时要把这一项的值设为0,也就是踢出去这一项
            {
                a[i]=0;
                num=0;
                out++;//排除一个就让out++  让out来计算人数是不是还大于1个人  一个人的时候不执行while语句
            }
            i++;//每判断一项,都要让数组元素的下标+1,为什么写在这个地方,因为i对out(while语句是否结束)和num++(报数)都有影响,每改变一次i值,需要让这两个相关项都执行完毕后再让i++,所以说i++应该放在num和out的改变之后。(当然第一次刚进入while循环的时候i是有初始值的,这时直接进行num和out的变化就可以了)
            if(i==n)//如果第一次所有人的循环到头了,比如说一共四个人,第三个人踢出去了,num=0,那么第四个人( a[3] )的num=1,然后i再加变成4,没有a[4]这一项,所以要将i变为0,再从头报数,不过这时候num没变还是1,所以下一个a[0]的num就是2了
            {
                i=0;//从始至终,原定a[i]的下标是没有改变的,这里让i=0,是i超了范围才改变的,改变完正好是第一个元素,报数也应该到了第一个元素了,所以说i==n(下标越界)应该放在最后,一旦越界,下标i立马变为一,再从第一个元素报数起
            }
        }
        for (i=0; i<n; i++) {
            if(a[i]==1)
            {
                printf("留下的人是%d号",i+1);
            }
        }
        return 0;
    }
    */

    //求100~200之间的所有素数(用2~sqrt(n)去整除即可),这样判断的次数会大大降低。

    /*//program 8.15
     #include "stdio.h"
     #include "math.h"
     int main()
     {
         int i,j;
         for(i=101;i<=200;i=i+2)//要从101 开始,依次加2判断,因为偶数肯定不是素数,不要从100开始
         {
             for(j=2;j<=sqrt(i);j++)
             {
                 if(i%j==0)
                     break;
             }
             if(j>sqrt(i))  //如果在2~sqrt(i)之间都没有可以整除j的,那么j执行完最后一次j++后就将跳出内层for循环,这时我们就可以判断i是素数了,然后输出即可
                 printf("%d是素数 ",i);
         }
         return 0;
     }

    */

    今天我们主要是写了几个经典函数程序,然后我又对之前一些问题做了说明,今天学习的程序比较多,希望大家能按时掌握,越到后面越困难,大家一定要挺住!!!加油!!!

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    试验thrift做后端rpc,nginx做web服务器, python后端php前端
    DBSCAN算法
    用VAE(variational autoencoder)做sentence embedding/representation或者其他任何结构数据的热presentation
    关于rnn神经网络的loss函数的一些思考
    神经网络建模的一些感悟;
    embedding based logistic regression-神经网络逻辑回归tensorflow
    Farseer.net轻量级开源框架说明及链接索引
    什么是表达式树,它与表达式、委托有什么区别?(1)
    Farseer.net轻量级ORM开源框架 V1.x 教程目录
    Farseer.net轻量级ORM开源框架 V1.8版本升级消息
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787907.html
Copyright © 2011-2022 走看看