#include // FIND THE BUGS // // The following program is intended to classify two // integers 'm' and 'n' into one of four cases: // // - they have opposite signs, // - exactly one is zero, // - both are zero, or // - they have the same sign. // // There are two logical bugs in the program. // // What are they, why do they cause incorrect behavior, // and how would you fix them? // Function declarations int main(); // Function definitions int main() { int m{}; int n{}; std::cout << "Enter an integer 'm': "; std::cin >> m; std::cout << "Enter an integer 'n': "; std::cin >> n; if ( ((m < 0) && (n > 0)) || ((n > 0) && (m < 0)) ) { std::cout << m << " and " << n << " have opposite signs." << std::endl; } else if ( (m == 0) || (n == 0) ) { std::cout << "One of 'm' and 'n' is zero." << std::endl; } else if ( (m == 0) && (n == 0) ) { std::cout << "Both 'm' and 'n' are zero." << std::endl; } else { std::cout << m << " and " << n << " have the same sign." << std::endl; } return 0; } // Hint: // // For the first condition, write down the two different // ways that two nonzero integers can have opposite signs: // // m is negative AND n is positive // // OR // // m is positive AND n is negative. // // Does the first condition test both of these cases? // // For the remaining conditions, remember that an // if-else-if cascade stops as soon as it encounters a // condition that is true. // // If both m and n are zero, which condition is encountered // first, and is it true? // Bug 1: // // The two operands of || in the first condition are // // ((m < 0) && (n > 0)) // // and // // ((n > 0) && (m < 0)). // // These are the same condition with the two operands of // && written in the opposite order. // // Consequently, the condition detects // // m < 0 and n > 0, // // but it does not detect // // m > 0 and n < 0. // // For example, if // // m = 3 // n = -2, // // the program incorrectly reaches the final 'else' and // says that the integers have the same sign. // Bug 2: // // Consider // // m = 0 // n = 0. // // The condition // // (m == 0) || (n == 0) // // is true, so that branch is executed. // // The following condition // // (m == 0) && (n == 0) // // is therefore never reached when both integers are zero. // // In fact, that entire branch is unreachable. Whenever // // (m == 0) && (n == 0) // // is true, the preceding condition // // (m == 0) || (n == 0) // // must also be true. // // The more specific case must therefore be tested first. // Here is one solution: /* int main() { int m{}; int n{}; std::cout << "Enter an integer 'm': "; std::cin >> m; std::cout << "Enter an integer 'n': "; std::cin >> n; if ( ((m < 0) && (n > 0)) || ((m > 0) && (n < 0)) ) { std::cout << m << " and " << n << " have opposite signs." << std::endl; } else if ( (m == 0) && (n == 0) ) { std::cout << "Both 'm' and 'n' are zero." << std::endl; } else if ( (m == 0) || (n == 0) ) { std::cout << "One of 'm' and 'n' is zero." << std::endl; } else { std::cout << m << " and " << n << " have the same sign." << std::endl; } return 0; } */