• Coursera课程笔记----C程序设计进阶----Week 1&2


    C程序中的函数(Week 1&2)

    函数

    函数的定义

    • 对函数的普遍认识:y=f(x)

    • C语言中的常用函数

      • 平方根: r = sqrt(100.0)
      • 底数x的y次幂:k = pow(x,y)
      • 字符串的长度:i = strlen(str1)
      • 比较两个字符串的大小: v = strcmp(str1,str2)
      • 把字符串转换为相应整数: n = atoi(str1)
    • 在C语言中,我们可以把所有程序都组织成函数

    • 定义一个函数:

    int absolute(int n)//n为形式参数,用于辅助进行函数定义,与实际参数相对
    {
      if(n<0)
        return (-n);
    	else
        return n;
    }
    
    float max(float a, float b)//2个形式参数的情况
    {
      if(a > b)
        return a;
      else
        retuen b;
    }
    
    int get_int() //无参函数的例子
    {
      int n = 0;
      cout<<"Please input an integer:"<<endl;
      cin >> n;
      return n;
    }
    
    void delay(int n) //无返回值函数的例子
    {
      for(int i = 0; i < n* 100000;i++);
      return; //可不写
    }
    
    void show() //既无参数也无返回值的例子
    {
      cout<<"***************************************";
      cout<<"********************show***************";
      cout<<"***************************************";
    }
    
    #include <iostream>
    using namespace std;
    int main() //程序执行的入口
    {
      
      return 0;
    }
    //用void定义的main函数是老的C标准,因为无法获知调用结果所以该方式被放弃
    
    • 函数调用的方式

      • 作为独立语句
      • 作为表达式的一部分(存在一个计算式中)
      • 实际参数形式出现在其他函数的调用
    • 函数是C程序的基本构成单位

      • 一个C程序由一个或多个源文件组成
      • 一个源程序文件可以由一个或多个函数组成
    • 函数的类型——函数的返回值的数据类型

    • 可以在main函数的后面定义函数,但必须要在main函数前面先声明

    • 函数原型&函数声明

      • 函数原型

        • 由函数的返回类型、函数名以及参数表构成的一个符号串,其中参数可不写名字

          bool checkPrime(int)

        • 函数的原型也叫函数的"Signature"

      • 函数声明

        • 函数在使用前都要声明,除非被调用函数的定义部分已经出现在主调函数之前
        • 在C语言中,函数声明=函数原型

    函数的执行

    • 在main函数中调用max函数的过程
      • 在调用max函数之前
        • 初始化max()
        • 传递参数
        • 保存当前现场
      • 在调用max函数之后
        • 接受函数的返回值
        • 恢复现场,从断点处继续执行
    • 函数参数的传递
      • 实参把数据"copy"给形参,因此对实参本身无影响
      • 实惨与形参具有不同的存储单元,实参与形参变量的数据传递是"值传递"
      • 函数调用时,系统给形参分配存储单元,并将实参的传给形参
        • 实参与形参的类型必须相同可以兼容
    • 思考总结
      • 值传递!值传递!值传递!

    变量的作用范围

    • 变量的分类
      • 局部变量:在函数内或代码块内定义,其作用域是函数内或代码块内
      • 全局变量:所有函数外定义的变量,其作用域是从定义变量的位置开始到程序文件结束为止
    • 当全局变量与局部变量同名时,局部变量将在自己的作用域内有效,它将屏蔽同名的全局变量。

    数组与函数

    • 数组元素做函数参数,没有什么特别(值传递

    • 数组名做函数参数

      • 虽然仍是copy,但数组名不是变量,而是数组在内存中的地址,因此不是值传递
    • 总结

      • 传递地址是一件严重的事情

    函数举例

    例1 日历问题

    • 问题:给定从公元2000年1月1日开始逝去的天数,请编写程序给出这一天是哪年哪月哪日星期几
      • 注意闰年:闰年被定义为能被4整除的年份,但能被100整除而不能被400整除的年不是闰年
      • 注意每个月的天数是不同的
    • 输入输出要求
      • 输入多组数据,每组一个正整数,表示从2000年1月1日开始已经过去的天数
      • 对输入的每一个天数,输出一行,该行包含对应的日期和星期几,格式为"YYYY-MM-DD DayOfWeek"
      • 其中"DayOfWeek"必须是:Sunday,Monday,Tuesday,WWednesday,Thursday,Friday and Saturday.
      • 输入最后一行是-1,不必处理,可以假设结果的年份不会超过9999
    • 思路
      • 先记录days,再计算出星期几,再减掉每年的天数(还要判断年是不是闰年),再减掉每月的天数(每月天数是不同的),从而逐步得到最终结果。
    //主程序
    #include<iostream>
    using namespace std;
    int days;
    int get_dayofweek();
    int get_year();
    int get_month(int);
    int main()
    {
      int year,month,dayofweek;
      int leap_year;
      char week[7][10] = {"Saturday","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"};
        while((cin>>days) && days!= -1)
        {
          dayofweek = get_dayofweek();
          year = get_year();
          leap_year = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
          month = get_month(leap_year);
          cout<<year<<"-"<<month<<"-"<<++days<<" "<<week[dayofweek];
        }
      return 0;
    }
    
    //计算星期几,2000年1月1日是周六
    int get_dayofweek()
    {
      return days % 7;
    }
    
    //计算年数
    int get_year()
    {
      int i = 2000, leap_year;
      while(1)
      {
        leap_year = (i % 4 == 0 && i % 100 != 0 || i % 400 == 0);
        if(leap_year == 1 && days >=366)
        {
          days = days - 366;
          i++;
          continue;
        }
        else if(leap_year == 0 && days >= 365)
        {
          days = days - 365;
          i++;
          continue;
        }
        else break;
      }
      return i;
    }
    
    //计算月份
    int get_month(int leap_year)
    {
      int pmonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31}
      int rmonth[12] = {31,29,31,30,31,30,31,31,30,31,30,31}
      int j = 0;
      while(1)
      {
        if(leap_year == 1 && days >= rmonth[j])
        {
          days = days - rmonth[j];
          j++;
        }
        else if(leap_year == 0 && days >= pmonth[j])
        {
          days = days - pmonth[j];
          j++;
        }
        else break;
      }
      return ++j
    }
    
    //在该程序中,定义了全局变量days
    //该变量在三个函数和主函数中都要使用,会带来一些问题:围绕着days的错误会影响所有函数
    //
    
    
    

    总结

    • 全局变量
      • 破坏了函数的相对独立性
      • 增加了函数之间的耦合性
      • 函数之间的交互不够清晰
    • 因此
      • 在不是非常必要的情况下,不要使用全局变量

    练习题目

    Quiz1 寻找下标

    #include <iostream>
    using namespace std;
    int main()
    {
        int n,num[100];
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> num[i];
        }
    
        for (int i = 0; i < n; i++) {
            if(num[i] == i)
            {
                cout<<num[i]<<endl;
                break;
            }
            if(i == n-1)
            {
                cout<<"N"<<endl;
                break;
            }
    
        }
    
        return 0;
    }
    

    Quiz2 四大湖

    #include <iostream>
    using namespace std;
    int main()
    {
        for (int d = 1; d <= 4; d++) {
            for (int h = 1; h <= 4; h++) {
                for (int t = 1; t <= 4; t++) {
                    for (int p = 1; p <= 4; p++) {
                        if((d!=h && d!=t && d!=p && h!=t && h!=p && t!=p) &&
                                ((d==1)+(h==4)+(p==3) == 1)&&
                                ((h==1)+(d==4)+(p==2)+(t==3) == 1)&&
                                ((h==4)+(d==3) == 1)&&
                                ((p==1)+(t==4)+(h==2)+(d==3) == 1))
                        {
                            cout << p << '
    ' << d << '
    ' << t << '
    ' << h << endl;
                            break;
                        }
                    }
    
                }
    
            }
    
        }
    
        return 0;
    
    }
    //这个题让我冥思苦想了好久orz
    //每人仅答对一个就等于所有表达式的和为1……
    

    Quiz3 发票统计

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
        double sumPerson[4] = {0.0}, sumType[4] = {0.0};
        char type[4] = {'','A','B','C'};
        int person,flag = 3;
        while (cin >> person)
        {
            int number;
            char tempC;
            double tempD;
            cin >> number;
            for (int i = 0; i < number; i++)
            {
                cin >> tempC >> tempD;
                sumPerson[person] += tempD;
                if(tempC == type[1])
                    sumType[1] +=tempD;
                if(tempC == type[2])
                    sumType[2] +=tempD;
                if(tempC == type[3])
                    sumType[3] += tempD;
            }
            flag--;
            if(flag == 0)
                break;
        }
        for (int i = 1; i <= 3; i++)
            cout<<fixed<<setprecision(2)<<i<<" "<<sumPerson[i]<<endl;
        for (int i = 1; i <=3 ; i++)
            cout<<fixed<<setprecision(2)<<type[i]<<" "<<sumType[i]<<endl;
    
        return 0;
    }
    

    Quiz4 Tomorrow never knows?

    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    int get_year(int year, int month, int day)
    {
        if(month == 12 && day == 31)
            return year + 1;
        else return year;
    }
    
    int get_month(int year, int month, int day, bool leap_year)
    {
        if(day == 28 && month == 2 && !leap_year)
            return month + 1;
        if(day == 29 && month == 2 && leap_year)
            return month + 1;
        if(day == 30 && (month == 4 || month == 6 || month == 9 || month == 11))
            return month + 1;
        if(day == 31 && (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month ==10))
            return month + 1;
        if(day == 31 && month == 12)
            return 1;
    
        return month;
    }
    
    bool leap_year(int year)
    {
        return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
    }
    
    int main()
    {
        int y,m,d;
        char t1,t2;
        cin >> y >> t1 >> m >> t2 >> d;
        int ny = get_year(y,m,d);
        int nm = get_month(y,m,d,leap_year(y));
        int nd;
        if(get_month(y,m,d,leap_year(y)) == m)
            nd = d + 1;
        else nd = 1;
    
        cout<<ny<<'-'<<setw(2)<<setfill('0')<<nm<<'-'<<setw(2)<<setfill('0')<<nd;
        return 0;
    }
    

    Quiz5 细菌实验分组

    #include <iostream>
    using namespace std;
    
    
    int main()
    {
        int rate[101] = {0}, n;
        cin >> n;
    
        int maxDiff = 0;
        int index[101];
        int flag;
    
        for (int i = 1; i <= n ; i++) {
            int num,before,after;
            cin >> num >> before >> after;
            rate[num] = after / before;
            index[num] = num;
        }
    
        for (int i = 1; i <= n ; i++)
            for (int j = 1; j <= n - i ; j++)
            {
                if(rate[j] > rate[j+1])
                {
                    int temp = rate[j];
                    rate[j] = rate[j+1];
                    rate[j+1] = temp;
                    temp = index[j];
                    index[j] = index[j+1];
                    index[j+1] = temp;
                }
            }
    
        for (int i = 1; i <= n-1 ; i++) {
            if((rate[i+1]-rate[i]) > maxDiff)
            {
                maxDiff = rate[i+1] - rate[i];
                flag = i;
            }
        }
    
        cout<< n - flag <<endl;
        for (int i = flag+1; i <= n ; i++)
        {
            cout<<index[i]<<endl;
        }
    
        cout<< flag <<endl;
        for (int i = 1; i <= flag ; i++)
        {
            cout<<index[i];
            if(i == flag)
                break;
            else cout<<'
    ';
        }
    
        return 0;
        }
    

    Quiz6 流感传染

    #include <iostream>
    using namespace std;
    
    bool zuoOK(int i,int j,char matrix[100][100])
    {
        if(j != 0 && matrix[i][j-1] == '.')
            return true;
        else return false;
    }
    bool youOK(int i,int j,char matrix[100][100],int n)
    {
        if(j+1 < n && matrix[i][j+1] == '.')
            return true;
        else return false;
    }
    bool shangOK(int i,int j,char matrix[100][100])
    {
        if(i != 0 && matrix[i-1][j] == '.')
            return true;
        else return false;
    }
    bool xiaOK(int i,int j,char matrix[100][100],int n)
    {
        if(i+1 < n && matrix[i+1][j] == '.')
            return true;
        else return false;
    }
    bool zuoShangOK(int i,int j,char matrix[100][100])
    {
        if(i!=0 && j!= 0 && matrix[i-1][j-1] == '.')
            return true;
        else return false;
    }
    bool zuoXiaOK(int i,int j,char matrix[100][100],int n)
    {
        if(i+1<n && j!=0 && matrix[i+1][j-1] == '.')
            return true;
        else return false;
    }
    bool youShangOK(int i,int j,char matrix[100][100],int n)
    {
        if(j+1 < n && i != 0 && matrix[i-1][j+1] == '.')
            return true;
        else return false;
    }
    bool youXiaOK(int i,int j,char matrix[100][100],int n)
    {
        if(i+1 < n && j+1 < n && matrix[i+1][j+1] =='.')
            return true;
        else return false;
    }
    int main()
    {
        char room[100][100];
        int n;
        cin >> n;
        int numFlu = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
            {
                cin>>room[i][j];
                if(room[i][j] == '@')
                    numFlu++;
            }
    
        int m;
        cin >> m;
        for (int p = 1; p < m; p++){
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                {
                    if(zuoOK(i,j,room) && room[i][j] == '@')
                    {
                        room[i][j-1] = 'n';
                        numFlu++;
                    }
                    if(youOK(i,j,room,n)&& room[i][j] == '@')
                    {
                        room[i][j+1] = 'n';
                        numFlu++;
                    }
                    if(shangOK(i,j,room)&& room[i][j] == '@')
                    {
                        room[i-1][j] = 'n';
                        numFlu++;
                    }
                    if(xiaOK(i,j,room,n)&& room[i][j] == '@')
                    {
                        room[i+1][j] = 'n';
                        numFlu++;
                    }
                }
    
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    if(room[i][j] == 'n')
                        room[i][j] = '@';
    
        }
        cout<<numFlu<<endl;
    }
    
    //题目应该明说斜着不算临近啊!!!!害我白写了4个函数!!!QAQ
    
  • 相关阅读:
    [Codeup 25482]选美
    [Codeup 25481] swan
    暑假集训D12总结
    [技术]浅谈重载操作符
    2020年寒假第6次学*进度记录
    2020年寒假第5次学*进度记录
    2020年寒假第4次学*进度记录
    “家庭记账本”软件开发(1)
    阅读《梦断代码》随笔(1)
    2020年寒假第三次学*进度记录
  • 原文地址:https://www.cnblogs.com/maimai-d/p/12815689.html
Copyright © 2020-2023  润新知