2014-02-13 1 views
2

Предполагается, что программа вернет, какой день недели для введенной даты. Одна из дат, которая не работает, - 01012000. Ничего не возвращается вообще. Но в некоторые другие високосные годы можно вычислить первый день марта. Также иногда кажущиеся случайными даты не работают. Я не знаю, как это исправить. Также я должен написать часть, которая вычисляет «daynumber», а затем вызывает ее позже, поэтому я не уверен, что я делаю это правильно.Моя программа C, использующая алгоритм Целлера, очень неспособен на високосные годы, не уверена, почему?

Извините за начальные вопросы, это моя первая программа на C.

#include<stdio.h> 
#include<math.h> 
int main() 
{ 
int day, month, year, lastday, dayname, daynumber, input, d; 

//Determine the last day of user specified month 

printf("Enter date: ddmmyyyy:\n"); 
scanf("%d", &input); 

day = input/1000000; 
month = (input/10000) % 100; 
year = input % 10000; 

if (month == 1 || month == 3 || month == 5 || month == 7 || 
    month == 8 || month == 10 || month == 12) 
    lastday = 31; 
else if (month == 4 || month == 6 || month == 9 || month == 11) 
    lastday = 30; 
else if ((year%4 == 0 && year%100 !=0) || year%400 == 0) 
    lastday = 29; 
else 
    lastday = 28; 

//Verify the date 

if (year < 0) 
    return 1; 
if (month < 1 || month > 12) 
    return 2; 
if (day < 1 || day > lastday) 
    return 3; 

//Algorithm 

{ 

int m, d, y, c, daynumber; 

if (month > 3) 
    m = month - 2; 
else 
    m = month + 10; 

if (m == 11 || m == 12) 
    year = year - 1; 
else 
    year = year; 

d = day; 
y = year % 100; 
c = year/100; 

daynumber = (((13*m - 1)/5) + d + y + (y/4) + (c/4) - 2*c) % 7; 

if (daynumber == 0) 
    printf("Sunday\n"); 
if (daynumber == 1) 
    printf("Monday\n"); 
if (daynumber == 2) 
    printf("Tuesday\n"); 
if (daynumber == 3) 
    printf("Wednesday\n"); 
if (daynumber == 4) 
    printf("Thursday\n"); 
if (daynumber == 5) 
    printf("Friday\n"); 
if (daynumber == 6) 
    printf("Saturday\n"); 

} 

} 
+0

Используйте 'ctime' библиотеку для управления датами. Переход на летнее время, високосные и скачкообразные секунды затрудняют запись собственного алгоритма, если вы заботитесь о точности. – IceArdor

+1

@IceArdor: конгруэнтность Целлера уже составляет високосные годы. Поскольку это вопрос новичка, может быть предпочтительнее помочь им, а не научить их, как сшивать библиотеки вместе. ;) –

+2

Не месяцы в конгруэнции Целлера считаются с 3 = с марта по 14 = февраль? Вы не должны вычитать из «месяца», добавляя «+ 12» за январь и февраль и, следовательно, только декрементируя год, когда 'm == 13 || m == 14', правильно? –

ответ

0

Вы используете:

printf("Enter date: ddmmyyyy:\n"); 
scanf("%d", &input); 

Здесь вы сохраняете вход как междунар. Если sizeof (int) равен 2 байтам, его диапазон будет находиться между -32,768 до 32,767, и ваш вход будет вне диапазона. Для этого вы должны использовать long int.

1

Я не могу увидеть вашу ошибку, но нет необходимости сканировать все число и разделить, использование:

scanf("%2d%2d%4d", &day, &month, &year); 

Использования Sakamoto's algorithm вы можете сделать то же самое в нескольких строках:

#include <stdio.h> 

static int wday(int d, int m, int y) 
{ 
    static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; 

    y -= m < 3; 
    return (y + y/4 - y/100 + y/400 + offset[m - 1] + d) % 7; 
} 

int main(void) 
{ 
    const char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 
    int d, m, y; 

    printf("Enter date [ddmmyyyy]: "); 
    scanf("%2d%2d%4d", &d, &m, &y); 
    printf("%s\n", days[wday(d, m, y)]); 
    return 0; 
} 
1

Это

(((13*m - 1)/5) + d + y + (y/4) + (c/4) - 2*c) 

, вероятно, может быть отрицательным. Результат % 7 будет по-прежнему отрицательным и ничего не печатается.

Просто добавьте daynumber = (daynumber + 7) % 7; после строки

daynumber = (((13*m - 1)/5) + d + y + (y/4) + (c/4) - 2*c) % 7;