降低圈复杂度的方法

一、方法概述

->提取函数(Extract Method)
    将重复的代码提取出来成为单独的函数。

->分解条件(Decompose Conditional)
    从判断分支中分别提取出独立函数。

->合并条件表达式(Consolidate Conditional Expression)
    将多个判断条件合并成一个函数。

->合并重复的条件片段(Consolidate Duplicate Conditional Fragments)
    如果每个判断分支都有同一段代码,将重复的代码移到条件判断之外。

->移除控制标记(Remove Control Flag)
    以break语句或return语句取代控制标记。

->表格驱动(Table drive)
    通过表格消除条件判断。

二、示例代码

示例代码的圈复杂度为20。

这个程序的功能是计算并打印出给定日期(年、月、日)是星期几。它基于一个已知的事实:1990年1月1日是星期一。程序通过计算从1990年1月1日到给定日期之间的总天数,然后利用这个总天数来确定给定日期是星期几。

2.1、源码weekday.c

#include <stdio.h>

/* 定义程序的主入口点 */
void main()
{
    /* 初始化变量 */
    int year, month, day, week, leap;
    int sum = 0;
    int i;

    /* 从用户输入中获取日期 */
    scanf("%d/%d/%d", &year, &month, &day);

    /* 计算从1990年到输入年份之间的天数 */
    for (i = 1990; i < year; i++)
    {
        /* 判断是否为闰年并累加天数 */
        if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
        {
            sum += 366;
        }
        else
        {
            sum += 365;
        }
    }

    /* 判断输入年份是否为闰年 */
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        leap = 1;
    }
    else
    {
        leap = 0;
    }

    /* 根据月份计算天数 */
    switch (month - 1)
    {
    case 11:
        sum += 30;
    case 10:
        sum += 31;
    case 9:
        sum += 30;
    case 8:
        sum += 31;
    case 7:
        sum += 31;
    case 6:
        sum += 30;
    case 5:
        sum += 31;
    case 4:
        sum += 30;
    case 3:
        sum += 31;
    case 2:
        sum += 28 + leap;
    case 1:
        sum += 31;
    }

    /* 累加天数得到总天数 */
    sum += day;
    /* 计算星期 */
    week = sum % 7;
    
    /* 根据计算结果输出星期 */
    if (week != 0)
    {
        printf("%d年%d月%d日是星期%d\n", year, month, day, week);
    }
    else
    {
        printf("%d年%d月%d日是星期日\n", year, month, day);
    }
}

2.2、查看圈复杂度

1、

sudo apt install python-pip

2、

sudo pip install lizard

3、

4、可以看到,代码的圈复杂度为20

三、优化后的代码

3.1、源码

#include <stdio.h>  
  
/* 1990年1月1日 是星期一 */  
int isLeapYear(int year);  
int daysInMonth(int year, int month) {  
    static const int daysPerMonth[2][12] = {  
        { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },  
        { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }  
    };  
    return daysPerMonth[isLeapYear(year)][month - 1];  
}  
  
int isLeapYear(int year) {  
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;  
}  
  
void printDayOfWeek(int year, int month, int day) {  
    int daysFromStart = 0;  
    int leap = isLeapYear(year);  
  
    // 计算从1990年到指定年份之前的天数  
    for (int i = 1990; i < year; i++) {  
        daysFromStart += isLeapYear(i) ? 366 : 365;  
    }  
  
    // 加上指定年份到指定月份之前的天数  
    for (int i = 1; i < month; i++) {  
        daysFromStart += daysInMonth(year, i);  
    }  
  
    // 加上指定月份的天数  
    daysFromStart += day;  
  
    // 计算是星期几  
    int week = (daysFromStart - 1) % 7 + 1; // 1990年1月1日是星期一,所以需要-1后取模  
  
    // 打印结果  
    printf("%d年%d月%d日是星期%d\n", year, month, day, week);  
}  
  
int main() {  
    int year, month, day;  
    scanf("%d/%d/%d", &year, &month, &day);  
    printDayOfWeek(year, month, day);  
    return 0;  
}

3.2、查看圈复杂度

可以看到,圈复杂度降低了,这里是采用提取函数(Extract Method)的方式实现的。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值