Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.06.2020, 00:22   #1
JOFRIF
Форумчанин
 
Регистрация: 21.04.2008
Сообщений: 164
По умолчанию язык C проверка даты.

Доброго времени суток!
Вкратце - прога должна считать промежуток времени между двумя введенными датами.
Проблема еще на стадии проверки корректности даты.
Работаю в среде codeBlocks.
Отлаживал прогу ее де средствами + печать с помощью printf где надо проверить определенное значение.

* дата в формате dd/mm/yyyy.
первым делом функция isValidDate проверяет значение yyyy (находиться ли в пределах..) - тут то и проблема. По не понятным мне причинам значение параметра/переменной года yyyy спокойно проходит с любым введенным значением

Код:
#include <stdio.h>
#define TYPE_ERR_MSG "***Type mismatch ERROR***\nPlease try again...\n"
#define VLD_ERR_MSG "***NOT VALID DATE***\nPlease try again...\n"
#define VLD_DAT_LOW 1800      //VALID YEAR 1800-2200
#define VLD_DAT_HIGH 2200

void calc_between_dates(int dd1, int mm1,int yyyy1, int dd2, int mm2, int yyyy2) //DATE1 < DATE2
{

}
int isValidDate(int dd, int mm, int yyyy)
{
    if((yyyy>=VLD_DAT_LOW) && (yyyy<=VLD_DAT_HIGH))
    {
        printf("THE YEAR INSIDE IF...\n");
        if(mm>=1 && mm<=12)
        {
            switch(mm)
            {
                //31 days
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12: if(dd!=31) return 0;break;
                //30 days
                case 4:
                case 6:
                case 9:
                case 11: if(dd!=30) return 0;break;
                //february case
                case 2: if(dd!=28)
                        {
                            if(dd==29)
                            {
                                if(!isLeapYear(dd, mm, yyyy))//אולי שנה מעוברת
                                    return 0;//לא תקין
                                else
                                    return 1;//שנה מעוברת עם 29 ימים
                            }
                            return 0;//לא תקין
                        }
                        break;
            }//SWITCH END
        }//IF month END
        return 0;
    }//IF year END
    printf("THE YEAR IS: %d\n\n",yyyy);
    return 1; //תאריך תקין
}
int isLeapYear(int yyyy)//שנה מעוברת
{
    if (yyyy%4==0 && yyyy%100!=0)//תנאים לשנה מעוברת
        if(yyyy%400==0)
            return 1;
    return 0;//לא מעוברת
}
int main()
{
    int dd1=0,mm1=0,yyyy1=0;
    int dd2=0,mm2=0,yyyy2=0;

    int n;//scanf ret val

    printf("Enter first date: (dd/mm/yyyy) \n");
    while(n=scanf("%d%d%d",&dd1,&mm1,&yyyy1) != 3 || !isValidDate(dd1,mm1,yyyy1))
    {
        if(n != 3)
            printf(TYPE_ERR_MSG);
        if (!isValidDate(dd1,mm1,yyyy1))
            printf(VLD_ERR_MSG);
        _flushall();
    }
    printf("Enter second date: (dd/mm/yyyy) \n");
    while(n=scanf("%d%d%d",&dd2,&mm2,&yyyy2) != 3 || !isValidDate(dd2,mm2,yyyy2))
    {
        if(n != 3)
            printf(TYPE_ERR_MSG);
        if (!isValidDate(dd2,mm2,yyyy2))
            printf(VLD_ERR_MSG);
        _flushall();
    }


}
JOFRIF вне форума Ответить с цитированием
Старый 01.06.2020, 01:24   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

1) Некоторые комментарии сломались.
2) В isValidDate самый последний return должен быть 0.
3) Стоит добавить в scanf слеши, если дата вводится с ними.
4) Количество дней в месяце нужно проверять на "меньше или равно", а не только на неравенство.
5) Проверка на високосный год работает неверно (например, 2020 год).
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 01.06.2020, 01:30   #3
JOFRIF
Форумчанин
 
Регистрация: 21.04.2008
Сообщений: 164
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
1) Некоторые комментарии сломались.
Извиняюсь это иврит ))
Цитата:
2) В isValidDate самый последний return должен быть 0.
Почему ? проверка идет на орицание... т.е если все проверки пройдены (не был возврашен 0) то все ОК.
Цитата:
3) Стоит добавить в scanf слеши, если дата вводится с ними.
Можно поподробнее.. не совсем понятно про слешы..
Цитата:
4) Количество дней в месяце нужно проверять на "меньше или равно", а не только на неравенство.
Согласен испрвлю ))
Цитата:
5) Проверка на високосный год работает неверно (например, 2020 год).
Что нужно поправить?

