【问题标题】:Improving readability [closed]提高可读性[关闭]
【发布时间】:2022-01-22 23:21:50
【问题描述】:

我需要找到最小的日期(年、月、日、小时、分钟、秒),我的代码正在运行,但它看起来很糟糕而且很长。我能做些什么来避免这个阶梯使我的代码可读? (我只想使用 stdio.h )

#include <stdio.h>
typedef struct DateTime_s {
    int year , month , day ;
    int hours , minutes , seconds ;
} DateTime ;
void DataTime(const DateTime *mas , int x){
    int i;
    struct DateTime_s min={40000,400000,4000000,400000,400000,4000};
    for(i=0;i<x;i++){
        if(mas[i].year<min.year){
            min=mas[i];
        }
        else if(mas[i].year==min.year){
            if(mas[i].month<min.month){
                min=mas[i];
            }
            else if(mas[i].month==min.month){
                if(mas[i].day<min.day){
                    min=mas[i];
                }
                else if(mas[i].day==min.day){
                    if(mas[i].hours<min.hours){
                        min=mas[i];
                    }
                    else if(mas[i].hours==min.hours){
                        if(mas[i].minutes<min.minutes){
                            min=mas[i];
                        }
                        else if(mas[i].minutes==min.minutes){
                            if(mas[i].seconds<min.seconds){
                                min=mas[i];
                            }
                            else if(mas[i].seconds==min.seconds){
                                min=mas[i];
                            }
                        }
                    }
                }
            }
        }
    }
    printf("%d %d %d %d %d %d",min.year,min.month,min.day,min.hours,min.minutes,min.seconds);
}

int main() {
    int x,i;
    struct DateTime_s mas[50001];
    scanf("%d",&x);
    for(i=0;i<x;i++){
        struct DateTime_s b;
        scanf("%d %d %d %d %d %d",&b.year, &b.month,&b.day,&b.hours,&b.minutes,&b.seconds);
        mas[i]=b;
    }
    DataTime(mas,x);
    return 0;
}

【问题讨论】:

  • 如果您的代码工作正常,并且您正在寻找代码审查 cmets,请前往 Code Review
  • 将时间戳转换为纪元时间可能更有意义。这将花费额外的费用,但会将比较链减少为单次检查。但如果你还是要这样做......
  • 如果你使用一致的缩进,代码会更容易阅读。缩进每个else if 是不习惯的。
  • 我投票结束这个问题,因为它属于代码审查的 "migrated"
  • 放大 Lundin 的评论:首先要做的是为长 if/else 链的 N 个分支中的每一个使用 same 缩进级别。尽管这可以说是“不一致的”,但几乎每个人都同意这比让它无情地向右移动要好得多。

标签: c readability code-readability


【解决方案1】:

可以使用continue 来减少阶梯效果。但它是否提高了可读性是一个不同的问题......:

void DataTime(const DateTime* mas, int x) {
    int i;
    struct DateTime_s min = { 40000,400000,4000000,400000,400000,4000 };
    for (i = 0; i < x; i++) {
        if (mas[i].year < min.year) {
            min = mas[i];
            continue;
        }
        else if (mas[i].year > min.year) continue;
        if (mas[i].month < min.month) {
            min = mas[i];
            continue;
        }
        else if (mas[i].month > min.month) continue;
        if (mas[i].day < min.day) {
            min = mas[i];
            continue;
        }
        else if (mas[i].day == min.day) continue;
        if (mas[i].hours < min.hours) {
            min = mas[i];
            continue;
        }
        else if (mas[i].hours > min.hours) continue;
        if (mas[i].minutes < min.minutes) {
            min = mas[i];
            continue;
        }
        else if (mas[i].minutes > min.minutes) continue;
        if (mas[i].seconds <= min.seconds) {
            min = mas[i];
        }
    }
    printf("%d %d %d %d %d %d", min.year, min.month, min.day, min.hours, min.minutes, min.seconds);
}

【讨论】:

  • 哎呀。最好将比较移至函数。然后min = mas[i]; continue;变成return a;
【解决方案2】:

我建议将其拆分为两个功能。检查一个DateTime 是否小于另一个DateTime 以及循环的函数。

删除大量嵌套的ifs 也有助于提高可读性。

如果您还需要进行排序和搜索,这里有一个函数可以与sortbsearch 一起使用:

int compar(const void *Lhs, const void *Rhs) {
    const DateTime* lhs = Lhs;
    const DateTime* rhs = Rhs;
    if(lhs->year < rhs->year) return -1;
    if(lhs->year > rhs->year) return 1;
    if(lhs->month < rhs->month) return -1;
    if(lhs->month > rhs->month) return 1;
    if(lhs->day < rhs->day) return -1;
    if(lhs->day > rhs->day) return 1;
    if(lhs->hours < rhs->hours) return -1;
    if(lhs->hours > rhs->hours) return 1;
    if(lhs->minutes < rhs->minutes) return -1;
    if(lhs->minutes > rhs->minutes) return 1;
    if(lhs->seconds < rhs->seconds) return -1;
    if(lhs->seconds > rhs->seconds) return 1;
    return 0;
}

void DataTime(const DateTime mas[], int x) {
    struct DateTime_s min = mas[0];

    for(int i = 1; i < x; i++) {
        if(compar(&mas[i], &min) < 0) min = mas[i];
    }
    printf("%d %d %d %d %d %d", min.year, min.month, min.day, min.hours,
           min.minutes, min.seconds);
}

