Calendar - for "REAL" programmers: Difference between revisions
Content added Content deleted
(→{{header|Visual Basic .NET}}: Added VB.NET) |
(Added a C versoin) |
||
Line 651: | Line 651: | ||
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 |
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 |
||
31 30</pre> |
31 30</pre> |
||
=={{header|C}}== |
|||
Upper-case C version of the C Calendar task. Relies on the ability of most C compilers to specify #defines on the command line and declares the putchar function to avoid needing any #includes. E.g. for tcc: |
|||
<pre> |
|||
tcc -DSTRUCT=struct -DCONST=const -DINT=int -DCHAR=char -DVOID=void -DMAIN=main -DIF=if -DELSE=else -DWHILE=while -DFOR=for -DDO=do -DBREAK=break -DRETURN=return -DPUTCHAR=putchar UCCALENDAR.c |
|||
</pre> |
|||
<lang c>/* UPPER CASE ONLY VERSION OF THE ORIGINAL CALENDAR.C, CHANGES MOSTLY TO AVOID NEEDING #INCLUDES */ |
|||
/* ERROR MESSAGES GO TO STDOUT TO SLIGHTLY SIMPLIFY THE I/O HANDLING */ |
|||
/* WHEN COMPILING THIS, THE COMMAND LINE SHOULD SPECIFY -D OPTIONS FOR THE FOLLOWING WORDS: */ |
|||
/* STRUCT, VOID, INT, CHAR, CONST, MAIN, IF, ELSE, WHILE, FOR, DO, BREAK, RETURN, PUTCHAR */ |
|||
/* THE VALUE OF EACH MACRO SHOULD BE THE WORD IN LOWER-CASE */ |
|||
INT PUTCHAR(INT); |
|||
INT WIDTH = 80, YEAR = 1969; |
|||
INT COLS, LEAD, GAP; |
|||
CONST CHAR *WDAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" }; |
|||
STRUCT MONTHS { |
|||
CONST CHAR *NAME; |
|||
INT DAYS, START_WDAY, AT; |
|||
} MONTHS[12] = { |
|||
{ "JANUARY", 31, 0, 0 }, |
|||
{ "FEBRUARY", 28, 0, 0 }, |
|||
{ "MARCH", 31, 0, 0 }, |
|||
{ "APRIL", 30, 0, 0 }, |
|||
{ "MAY", 31, 0, 0 }, |
|||
{ "JUNE", 30, 0, 0 }, |
|||
{ "JULY", 31, 0, 0 }, |
|||
{ "AUGUST", 31, 0, 0 }, |
|||
{ "SEPTEMBER", 30, 0, 0 }, |
|||
{ "OCTOBER", 31, 0, 0 }, |
|||
{ "NOVEMBER", 30, 0, 0 }, |
|||
{ "DECEMBER", 31, 0, 0 } |
|||
}; |
|||
VOID SPACE(INT N) { WHILE (N-- > 0) PUTCHAR(' '); } |
|||
VOID PRINT(CONST CHAR * S){ WHILE (*S != '\0') { PUTCHAR(*S++); } } |
|||
INT STRLEN(CONST CHAR * S) |
|||
{ |
|||
INT L = 0; |
|||
WHILE (*S++ != '\0') { L ++; }; |
|||
RETURN L; |
|||
} |
|||
INT ATOI(CONST CHAR * S) |
|||
{ |
|||
INT I = 0; |
|||
INT SIGN = 1; |
|||
CHAR C; |
|||
WHILE ((C = *S++) != '\0') { |
|||
IF (C == '-') |
|||
SIGN *= -1; |
|||
ELSE { |
|||
I *= 10; |
|||
I += (C - '0'); |
|||
} |
|||
} |
|||
RETURN I * SIGN; |
|||
} |
|||
VOID INIT_MONTHS(VOID) |
|||
{ |
|||
INT I; |
|||
IF ((!(YEAR % 4) && (YEAR % 100)) || !(YEAR % 400)) |
|||
MONTHS[1].DAYS = 29; |
|||
YEAR--; |
|||
MONTHS[0].START_WDAY |
|||
= (YEAR * 365 + YEAR/4 - YEAR/100 + YEAR/400 + 1) % 7; |
|||
FOR (I = 1; I < 12; I++) |
|||
MONTHS[I].START_WDAY = |
|||
(MONTHS[I-1].START_WDAY + MONTHS[I-1].DAYS) % 7; |
|||
COLS = (WIDTH + 2) / 22; |
|||
WHILE (12 % COLS) COLS--; |
|||
GAP = COLS - 1 ? (WIDTH - 20 * COLS) / (COLS - 1) : 0; |
|||
IF (GAP > 4) GAP = 4; |
|||
LEAD = (WIDTH - (20 + GAP) * COLS + GAP + 1) / 2; |
|||
YEAR++; |
|||
} |
|||
VOID PRINT_ROW(INT ROW) |
|||
{ |
|||
INT C, I, FROM = ROW * COLS, TO = FROM + COLS; |
|||
SPACE(LEAD); |
|||
FOR (C = FROM; C < TO; C++) { |
|||
I = STRLEN(MONTHS[C].NAME); |
|||
SPACE((20 - I)/2); |
|||
PRINT(MONTHS[C].NAME); |
|||
SPACE(20 - I - (20 - I)/2 + ((C == TO - 1) ? 0 : GAP)); |
|||
} |
|||
PUTCHAR('\012'); |
|||
SPACE(LEAD); |
|||
FOR (C = FROM; C < TO; C++) { |
|||
FOR (I = 0; I < 7; I++) { |
|||
PRINT(WDAYS[I]); |
|||
PRINT(I == 6 ? "" : " "); |
|||
} |
|||
IF (C < TO - 1) SPACE(GAP); |
|||
ELSE PUTCHAR('\012'); |
|||
} |
|||
WHILE (1) { |
|||
FOR (C = FROM; C < TO; C++) |
|||
IF (MONTHS[C].AT < MONTHS[C].DAYS) BREAK; |
|||
IF (C == TO) BREAK; |
|||
SPACE(LEAD); |
|||
FOR (C = FROM; C < TO; C++) { |
|||
FOR (I = 0; I < MONTHS[C].START_WDAY; I++) SPACE(3); |
|||
WHILE(I++ < 7 && MONTHS[C].AT < MONTHS[C].DAYS) { |
|||
INT MM = ++MONTHS[C].AT; |
|||
PUTCHAR((MM < 10) ? ' ' : '0' + (MM /10)); |
|||
PUTCHAR('0' + (MM %10)); |
|||
IF (I < 7 || C < TO - 1) PUTCHAR(' '); |
|||
} |
|||
WHILE (I++ <= 7 && C < TO - 1) SPACE(3); |
|||
IF (C < TO - 1) SPACE(GAP - 1); |
|||
MONTHS[C].START_WDAY = 0; |
|||
} |
|||
PUTCHAR('\012'); |
|||
} |
|||
PUTCHAR('\012'); |
|||
} |
|||
VOID PRINT_YEAR(VOID) |
|||
{ |
|||
INT Y = YEAR; |
|||
INT ROW; |
|||
CHAR BUF[32]; |
|||
CHAR * B = &(BUF[31]); |
|||
*B-- = '\0'; |
|||
DO { |
|||
*B-- = '0' + (Y % 10); |
|||
Y /= 10; |
|||
} WHILE (Y > 0); |
|||
B++; |
|||
SPACE((WIDTH - STRLEN(B)) / 2); |
|||
PRINT(B);PUTCHAR('\012');PUTCHAR('\012'); |
|||
FOR (ROW = 0; ROW * COLS < 12; ROW++) |
|||
PRINT_ROW(ROW); |
|||
} |
|||
INT MAIN(INT C, CHAR **V) |
|||
{ |
|||
INT I, YEAR_SET = 0, RESULT = 0; |
|||
FOR (I = 1; I < C && RESULT == 0; I++) { |
|||
IF (V[I][0] == '-' && V[I][1] == 'W' && V[I][2] == '\0') { |
|||
IF (++I == C || (WIDTH = ATOI(V[I])) < 20) |
|||
RESULT = 1; |
|||
} ELSE IF (!YEAR_SET) { |
|||
YEAR = ATOI(V[I]); |
|||
IF (YEAR <= 0) |
|||
YEAR = 1969; |
|||
YEAR_SET = 1; |
|||
} ELSE |
|||
RESULT = 1; |
|||
} |
|||
IF (RESULT == 0) { |
|||
INIT_MONTHS(); |
|||
PRINT_YEAR(); |
|||
} ELSE { |
|||
PRINT("BAD ARGS\012USAGE: "); |
|||
PRINT(V[0]); |
|||
PRINT(" YEAR [-W WIDTH (>= 20)]\012"); |
|||
} |
|||
RETURN RESULT; |
|||
}</lang> |
|||
=={{header|COBOL}}== |
=={{header|COBOL}}== |