Трабл с календарем домашних заданий в т - PullRequest
0 голосов
/ 07 декабря 2009

Я пишу программу, которая получает month и year от пользователя, а затем распечатывает календарь. Но календарь верен только в январе (каждые два года).

Как мне исправить остальные месяцы? Что я делаю не так?

#include "stdafx.h"

void printMonth (int* startDay, int* days);

int _tmain(int argc, _TCHAR* argv[])
{

    int startDay, days, year, month, a;

    printf("enter year: ");
    scanf("%d", &year);
    printf("enter month: ");
    scanf("%d", &month);

    a = year - 1;
    startDay = ((a * 365) + (a / 4) - (a / 100) + (a / 400) + 1) % 7;

    switch (month)
    {
    case 1: days = 31;
        break;
    case 2: days = 28;
        break;
    case 3: days = 31;
        break;
    case 4: days = 30;
        break;
    case 5: days = 31;
        break;
    case 6: days = 30;
        break;
    case 7: days = 31;
        break;
    case 8: days = 31;
        break;
    case 9: days = 30;
        break;
    case 10: days = 31;
        break;
    case 11: days = 30;
        break;
    case 12: days = 31;
        break;
    }

    printMonth (&startDay, &days);

    printf("\nstart day: %d\n", startDay);
    printf("\na: %d\n", a);

    return 0;
}

void printMonth (int* startDay, int* days)
{
    int weekDay;

    printf("Sun Mon Tue Wed Thu Fri Sat\n");
    printf("--- --- --- --- --- --- ---\n");

    for (weekDay = 0; weekDay < *startDay; weekDay++)
        printf("    ");

    for (int dayCount = 1; dayCount <= *days; dayCount++)
    {
        if (weekDay > 6)
        {
            printf("\n");
            weekDay = 1;
        }
        else
            weekDay++;
        printf("%3d ", dayCount);
    }

printf("\n--- --- --- --- --- --- ---\n");

return;
}

Ответы [ 5 ]

3 голосов
/ 07 декабря 2009

1) Инициализируйте все ваши переменные.

int startDay, days, year, month, a;
startDay = -1;
days = -1;

В этом случае «-1» или «0» выражают значение, которое по-прежнему не имеет реального контента, предоставленного пользователем. В других случаях вы можете инициализировать «правдоподобное» действительное значение по умолчанию. Это помогает отладке. Очень некрасиво проверять значения отладки, которые являются тем мусором, который был там, когда вы создавали свою переменную.

Я не помню, позволяет ли C сделать это в одну строку, как C ++. Так или иначе, сделать инициализировать их.

2) Проверьте и подтвердите ввод пользователя.

printf("enter year: ");
scanf("%d", &year);
// Check validity of year here. If year not valid, ask again, abort, or anything.

3) Подтвердите логику вашего кода с помощью утверждений (не делайте этого, конечно, для проверки ввода пользователя; см. 2).

assert(month >= 1);
assert(month <= 12);
switch (month)
{ // ...

void printMonth (int startDay, int days)
{
    assert(startDay >= 1);
    assert(startDay <= 31);
    assert(days >= 0);
    // ...

Перепроверьте, что вы на самом деле находитесь в режиме отладки и что неудачные утверждения что-то делают вообще. Для одного исполнения просто напишите assert(0); (я не знаю, есть ли у вас логические значения в C). Это должно провалиться.

4) Делать разные вещи в разных функциях. Запрашивать у пользователя месяц и делать с ним что-нибудь «сложное» позже - это запах кода.

2 голосов
/ 07 декабря 2009

Ваш звонок на printMonth явно проходит день начала января, а не день начала этого месяца.

1 голос
/ 07 декабря 2009

Вы передаете одно и то же значение для startDay на printMonth() независимо от того, какой месяц введен. Подумайте, сколько дней прошло с начала года до начала данного месяца, и из этого вы можете выяснить, с какого дня начинается данный месяц.

Обратите внимание, что вы также не учитываете тот факт, что в феврале может быть 29 дней, если это високосный год. Является ли это високосным годом или нет, важно, потому что продолжительность февраля влияет на то, с какого дня начинаются остальные месяцы.

Год - это високосный год, если он делится на 4 равномерно (2008, 2012 - високосные годы) и не делится на 100 (1900 не является високосным годом) , если не делится на 400 (2000 год високосный). Поэтому:

leap_year = (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))
1 голос
/ 07 декабря 2009

startDay - это день недели первого дня года. Вам необходимо пройти день недели первого дня месяца.

Рассмотрите возможность изменения вашего оператора switch в массив. Рассчитайте февраль на основе високосного года, остальные могут быть назначены статически. Затем вы можете просмотреть циклы суммирования длин, чтобы выяснить, сколько дней в году вам нужно начать, и добавить это в вычисление startDay перед модулем 7, и вы можете передать число дней в году индексирование в массив.

Имейте в виду, что массивы C основаны на 0. Вам также следует проверить правильность ввода пользователя.

Если вы не знакомы с этим, в * NIX системах есть команда cal, которая может помочь вам проверить правильность вашего вывода, но имейте в виду: в происходят странные вещи история календарей .

0 голосов
/ 07 декабря 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...