这是我在这个论坛上的第一篇帖子。我已经阅读了指南,并将努力遵守它们,但如果我错过了什么,我道歉。我发布的代码意在复制XV6操作系统中"date -u“的输出。它做到了这一点,除了17世纪之前的日期(这与任务无关,而且数学与我所读到的有点不同)。我在这篇文章中的目标是寻求关于在安全性和性能方面改进代码的建议,重点放在我可以概括到未来C代码的最佳实践上(我意识到,对于打算在XV6中运行的代码来说,这可能不那么可行)。关于我的代码和更好的技术张贴在这里的建议是值得赞赏的!
#include "types.h"
#include "stat.h"
#include "user.h"
#include "date.h"
int check_leap(int year);
void print_day(int year, int month, int day);
void print_month(int month);
int month_key(int month);
int
main(void)
{
struct rtcdate current_date;
if(date(¤t_date) != 0)
exit();
print_day(current_date.year, current_date.month, current_date.day);
print_month(current_date.month);
printf(1, " %d",current_date.day);
printf(1," %d:%d:%d", current_date.hour, current_date.minute, current_date.second);
printf(1," %d", current_date.year);
printf(1," UTC\n");
exit();
}
int
check_leap(int year)
{
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
return 1; //Leap year
}
}
return 0;
}
int
month_key(int month)
{
int key;
switch (month)
{
case 1: key = 1;
break;
case 2: key = 4;
break;
case 3: key = 4;
break;
case 4: key = 0;
break;
case 5: key = 2;
break;
case 6: key = 5;
break;
case 7: key = 0;
break;
case 8: key = 3;
break;
case 9: key = 6;
break;
case 10: key = 1;
break;
case 11: key = 4;
break;
case 12: key = 6;
break;
default: key = -1;
break;
}
return key;
}
void
print_day(int year, int month, int day)
{
int week_day;
int decade = year % 100;
int century = year / 100;
int leap = check_leap(year);
int key = month_key(month);
if(key < 0)
{
printf(1, "%s", "Invalid value for month!\n");
exit();
}
week_day = decade / 4;
week_day += day;
week_day += key;
if((leap) && ((month == 1) || (month == 2)))
{
week_day -= 1;
}
switch (century)
{
case 17: week_day += 4;
break;
case 18: week_day += 2;
break;
case 19: break;
case 20: week_day += 6;
break;
default: printf(1, "%s", "Centuries before 1700 or after 2000 not yet supported. \n");
break;
}
week_day += decade;
week_day = (week_day % 7) - 1;
if(week_day < 0 || week_day > 6)
{
printf(1, "Invalid Day error!"); //TS code- to be removed
}
switch(week_day)
{
case 0: printf(1, "Sun ");
break;
case 1: printf(1, "Mon ");
break;
case 2: printf(1, "Tue ");
break;
case 3: printf(1, "Wed ");
break;
case 4: printf(1, "Thu ");
break;
case 5: printf(1, "Fri ");
break;
case 6: printf(1, "Sat ");
break;
default: printf(1, "Unknown day!");
break;
}
return;
}
void
print_month(int month)
{
switch (month)
{
case 1: printf(1, "Jan");
break;
case 2: printf(1, "Feb");
break;
case 3: printf(1, "Mar");
break;
case 4: printf(1, "Apr");
break;
case 5: printf(1, "May");
break;
case 6: printf(1, "Jun");
break;
case 7: printf(1, "Jul");
break;
case 8: printf(1, "Aug");
break;
case 9: printf(1, "Sep");
break;
case 10: printf(1, "Oct");
break;
case 11: printf(1, "Nov");
break;
case 12: printf(1, "Dec");
break;
default: printf(1, "Month Error");
break;
}
return;
}发布于 2021-03-30 19:25:27
XV6至少做出了一项不明智的决定,强制使用非标准的printf签名,该签名要求传入文件描述符。也许他们应该完全省略printf,让您使用fprintf,但是无论如何:至少您应该使一个stdout常量等于1,并使用它而不是数字文字。
实际上,您可以在一个将XV6 6到C99转换集中的头文件中使#define shims,包括fprintf的定义,您可以像标准版本那样调用该定义,但实际上在内部调用XV6 printf。如果你在一个非标准C的课程,但你仍然想学习标准C,这将是一个明智的选择。
另外,从main返回不起作用吗?如果是这样的话,return而不是exit()。
在执行了边界检查之后,将这个长的、连续的switch重新表示为一个索引到其中的static const查找数组。对于您的switch (week_day)和switch (month)来说也是可能的。
https://codereview.stackexchange.com/questions/258806
复制相似问题