SHEBI
SHEBI

Reputation: 1

Print a calendar by input character month and integer year

I've write the code to print the one month calendar by input of integer month and integer year. But I want to input the month by characters, first three letters of the month word like Jan for January and Feb For February.As Shown in the picture the month is entered by characters. Here is the Image. So please change the code, so I can input the month in character.Thanks

#include <stdio.h>

int isLeapYear(int y);        /* True if leap year */
int leapYears(int y);         /* The number of leap year */
int todayOf(int y, int m, int d); /* The number of days since the beginning
                                  of the year */
long days(int y, int m, int d);   /* Total number of days */
void calendar(int y, int m);       /* display calendar at m y */

int main(void) {
  int year, month;

  printf("Enter the month and year: ");
  scanf("%d %d", &month, &year);

  calendar(year, month);

  return 0;
}

int isLeapYear(int y) /* True if leap year */
{
  return(y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0));
}

int leapYears(int y) /* The number of leap year */
{
  return y / 4 - y / 100 + y / 400;
}

int todayOf(int y, int m, int d) /* The number of days since the beginning
                                 of the year */
{
  static int DayOfMonth[] =
  { -1/*dummy*/,0,31,59,90,120,151,181,212,243,273,304,334 };

  return DayOfMonth[m] + d + ((m>2 && isLeapYear(y)) ? 1 : 0);
}

long days(int y, int m, int d) /* Total number of days */
{
  int lastYear;

  lastYear = y - 1;

  return 365Q * lastYear + leapYears(lastYear) + todayOf(y, m, d);
}

void calendar(int y, int m) /* display calendar at m y */
{
  const char *NameOfMonth[] = { NULL/*dummp*/,
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  };
  char Week[] = "Su Mo Tu We Th Fr Sa";
  int DayOfMonth[] =
  { -1/*dummy*/,31,28,31,30,31,30,31,31,30,31,30,31 };
  int weekOfTopDay;
  int i, day;

  weekOfTopDay = days(y, m, 1) % 7;
  if (isLeapYear(y))
    DayOfMonth[2] = 29;
  printf("\n     %s %d\n%s\n", NameOfMonth[m], y, Week);

  for (i = 0; i<weekOfTopDay; i++)
    printf("   ");
  for (i = weekOfTopDay, day = 1; day <= DayOfMonth[m]; i++, day++) {
    printf("%2d ", day);
    if (i % 7 == 6)
      printf("\n");
  }
  printf("\n");
}

Upvotes: 0

Views: 264

Answers (1)

chux
chux

Reputation: 154280

There are many way to do this. They usually involve taking the input string and looking up in some table.

An efficient way is to compute a hash based on the string input rather than do up to 12 string compares. Use the hash to look that month name and see if it matches. The hash below requires ASCII encoding for the month names. char may be signed or unsigned.

Of course if the month names change (another language?), the specific values and hash method below need adjustment.

// Assume month is any 3 ASCII characters (either case)
int month2int_chux(const char *month) {
  if (month[0] && month[1] && month[2]) {
    unsigned m0 = month[0] | 0x20;
    unsigned m1 = month[1] | 0x20;
    unsigned m2 = month[2] | 0x20;
    unsigned m = (14 * m2) ^ (47 * m1);  // magic computation does not use m0.
    m %= 13;
    const unsigned char hash[] = { 9, 11, 5, 12, 0, 7, 2, 1, 3, 4, 8, 10, 6 };
    m = hash[m % 13u];
    if (m && (NameOfMonth[m][0] | 0x20) == m0 &&  
        NameOfMonth[m][1] == m1 && NameOfMonth[m][2] == m2) {
      return m;
    }
  }
  return 0;
}

Upvotes: 1

Related Questions