bug around while(!())

there is this bug around while(!())
where i have to re enter my year because it didnt register

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  #include <iostream>
using namespace std;

int main (){
    char again = 'Y';
    while (again == 'Y' || again == 'y'){
        cout << "Enter a year:\n";
        int yr;
        cin >> yr;

        while(!(cin >> yr)){
            cout << "Wrong Data. Try again:\n";
            cin.clear();
            cin.ignore(100,'\n');
        }

        if (yr % 400 == 0){
            cout << "Leap Year.\n";
            cout << "Try Again [Y/N]\n";
            cin >> again;

        }else if (yr % 100 == 0){
            cout << "Not a leap year.\n";
            cout << "Try Again [Y/N]\n";
            cin >> again;

        }else if (yr % 4 == 0){
            cout << "Leap Year.\n";
            cout << "Try Again [Y/N]\n";
            cin >> again;

        }else{
            cout << "Not a leap year.\n";
            cout << "Try Again [Y/N]\n";
            cin >> again;
        }
    }
}
The bug is line 9.
can you tell me how to fix it ? thank you in advance.
Ask yourself, what is the purpose of line 9?
can you tell me how to fix it ? thank you in advance.


Preceed L9 with //
get it now
there is something fishy with your math.
its probably working ok, but
if a year is divisible by 400, it is ALSO divisible by 4 and 100. the 400 check is redundant
as is the 100. If a year is divisible by 100, it is also divisible by 4.
therefore %4 is sufficient and the other 2 are not needed at all.

and clutter. Those if / else blocks are identical. If you combined the conditions, you can do the block once only, just one for is a leap year and one for is not. (this assumes all the conditions are useful, which as noted above, they are redundant, the point is that if you run into this again where the code is the same for a couple of conditions, combine the conditions).
Last edited on
Those if / else blocks are identical

Some say "Leap Year" and some say "Not a leap year", but yeah the last two lines are identical in each block and could be put after the if-else chain to avoid code repetition.


if a year is divisible by 400, it is ALSO divisible by 4 and 100. the 400 check is redundant
as is the 100. If a year is divisible by 100, it is also divisible by 4.
therefore %4 is sufficient and the other 2 are not needed at all.

It's possible to write it more compactly but the checks are not redundant.

Leap years are years that are evenly divisible by 4 except for years that are evenly divisible by 100 but not 400.

Last edited on
A bit more modular, replacing the first while loop with a do/while since the first loop should always execute at least one time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

int main()
{
   char again { 'Y' };

   do
   {
      int year { };

      while (std::cout << "Enter a year: " && !(std::cin >> year))
      {
         std::cout << "Wrong Data. Try again.\n\n";
         std::cin.clear();
         std::cin.ignore(100, '\n');
      }

      // if year is divisible by 4 AND not divisible by 100
      // OR if year is divisible by 400
      // then it is a leap year
      if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
      {
         std::cout << year << " is a leap year.\n\n";
      }
      else
      {
         std::cout << year << " is not a leap year.\n\n";
      }

      std::cout << "Try Again [Y/N]? ";
      std::cin >> again;
      std::cout << '\n';
   }
   while (again == 'Y' || again == 'y');
}
Enter a year: 1900
1900 is not a leap year.

Try Again [Y/N]? y

Enter a year: blarf
Wrong Data. Try again.

Enter a year: 2022
2022 is not a leap year.

Try Again [Y/N]? y

Enter a year: 2020
2020 is a leap year.

Try Again [Y/N]? n
Playing around:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <type_traits>
#include <concepts>
#include <cctype>
#include <limits>

template<typename T = int>
typename std::enable_if_t< std::is_arithmetic_v<T>, T>
getInp(const std::string& prm) {
	const auto notsp { [&] {while (std::isspace(static_cast<unsigned char>(std::cin.peek())) && std::cin.peek() != '\n') std::cin.ignore(); return std::cin.peek() != '\n'; } };
	T n {};

	const auto clear { [] {
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } };

	while ((std::cout << prm) && (!(std::cin >> n) || notsp())) {
		std::cout << "Invalid input. Not a(n) " << typeid(T).name() << '\n';
		clear();
	}

	clear();
	return n;
}

char getInp(const std::string& prm, const std::string& allwd) {
	char ch {};

	do {
		ch = static_cast<char>(std::toupper(static_cast<unsigned char>(getInp<char>(prm))));
	} while ((allwd.find(ch) == std::string::npos) && (std::cout << "Invalid option\n"));

	return ch;
}

bool isLeap(std::integral auto y) {
	return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}

int main() {
	do {
		const auto year { getInp("Enter a year: ") };

		std::cout << year << " is " << (isLeap(year) ? "not " : "") << "a leap year\n";

	} while (getInp("Try again [Y/N]: ", "YN") == 'Y');
}

Topic archived. No new replies allowed.