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;

 }



*/



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

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

12天学好C语言——记录我的C语言学习之路(Day 8)的更多相关文章

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

    12天学好C语言--记录我的C语言学习之路 Day 12: 进入最后一天的学习,用这样一个程序来综合考量指针和字符串的关系,写完这个程序,你对字符串和指针的理解应该就不错了. //输入一个字符串,内有 ...

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

    12天学好C语言--记录我的C语言学习之路 Day 11: 因为指针部分比较的难,所以我们花费的时间也是最长的,希望大家耐的住性子,多多理解,多多打代码.好了,废话不多说,来看第11天的学习. //编 ...

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

    12天学好C语言--记录我的C语言学习之路 Day 10: 接着昨天的指针部分学习,有这么一个题目: //还是四个学生,四门成绩,只要有学生一门功课没及格就输出这个学生的所有成绩 /*//progra ...

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

    12天学好C语言--记录我的C语言学习之路 Day 9: 函数部分告一段落,但是我们并不是把函数完全放下,因为函数无处不在,我们今后的程序仍然会大量运用到函数 //转入指针部分的学习,了解指针是什么 ...

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

    12天学好C语言--记录我的C语言学习之路 Day 7: 昨天进行了一天的数组学习,今天大家可以先写几个昨天的程序热热身,回顾回顾,然后今天第一个新程序也是关于数组的,比较难,准备好就开始啦! //输 ...

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

    12天学好C语言--记录我的C语言学习之路 Day 6: 今天,我们要开始学习数组了. //①数组部分,数组的大小不能够动态定义.如下: //int n;   scanf("%d,& ...

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

    12天学好C语言--记录我的C语言学习之路 Day 5: 第五天的学习开始了,今天我们主要对几个程序进行编写,让自己充分的熟练编程语言,大量的题目会让自己变的精炼.以一个程序(program 5.1) ...

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

    12天学好C语言--记录我的C语言学习之路 Day 4: 首先来看一段程序: //输出下面4*5的矩阵 /* 1  2  3   4   5 2  4  6   8   10 3  6  9   12 ...

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

    12天学好C语言--记录我的C语言学习之路 Day 3: 不知不觉到了第三天的学习,我们前两天学习的东西很杂乱,各个方面都有学习.我觉得这不是不系统,也不是学的不扎实,这种学习对于初学者而言我认为是很 ...

随机推荐

  1. [Xcode使用 - 2] 设置APP图标和启动画面

    1.App Icon   把所有图标文件拖放到 “Images.xcassets” 的”AppIcon” 里面     应对非视网膜和视网膜屏,APP有时会提供两套不同大小的图片,1倍图和2倍图,它们 ...

  2. CSS区块、浮动、定位、溢出、滚动条

    CSS中区块的使用 CSS中浮动的使用 CSS中定位的使用 CSS中溢出的使用 CSS中滚动条的使用 17.1 CSS中区块的使用 属性名称            属性值                ...

  3. Custom Properties for Alert Description and Notification(PropertyBag)

    Alert Description Variables: For event Rules: EventDisplayNumber (Event ID):             $Data/Event ...

  4. Mac下移动硬盘不能粘贴

    不想格式化,安装 Paragon NTFS 10.0.2 from:http://www.nowmac.com/support/mac/664.html 就可以解决

  5. Codeforces Round #322 (Div. 2) C. Developing Skills 优先队列

    C. Developing Skills Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/p ...

  6. BZOJ [ZJOI2008]泡泡堂BNB 贪心

    [ZJOI2008]泡泡堂BNB Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/proble ...

  7. 学习笔记之SQL Programming DB2

    http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp If you intend to update a column or ...

  8. [Effective C++ --019]设计class犹如设计type

    前言 我们在编写程序的时候,无论哪一种语言,总是会告诉你这种语言应该有的类型.我们将它们直接拿来使用,可是从来没有考虑过这些类到底是怎么设计出来的! 所幸的是:在OOP中,每当我们定义一个新的clas ...

  9. Android 自学之自动完成文本框 AutoCompleteTextView

    自动完成文本框(AutoCompleteTextView)从EditText派生而出,实际上他也是一个编辑框,但他比普通的编辑框多了一个功能:当用户输入一定字符后,自动完成文本框会显示一个下拉菜单,供 ...

  10. 关于Socket通讯原理

    通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄. 在Internet上的主机一般运行了多个服务软件,同时提供几种服务. 每种服务都打开一个Socket,并绑定到一 ...