*спс за быстрый и четкий ответ

п.с например если ввести 12 12 65 (а год должен быть в рамках от 1800 - 2200) то эти данные спокойно пропускаються и сразу же идет прыжок к return 1;

Последний раз редактировалось JOFRIF; 01.06.2020 в 01:33. Причина: добавка
JOFRIF вне форума Ответить с цитированием
Старый 01.06.2020, 01:42   #4
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

Извиняюсь, не знал, как выглядит иврит.
Цитата:
Сообщение от JOFRIF Посмотреть сообщение
если все проверки пройдены (не был возврашен 0) то все ОК
Хорошо, тогда не хватает парочки return внутри ифов и по веткам else. Может быть лучше "вывернуть" логику?
Код:
int isValidDate(int dd, int mm, int yyyy)
{
    if (yyyy < VLD_DAT_LOW || yyyy > VLD_DAT_HIGH)
        return 0;
    if (mm < 1 || mm > 12)
        return 0;
    ...
    return 1;
}
Цитата:
Сообщение от JOFRIF Посмотреть сообщение
не совсем понятно про слешы
Код:
scanf("%d/%d/%d", &dd1, &mm1, &yyyy1)
Цитата:
Проверка на високосный год
Код:
int isLeapYear(int yyyy)
{
    if (yyyy % 400 == 0)
        return 1;
    if (yyyy % 100 == 0)
        return 0;
    if (yyyy % 4 == 0)
        return 1;
    return 0;
}
или
Код:
int isLeapYear(int yyyy)
{
    if (yyyy % 4 != 0 || (yyyy % 100 == 0 && yyyy % 400 != 0))
        return 0;
    else
        return 1;
}
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 01.06.2020 в 01:47.
BDA на форуме Ответить с цитированием
Старый 02.06.2020, 23:24   #5
JOFRIF
Форумчанин
 
Регистрация: 21.04.2008
Сообщений: 164
По умолчанию

Поправил все что вы сказали... но проверка на високосный год не работает корректно.
например я ввел 29/02/2000 (это високосный год т.е return 1, а пофакту идет возврат 0)
п.с пробовал оба варианта.

Код:
#include <stdio.h>
#define TYPE_ERR_MSG "***Type mismatch ERROR***\nPlease try again...\n"
#define VLD_ERR_MSG "***NOT VALID DATE***\nPlease try again...\n"
#define VLD_DAT_LOW 1800      //VALID YEAR 1800-2200
#define VLD_DAT_HIGH 2200

void calc_between_dates(int dd1, int mm1,int yyyy1, int dd2, int mm2, int yyyy2) //DATE1 < DATE2
{

}
int isValidDate(int dd, int mm, int yyyy)
{
    if(yyyy<VLD_DAT_LOW || yyyy>VLD_DAT_HIGH)
        return 0;
    if(mm<1 || mm>12)
        return 0;
    switch(mm)
    {
        //31 days
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12: if(dd<1 || dd>31) return 0;break;
        //30 days
        case 4:
        case 6:
        case 9:
        case 11: if(dd<1 || dd>30) return 0;break;
        //february case
        case 2:
            if(dd<1 || dd>29)
                return 0;
            if(dd==29)//ok on specific case
            {
                if(isLeapYear(dd, mm, yyyy))//אולי שנה מעוברת
                    return 1;//שנה מעוברת עם 29 יום
                else
                    return 0;//לא תקין
            }
        break;
    }//SWITCH END

    printf("THE YEAR IS: %d\n\n",yyyy);
    return 1; //תאריך תקין
}
int isLeapYear(int yyyy)
{
    if (yyyy % 400 == 0)
        return 1;
    if (yyyy % 100 == 0)
        return 0;
    if (yyyy % 4 == 0)
        return 1;
    return 0;
    /*int isLeapYear(int yyyy)
      {
        if (yyyy % 4 != 0 || (yyyy % 100 == 0 && yyyy % 400 != 0))
            return 0;
        else
            return 1;
      }*/
}
int main()
{
    int dd1=0,mm1=0,yyyy1=0;
    int dd2=0,mm2=0,yyyy2=0;

    int n=0;//scanf ret val

    printf("Enter first date: (dd/mm/yyyy) \n");
    n = scanf("%d/%d/%d",&dd1,&mm1,&yyyy1);
    while(n != 3 || !isValidDate(dd1,mm1,yyyy1))
    {
        printf("n=: %d\n",n);
        if(n != 3)
            printf(TYPE_ERR_MSG);
        if (!isValidDate(dd1,mm1,yyyy1))
            printf(VLD_ERR_MSG);
        _flushall();
        n = scanf("%d/%d/%d",&dd1,&mm1,&yyyy1);
    }

    printf("Enter second date: (dd/mm/yyyy) \n");
    n = scanf("%d/%d/%d",&dd2,&mm2,&yyyy2);
    while(n != 3 || !isValidDate(dd2,mm2,yyyy2))
    {
        if(n != 3)
            printf(TYPE_ERR_MSG);
        if (!isValidDate(dd2,mm2,yyyy2))
            printf(VLD_ERR_MSG);
        _flushall();
        n = scanf("%d/%d/%d",&dd2,&mm2,&yyyy2);
    }


}
JOFRIF вне форума Ответить с цитированием
Старый 02.06.2020, 23:40   #6
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 16,216
По умолчанию

