#c #if-statement #conditional-operator #leap-year
Вопрос:
*Программа выдает неверные выходные данные за столетний год, которые не являются високосными, например, 1900,1700.Программа выдает неверный вывод для високосного года, значение переменной нагрузки неверно, я думаю, например, 1900,1700. *
#include <iostream>
using namespace std;
int main()
{
int year;
bool t1=true;
cout<<t1;
bool t2=false;
cin>>year;
if(year%4==0)
{
int value=year0?year@0?t1:t2:t1;
cout<<value;
if(value==t1)
{
cout<<"leap year";
}
else
{
cout<<"not a leap year";
}
}
else
{
cout<<"not a leap year";
}
}
Комментарии:
1.
int value=year0?year@0?t1:t2:t1;
только почему?2. Как ты думаешь
year0?
, что делает? Или что оператор % вообще делает для ints?3. Пусть все будет просто…. Не делай таких вещей, как
year0?year@0?t1:t2:t1;
4. Почему у вас есть такие переменные, как
t1
иt2
5. Даже не обращая внимания на нечитабельность
int value= ...
вопроса, почему вы решили написать «t1» и «t2» вместо «истина» и «ложь»? (Если вы упростите это, вы найдетеyear % 100 == 0 || year % 400 != 0
.)
Ответ №1:
year0
становится ложным, когда year
делится на 100 (остаток равен нулю), и становится истинным, когда year
не делится на 100 (остаток не равен нулю).
year@0
становится ложным, когда year
делится на 400 (остаток равен нулю), и становится истинным, когда year
не делится на 400 (остаток не равен нулю).
Следовательно, вы должны оценивать число как не високосный год, когда year0
оно ложно и year@0
истинно, и как не високосный год в противном случае.
В заключение, строка
int value=year0?year@0?t1:t2:t1;
должно быть
bool value=year0?t1:year@0?t2:t1;
Кроме того, я не думаю, что использование int
здесь для назначения bool
переменных разумно.
Комментарии:
1. Конечно, это исправление, но это все еще нечитаемый трудный для поддержания беспорядок…
2. @JHBonarius: На мой взгляд, это читается на C , хотя
t1
иt2
нуждается в доработке. Но имейте в виду, что PHP изменил ассоциативность. Забавные ребята.3. @Bathsheba нет, когда будущий разработчик посмотрит на этот код, ему/ей/им придется приложить некоторые усилия, чтобы понять его. Я бы сделал функцию
bool IsDivisibleBy(int num, int divisor) { return num % divisor == 0; }
и однуbool IsLeapYear(int year) { return (IsDivisibleBy(year, 4) amp;amp; !IsDivisibleBy(year, 100)) || IsDivisibleBy(year, 400);}
. Это то, что я считаю читабельным. (Я опускаю[[nodiscard]]
,static
,constexpr
, иnoexcept
)
Ответ №2:
В дополнение к исправлению в ответе MikeCAT вы также можете значительно упростить свой код всего до нескольких строк:
#include <iostream>
int main()
{
int year;
std::cin>>year;
bool leap = (year % 4 == 0) amp;amp; ( (year % 100 != 0) || (year % 400 == 0) );
if(leap)
{
std::cout<<"leap year";
}
else
{
std::cout<<"not a leap year";
}
}
Вы можете использовать 0
эквивалент false
, чтобы сделать его короче, но я думаю, что первая версия более читабельна:
bool leap = !(year % 4) amp;amp; ( (year % 100) || !(year@0) );
Комментарии:
1. @4386427 мне это не кажется намного проще, и у меня есть теоретическое небольшое преимущество в производительности от остановки оценки короткого замыкания после первого срока для 3/4 входных значений, это также в логическом порядке, в котором большинство людей подумали бы о правилах високосного года
2. Отчасти это правда… логика кажется мне более простой, но.. вы правы насчет короткого замыкания
Ответ №3:
Как только компиляторы правильно реализуют C 20 (который еще не выпущен), вам не нужно изобретать велосипед и вы можете использовать std::chrono::year::is_leap
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
year y = 1900y;
std::cout << "year: " << static_cast<int>(y)
<< " is " << (y.is_leap()?"":"not ") << "a leap yearn";
}