Избавиться от условных конструкций в C

Есть программа, которая принимает на вход дату рождения, а также текущую дату. Задание - определить следующие вещи:

  1. Родился ли человек в високосный год
  2. В год какого животного родился человек
  3. Какой знак зодиака у человека
  4. Сколько дней прожил человек с рождения

Мой код выглядит таким образом:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main()
{
  time_t timeA, timeB;
  struct tm tA, tB, *tptr;
  int difference;
  int year, month, date, currentYear, currentMonth, currentDate, yearNumber;
  char *lapYear;
  char *astroSign;
  const char *yearAnimals[12] = {"Pig", "Dog", "Rooster", "Monkey", "Sheep", "Horse", "Snake", "Dragon", "Rabbit", "Tiger", "Buffalo", "Rat"};
    
  printf("Enter your year, month and day of birth with space: "); scanf("%d%d%d", &year, &month, &date);
  printf("Enter the current date with space: "); scanf("%d%d%d", &currentYear, &currentMonth, &currentDate);

  yearNumber = abs((year - 2019) % 12);
    
  if (year % 4 == 0) {
    lapYear = "Yes";
  } else {
    lapYear = "No";
  }

  time(&timeA);
  time(&timeB);
  tptr = localtime(&timeA);
  tA = *tptr;
  tptr = localtime(&timeB);
  tB = *tptr;

  // today 
  tA.tm_mday = currentDate;
  tA.tm_mon = currentMonth;
  tA.tm_year = currentYear;
  // birth date
  tB.tm_mday = date;
  tB.tm_mon = month;
  tB.tm_year = year;
  timeA = mktime(&tA);
  timeB = mktime(&tB);
  difference = (int)(difftime(timeA, timeB) / 86400);
 
    if ((month == 1 && date < 20) || (month == 12 && date >= 22)) {
        astroSign = "Capricorn";
    }    
    else if ((month == 2 && date < 19)){
        astroSign = "Aquarius";
    }    
    else if((month == 3 && date < 21) || (month == 2 && date >= 19)) {
        astroSign = "Pisces";
    }
    else if ((month == 4 && date < 20) || (month == 3 && date >= 21)) {
        astroSign = "Aries";
    }    
    else if ((month == 5 && date < 21) || (month == 4 && date >= 20)) {
        astroSign = "Taurus";
    }    
    else if ((month == 6 && date < 21) || (month == 5 && date >= 21)) {
        astroSign = "Gemini";
    }    
    else if ((month == 7 && date < 23) || (month == 6 && date >= 21)) {
        astroSign = "Cancer";
    }    
    else if ((month == 8 && date < 23) || (month == 7 && date >= 23)) {
        astroSign = "Leo";
    }    
    else if ((month == 9 && date < 23) || (month == 8 && date >= 23)) {
        astroSign = "Virgo";
    }    
    else if ((month == 10 && date < 23) || (month == 9 && date >= 23)) {
        astroSign = "Libra";
    }    
    else if ((month == 11 && date < 22) || (month == 10 && date >= 23)) {
        astroSign = "Scorpio";
    }
    else if ((month == 12 && date < 22) || (month == 11 && date >= 22)) {
        astroSign = "Sagittarius";
    }  
  
  printf("You were born in a lap year: %s \n", lapYear);
  printf("Animal of your year: %s \n", yearAnimals[yearNumber]);
  printf ("You are %d days old\n", difference);
  printf ("Your astro sign is %s\n", astroSign);
}

Код работает без каких-либо ошибок, но есть несколько вопросов:

  1. Количество прожитых дней считается через библиотеку <time.h>. Как можно посчитать количество прожитых дней без нее, если надо учитывать, что года бывают високосные, а в месяцах разное количество дней?
  2. Можно ли определить знак зодиака не через множество if...else, а через какую-то более гибкую конструкцию?

Ответы (1 шт):

Автор решения: Алексей Р
  1. Разница между датами в днях
  2. См. вариант решения ниже (полностью не тестировал) + Определение знака зодиака по дате + Case20. Решебник Абрамяна М. Э.
#include <stdio.h>

int main ()
{
  int dates[] = { 0, 19, 18, 20, 19, 20, 21, 22, 22, 22, 22, 22, 21 };
  const char *names[] = { "Capricorn", "Aquarius", "Pisces", "Aries", "Taurus", "Gemini",
                        "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn"};

  int m = 9;
  int d = 24;

  printf ("Your astro sign is %s\n", names[(d > dates[m]) ? m : m-1]);
  return 0;
}
Your astro sign is Libra
→ Ссылка