///////////////////////////////////////////////////////////////////// // Task3.cpp - second task for GettingStarted application // #include "Task3.h" #include #include #include #include /*----< initialize Task3 instances >-------------------------------*/ Task3::Task3(const std::string& fileName, double num, double denom) { std::cout << "\n Starting Task3"; } /*----< return resources used by Task3 instances >-----------------*/ Task3::~Task3() { std::cout << "\n Task3 shutting down"; } /*----< execute Task3 file activity >------------------------------*/ /* * - attempts to open file with name fileName * - throws exception if file open fails */ std::ifstream Task3::doWork(const std::string& fileName) { std::cout << "\n performing Task #3 -- attempts to open file \"" << fileName.c_str() << "\""; std::ifstream strm; // c++ streams won't throw exceptions unless you tell them to do so, i.e., //strm.exceptions(std::ifstream::failbit | std::ifstream::badbit); // open file stream and read first four lines strm.open(fileName); std::function fileOp = [&]() { if (strm.good()) { std::string line; for (int i = 0; i < 4; ++i) { std::getline(strm, line); std::cout << "\n " << line; } } else { std::cout << "\n can't open file \"" << fileName << "\""; } }; safeInvoke(fileOp); return strm; } /*----< execute Task3 divide activity >----------------------------*/ double Task3::doWork(double num, double denom) { std::cout << "\n performing Task #3 -- divides " << num << " by " << denom; return (num / denom); } /*----< implement required self-test >-----------------------------*/ bool Task3::test() { std::ostringstream out; // test cases expected to succeed double num = 3.1415927, denom = 2.0, result; std::function arithOp1 = [&]() { result = doWork(num, denom); // divides num by denom }; safeInvoke(arithOp1); out << "result = " << result; bool tst1 = checkResult(result != INFINITY && result != NAN, "Task3::doWork(double, double)", out.str()); out.str(""); std::ifstream strm1; std::string fileName = "../Task3/Task3.h"; std::function fileOp1 = [&]() { strm1 = doWork(fileName); }; bool testReturn = safeInvoke(fileOp1) && strm1.good(); out << "\"" << fileName << "\"" << " " << (testReturn ? "opened" : "failed to open"); bool tst2 = checkResult(testReturn, "Task3:doWork(const std::string&)", out.str()); // test cases expected to fail out.str(""); strm1.close(); num = 3.1415927; denom = 0.0; std::function arithOp2 = [&]() { result = doWork(num, denom); // divides num by denom }; safeInvoke(arithOp2); out << "result = " << result; bool tst3 = checkResult(result != INFINITY && result != NAN, "Task3::doWork(double, double)", out.str()); out.str(""); fileName = "doesn't exist"; std::function fileOp2 = [&]() { strm1 = doWork(fileName); }; testReturn = safeInvoke(fileOp2) && strm1.good(); out << "\"" << fileName << "\"" << " " << (testReturn ? "opened" : "failed to open"); bool tst4 = checkResult(testReturn, "Task3:doWork(const std::string&)", out.str()); return tst1 && tst2 && tst3 && tst4; } /*----< entry point simply invokes its own self-test >-------------*/ #ifdef TEST_TASK3 int main() { std::cout << "\n testing Task3"; std::cout << "\n ---------------"; Task3 t3("doesn't exist", 2.0, 0.0); t3.testPackage(); std::cout << "\n\n"; } #endif