【讨论】:

  • 次要备注:如果您可以调整less 以使用返回类型int 和两个const void*,您也许可以将它与bsearch 一起使用而不是循环。不过,可能只有在有大量排序数据的情况下才有意义。
  • @TedLyngmo 我正要像 Lundin 一样发表评论;但仅限于 int 的返回类型。另外,我认为将!= 替换为&gt; 可能会更好一些,以反映您尽早退出的“不少于”条件。
  • @EdwinBuck const void* 参数是必要的。不幸的是,这会降低类型安全性。
  • @Lundin 我无法摆脱这个想法,所以我把它做成了可以与sortbsearch 一起使用的东西。
  • @Lundin 是的,它们是必要的;但是,我的 cmets 并没有考虑使用 bsearch,而是将 less 扩展为直接与 DateTimes 绑定的 compare 功能。如果您不关心使其兼容,则可以使用更强的类型绑定。
【解决方案3】:

提高可读性的最有效工具之一是函数!

DateTime *min_dt(const DateTime *a, const DateTime *b) {
    if ( a->year    != b->year    ) return (DateTime*)( a->year    < b->year    ? a : b );
    if ( a->month   != b->month   ) return (DateTime*)( a->month   < b->month   ? a : b );
    if ( a->day     != b->day     ) return (DateTime*)( a->day     < b->day     ? a : b );
    if ( a->hours   != b->hours   ) return (DateTime*)( a->hours   < b->hours   ? a : b );
    if ( a->minutes != b->minutes ) return (DateTime*)( a->minutes < b->minutes ? a : b );
    if ( a->seconds != b->seconds ) return (DateTime*)( a->seconds < b->seconds ? a : b );
    return a;
}

void DataTime(const DateTime *mas, size_t n) {
    if (n == 0)
        return;  // Or whatever

    const DateTime *min = &mas[0];

    for (size_t i=1; i<n; ++i)
        min = min_dt(min, &mas[i]);

    printf("%d %d %d %d %d %d",
        min->year, min->month, min->day,
        min->hours, min->minutes, min->seconds
    );
}

不幸的是,const 的删除使这条线有点长。但是函数需要同时使用指向常量的指针和指向非常量的指针。这个问题可以通过返回一个布尔值来避免。

【讨论】:

  • 最后一次检查,还需要检查if ( a-&gt;seconds != b-&gt;seconds )吗?如果它通过minute 过滤器,如果我没有完全关闭,你可以只使用return (DateTime*)( a-&gt;seconds &lt; b-&gt;seconds ? a : b );
  • @Ted Lyngmo,我知道。我追求统一 :) 我希望优化器能解决这个问题。
【解决方案4】:
/**
 * Compares to DateTimes.
 *
 * @return -1 when the first is earlier
 *          0 when they are equal
 *          1 when the seconde is earlier
 */
int DateTime_compare(const DateTime* lhs, const DateTime* rhs) {
    if (lhs->year < rhs->year) return -1;
    if (lhs->year > rhs->year) return 1;
    if (lhs->month < rhs->month) return -1;
    if (lhs->month > rhs->month) return 1;
    if (lhs->day < rhs->day) return -1;
    if (lhs->day > rhs->day) return 1;
    if (lhs->hours < rhs->hours) return -1;
    if (lhs->hours > rhs->hours) return 1;
    if (lhs->minutes < rhs->minutes) return -1;
    if (lhs->minutes > rhs->minutes) return 1;
    if (lhs->seconds < rhs->seconds) return -1;
    if (lhs->seconde > rhs->seconds) return 1;
    return 0;
}

/** Find the minimum */
void DataTime(const DateTime mas[], int x) {
    struct DateTime_s min = {40000, 400000, 4000000, 400000, 400000, 4000};

    for (int i = 0; i < x; i++) { 
        min = (DateTime_compare( &mas[i], &min ) < 0) ? mas[i] : min;
    }
    printf("%d %d %d %d %d %d", min.year, min.month, min.day, min.hours,
           min.minutes, min.seconds);
}

【讨论】:

    【解决方案5】:

    您可以转换为浮动类型:

    double min_fltime = 99999.9*9999999, fltime;
    int i, xmin;
    
    for(i=0;i<x;i++){
        fltime = mas[i].seconds
               + mas[i].minutes *                60
               + mas[i].hours *                3600
               + mas[i].day *               24*3600
               + mas[i].month *      365.25*24*3600
               + mas[i].year *   12* 365.25*24*3600;
    
        if (fltime < min_fltime) {
            min_fltime = fltime;
            xmin = i;
    
        }
        #define M mas[i]
        printf("%d %d %d %d %d %d %f\n",M.year,M.month,M.day,M.hours,M.minutes,M.seconds, fltime);
    }
    #define MM mas[xmin]
    printf("min\n%d %d %d %d %d %d  %f", MM.year,MM.month,MM.day,MM.hours,MM.minutes,MM.seconds, min_fltime);
    

    fltime 赋值应该是一个函数,并且从第一个日期开始。

    输出:

    1999 12 31 12 45 7 757385124307.000000
    999 6 17 10 59 59 378503362799.000000
    999 6 18 10 59 59 378503449199.000000
    999 6 17 10 59 58 378503362798.000000
    min
    999 6 17 10 59 58  378503362798.000000
    

    对于该地区的有效日期,它似乎有效。

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 2013-08-30
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多