12天学好C语言——记录我的C语言学习之路(Day 8)

时间:2023-12-14 14:01:26

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\n数组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\n",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\n",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\n",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\n",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("请输入两个数字:\n");

    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\n",yue(a,b));//这样输出或者是上面的先把值赋给变量再输出都行。

    printf("%d\n",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("请输入一个整数:\n");

    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\n",a,b);

    for(int i=0;i<3;i++)

    {

        printf("c[%d]=%c\n",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:\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是素数\n",i);

     }

     return 0;

 }



*/



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

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