Workshop solution week 2

This commit is contained in:
Peter 2021-08-09 17:20:19 +08:00
parent b418e749af
commit b372fafd93
4 changed files with 193 additions and 0 deletions

22
Week 2-workshop/README.md Normal file
View File

@ -0,0 +1,22 @@
## Workshop 1 content
Workshop content: https://web.archive.org/web/20210809074913/https://teaching.csse.uwa.edu.au/units/CITS2002/workshops/workshop2.php\
`first_day_of_month.c`: https://web.archive.org/web/20210809075040/https://teaching.csse.uwa.edu.au/units/CITS2002/workshops/first_day_of_month.c
EXTRA WORK
* There's some required information that we haven't yet covered in lectures (information we can get from our computer's operating system). Try to identify that extra information.
* Consider the file first_day_of_month.c whose function determines the first day (Sun, Mon, ...) of a requested month. Identify the functions that are used to determine this information, and read their documentation for your system.
* We know that Linux utility programs can receive optional command-line arguments to specify actions beyond their default actions. In the case of the cal utility, if two (optional) arguments are provided, we are specifying the required month and year to be printed.
* Assuming we receive the additional two command-line arguments, which the C program receives as character strings, we can 'convert' their string representations of integers to integer values using the standard atoi() function.
* Extend your program to detect optional command-line arguments, and to print the requested calendar.
* 🌶 And how could we support left-handers?
* 🌶 🌶 Wow! What happened in September 1752? (which you don't have to deal with!) :
```
prompt> cal 9 1752
September 1752
Su Mo Tu We Th Fr Sa
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
```

110
Week 2-workshop/cal.c Normal file
View File

@ -0,0 +1,110 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include "first_day_of_month.c"
#include "year_utils.c"
#define WEEK_LENGTH 7
// Adds padding so it's centered.
void printHeader(int month, int year) {
int len = strlen(MONTH_NAME[month-1]) + 5; // Let's assume the year length is 4.
int lPad = (3*WEEK_LENGTH - len)/2;
printf("%*s %d\n", 12, MONTH_NAME[month-1], year);
}
static bool LEFT_HAND = false;
int leftIdx(int i) {
switch (LEFT_HAND)
{
case true:
return 6-i;
default:
return i;
}
}
void printCal(int month, int year) {
printHeader(month, year);
for (int i = 0; i < WEEK_LENGTH; i++)
{
printf("%s ", DAY_NAME[leftIdx(i)]);
}
printf("\n");
// Original solution just printed but easier to use
// 2d array for left hand mode.
int limit = monthLimit(month, year);
int week[WEEK_LENGTH] = {0};
int idx = first_day_of_month(month, year);
int day_ = 1;
for (int i = 1; i < 6; i++)
{
while (idx < WEEK_LENGTH)
{
if (day_ > limit) {
break;
}
week[idx] = day_;
day_++;
idx++;
}
// print row
idx = 0;
for (int j = 0; j < WEEK_LENGTH; j++)
{
int d = week[leftIdx(j)];
switch (d)
{
case 0:
printf(" ");
break;
default:
printf("%-3d", d);
break;
}
}
memset(week, 0, sizeof week); // clear int array
printf("\n");
}
printf("\n");
}
int main(int argc, char const *argv[])
{
int year = 1;
int month = 1;
switch (argc)
{
case 0:
case 1:
{
struct tm tm = getCurrentTime();
year = tm.tm_year+1900;
month = tm.tm_mon+1;
}
break;
case 4:
LEFT_HAND = (strcmp(argv[3], "true") == 0);
case 3:
year = atoi(argv[1]);
month = atoi(argv[2]);
if (month >= 1 && month <= 12 && year >= 1) {
break;
}
default:
printf("Incorrect arguments - expected no arguments or two arguments\ncal year month\ncal year month lefthanded_mode(true|false)\n");
exit(EXIT_FAILURE);
break;
}
printCal(month, year);
exit(EXIT_SUCCESS);
return 0;
}

View File

@ -0,0 +1,28 @@
#include <time.h>
#include <string.h>
// written by Chris.McDonald@uwa.edu.au
// PROVIDED WITHOUT MUCH EXPLANATION YET!
// RETURNS 0=Sun, 1=Mon, .....
//
int first_day_of_month(int month, int year)
{
struct tm tm;
// SET ALL FIELDS OF tm TO ZERO TO MAKE SOME FIELDS 'UNKNOWN'
memset(&tm, 0, sizeof(tm));
// INITIALIZE THE FILEDS THAT WE ALREADY KNOW
tm.tm_mday = 1;
tm.tm_mon = month-1; // 0=Jan, 1=Feb, ....
tm.tm_year = year-1900;
// ASK THE POSIX FUNCTION mktime TO DETERMINE THE 'UNKNOWN' FIELDS
// See: http://pubs.opengroup.org/onlinepubs/9699919799/
mktime(&tm);
// RETURN THE INTEGER MONTH VALUE
return tm.tm_wday; // 0=Sun, 1=Mon, .....
}

View File

@ -0,0 +1,33 @@
#include <time.h>
#include <stdbool.h>
static char *DAY_NAME[] = {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"};
static char *MONTH_NAME[] = {
"January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December"
};
bool isLeapYear(int year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
int monthLimit(int month, int year)
{
bool leapYear = isLeapYear(year);
switch (month)
{
case 2:
return 28 + leapYear;
default:
return 31 - (month - 1) % 7 % 2;
}
}
struct tm getCurrentTime() {
time_t t = time(NULL);
struct tm tm = *localtime(&t);
return tm;
}