Можно чуть упростить:
Код:
int isValidDate(int dd, int mm, int yyyy){
	if(yyyy<VLD_DAT_LOW || yyyy>VLD_DAT_HIGH)
		return 0;
	if(mm<1 || mm>12)
		return 0;
	int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
	if(yyyy % 4 == 0 && yyyy % 100 != 0 || yyyy % 400 == 0)
		days[1] = 29;
	if(dd<1 || dd>days[mm-1])
		return 0;
	return 1;
}
Arigato вне форума Ответить с цитированием
Старый 02.06.2020, 23:55   #7
JOFRIF
Форумчанин
 
Регистрация: 21.04.2008
Сообщений: 164
По умолчанию

Arigato, Спасибо действительно можно укоротить, но проблема в самой проверке.

Код:
if(yyyy % 4 == 0 && yyyy % 100 != 0 || yyyy % 400 == 0)
проверил ваш вариант ввел 29/02/1900 - выдает что год високосный.. что неверно..
JOFRIF вне форума Ответить с цитированием
Старый 03.06.2020, 00:00   #8
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

В коде из 5 поста isLeapYear вызывается с 3 аргументами, а сама функция объявлена с одним.
Предлагаю вынести ввод в отдельную функцию.
Код:
void get_date(char *msg, int *dd, int *mm, int *yyyy)
{
    int n;
    printf("Enter %s date: (dd/mm/yyyy)\n", msg);
    while (1) {
        n = scanf("%d/%d/%d", dd, mm, yyyy);
        if (n != 3) {
            printf(TYPE_ERR_MSG);
            _flushall();
            continue;
        }
        if (!isValidDate(*dd, *mm, *yyyy)) {
            printf(VLD_ERR_MSG);
            _flushall();
            continue;
        }
        break;
    }
}

int main()
{
    int dd1=0,mm1=0,yyyy1=0;
    int dd2=0,mm2=0,yyyy2=0;

    get_date("first", &dd1, &mm1, &yyyy1);
    get_date("second", &dd2, &mm2, &yyyy2);
}
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 03.06.2020, 00:05   #9
JOFRIF
Форумчанин
 
Регистрация: 21.04.2008
Сообщений: 164
По умолчанию

BDA, ЁЁЁЁЁЁЁЁЁ А слона то я и незаметил )) странно что компилятор молчит об этом..
спасибо за ответы, закончю функцию calc_between_dates выложу здесь может кому пригодиться.
JOFRIF вне форума Ответить с цитированием
Старый 03.06.2020, 00:39   #10
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 16,216
По умолчанию

Цитата:
Сообщение от JOFRIF Посмотреть сообщение
проверил ваш вариант ввел 29/02/1900 - выдает что год високосный.. что неверно..
Неверно... проверили...
Arigato вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проверка даты (Java) zhenya.ya Помощь студентам 0 04.12.2011 19:28
Проверка даты daniil123 Паскаль, Turbo Pascal, PascalABC.NET 1 17.11.2011 22:14
Проверка корректности даты Oleg Romanchuk Общие вопросы Delphi 3 09.07.2011 07:13
Проверка даты на сервере!!! $T@LKER Работа с сетью в Delphi 0 11.05.2010 17:03
Проверка даты Михаил Юрьевич Общие вопросы Delphi 11 24.01.2010 20:39