C :: Aufgabe #91
1 Lösung
BashCal - grafischer Konsolenkalender
Anfänger - C
von Michi
- 07.09.2015 um 14:34 Uhr
Schreiben Sie ein Programm das einen simplen Kalender grafisch in der Konsole darstellt.
Folgende Befehle mit Parametern sollen zur Verfügung stehen
- cal -m -> bestimmten Monat aus dem aktuellen Jahr anzeigen
- cal -y -> alle Kalender für ausgewähltes Jahr anzeigen
- cal -my -> bestimmten Monat aus bestimmten Jahr anzeigen
Beispiel:
"cal -m 2" zeigt den Kalender Februar des aktuellen Jahres
"cal -y 2013" zeigt alle Monate von Januar bis Dezember des Jahres 2013
"cal -my 2 2011" zeigt den Kalender Februar des Jahres 2011
Im Anhang befindet sich ein Beispiel der möglichen grafischen Ausgabe in der Konsole.
Folgende Befehle mit Parametern sollen zur Verfügung stehen
- cal -m -> bestimmten Monat aus dem aktuellen Jahr anzeigen
- cal -y -> alle Kalender für ausgewähltes Jahr anzeigen
- cal -my -> bestimmten Monat aus bestimmten Jahr anzeigen
Beispiel:
"cal -m 2" zeigt den Kalender Februar des aktuellen Jahres
"cal -y 2013" zeigt alle Monate von Januar bis Dezember des Jahres 2013
"cal -my 2 2011" zeigt den Kalender Februar des Jahres 2011
Im Anhang befindet sich ein Beispiel der möglichen grafischen Ausgabe in der Konsole.
Lösungen:
Konsolenausgabe:
$ ./cal -my 9 2015
September 2015
So Mo Di Mi Do Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
/**************************
* cal.c Kalender
**************************/
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <time.h>
#define LOCALE "de_DE.UTF-8"
#define ARG_ERR_1 "Parameter Monat und Jahr erforderlich"
#define ARG_ERR_2 "Optionen -m und -y erforderlich"
#define ARG_ERR_3 "Ungültiger Monat"
#define ARG_ERR_4 "Ungültiges Jahr"
typedef enum _date_part {MONTH, YEAR} date_part_t;
typedef enum _direction {LEFT, DOWN, UP} direction_t;
/**************
* Funktionen
**************/
/* Hilfe */
void usage_ex(int exit_code) {
fprintf( stderr, "Usage: cal [-my] [[month] year]\n" );
exit(exit_code);
}
/* Cursor verschieben mit ANSI Escape Sequenzen */
void move_cur(direction_t dir, int steps) {
char strmv[10];
switch (dir) {
case LEFT: sprintf(strmv, "\033[%dC", steps); break;
case DOWN: sprintf(strmv, "\033[%dB", steps); break;
case UP: sprintf(strmv, "\033[%dA", steps); break;
}
printf("%s", strmv);
}
/* Schaltjahr-Test */
int is_leapyear(int year) {
return (((year%4==0) && (year%100!=0)) || (year%400==0));
}
/* Anzahl Tage im Monat ermitteln */
int get_days_per_month(int month, int year) {
switch (month) {
case 2:
return (is_leapyear(year))?29:28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
/* Wert (num.) fuer aktuellen Monat oder Jahr */
int get_current_date(date_part_t dp) {
struct tm *tm;
time_t t;
t = time(NULL);
if ((tm = localtime(&t)) != NULL)
switch(dp) {
case MONTH: return tm->tm_mon+1;
case YEAR: return tm->tm_year+1900;
}
return -1;
}
/* erster Wochentag im Monat (0=Sonntag) */
int get_first_day_in_month(int month, int year) {
char sdate[12];
struct tm tm;
memset(&tm, 0, sizeof(struct tm));
sprintf(sdate, "%d-%d-01", year, month);
strptime(sdate, "%Y-%m-%d", &tm);
return tm.tm_wday;
}
/* voller Name des Monats */
char * get_name_of_month(int month) {
static char smonth[10];
char sdate[12];
struct tm tm;
memset(&tm, 0, sizeof(struct tm));
sprintf(sdate, "2000-%d-01", month);
strptime(sdate, "%Y-%m-%d", &tm);
strftime(smonth, 10, "%B", &tm);
return smonth;
}
/* Monatskalender ausgeben */
int print_calendar_month(int month, int year, int column, int print_year) {
char header[16];
int day, day1, maxday;
int col, row, ind;
/* Monatsname + Jahr(optional) zentriert */
if (print_year)
sprintf(header, "%s %d", get_name_of_month(month), year);
else
sprintf(header, "%s", get_name_of_month(month));
ind = (20-strlen(header))/2;
move_cur(LEFT, column+ind);
printf("%s\n", header);
move_cur(LEFT, column);
printf("So Mo Di Mi Do Fr Sa\n");
row=3;
/* Einrueckung 1. Zeile */
move_cur(LEFT, column);
day1 = get_first_day_in_month(month, year);
for (day=0; day<day1; day++)
printf(" ");
/* Ausgabe der Tage */
maxday = get_days_per_month(month, year);
col = day1;
for (day=1; day<=maxday; day++) {
printf("%2d ", day);
if (++col % 7 == 0) {
printf("\n");
move_cur(LEFT, column);
row++;
}
}
printf("\n");
return row;
}
/* Jahreskalender ausgeben */
void print_calendar_year(int year) {
int month, qmonth, quart;
int colmn, rows;
/* Jahrszahl zentriert */
printf("%33d\n", year);
/* Monatskalender in 3x4 Matrix (Quartale) anordnen */
for (quart=0; quart<4; quart++) {
for (qmonth=0; qmonth<3; qmonth++) {
month = quart*3 + qmonth + 1;
colmn = qmonth*22 + 1;
rows = print_calendar_month(month, year, colmn, 0);
move_cur(UP, rows);
}
move_cur(DOWN, 11);
printf("\n");
}
}
/*********
* main
*********/
int main( int argc, char **argv )
{
int opt_month = 0;
int opt_year = 0;
int month = -1;
int year = -1;
int opt;
/* lokale Zeitumgebung setzen (LC_TIME) */
if ((setlocale(LC_TIME, LOCALE)) == NULL) {
fprintf(stderr, "Kann lokale Umgebung (LC_TIME) nicht setzen\n");
exit(EXIT_FAILURE);
}
/* Check Optionen */
while ((opt = getopt(argc, argv, "myh")) != -1) {
switch(opt) {
case 'm' : opt_month=1; break;
case 'y' : opt_year=1; break;
case 'h' : usage_ex(EXIT_SUCCESS); break;
default : usage_ex(EXIT_FAILURE);
}
}
/* Check Parameter: Monat und/oder Jahr */
switch (argc-optind) {
case 0:
month = get_current_date(MONTH);
year = get_current_date(YEAR);
break;
case 1:
if (opt_month && opt_year) {
fprintf(stderr, "%s\n", ARG_ERR_1);
exit(EXIT_FAILURE);
}
if (opt_month) {
month = atoi(argv[optind]);
year = get_current_date(YEAR);
} else
year = atoi(argv[optind]);
break;
case 2:
if (opt_month ^ opt_year) {
fprintf(stderr, "%s\n", ARG_ERR_2);
exit(EXIT_FAILURE);
}
month = atoi(argv[optind]);
year = atoi(argv[optind+1]);
break;
}
/* Werte pruefen */
if (month == 0 || month > 12) {
fprintf(stderr, "%s\n", ARG_ERR_3);
exit(EXIT_FAILURE);
}
if (year < 1900 || year > 2099) {
fprintf(stderr, "%s\n", ARG_ERR_4);
exit(EXIT_FAILURE);
}
/* Kalender-Ausgabe */
if (month < 0)
print_calendar_year(year);
else
print_calendar_month(month, year, 1, 1);
return 0;
}
