online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
/* ================================================================= Step 8 (for Solution see Step 9) ================================================================= */ #include "do_averages.h" #include <sstream> // std::istringstream #ifndef TEST int main() { do_averages(); } #else #include "pxt.h" void typical_good_input() { { //////////////////////////////////////////////////////////// std::istringstream input{ "1 5 7" "\n" "1.5 7" "\n" "15.7" "\n" }; std::ostringstream output{}; PX(do_averages(input, output), output.str()) >>= "4.33333" "\n" "4.25" "\n" "15.7" "\n"; } //////////////////////////////////////////////////////////// } void some_empty_inputs() { { //////////////////////////////////////////////////////////// std::istringstream input{"\n"}; std::ostringstream output{}; PX(do_averages(input, output), output.str()) == ""; } //////////////////////////////////////////////////////////// { //////////////////////////////////////////////////////////// std::istringstream input{" \n"}; std::ostringstream output{}; PX(do_averages(input, output), output.str()) == ""; } //////////////////////////////////////////////////////////// } void some_invalid_inputs() { { //////////////////////////////////////////////////////////// std::istringstream input{ "1 5 7" "\n" "1 S 7" "\n" "15.7" "\n" }; std::ostringstream output{}; PX(do_averages(input, output), output.str()) >>= "4.33333" "\n" "non-numeric input - line ignored" "\n" "15.7" "\n"; } //////////////////////////////////////////////////////////// { //////////////////////////////////////////////////////////// std::istringstream input{ "1 5 7" "\n" "xxx 7" "\n" "1 xyz 7" "\n" "1 xyz" "\n" }; std::ostringstream output{}; PX(do_averages(input, output), output.str()) >>= "4.33333" "\n" "non-numeric input - line ignored" "\n" "non-numeric input - line ignored" "\n" "non-numeric input - line ignored" "\n"; } //////////////////////////////////////////////////////////// } void fails_on_my_mac_only() { { //////////////////////////////////////////////////////////// std::istringstream input{ "1 xyz" "\n" "1 abc" "\n" }; std::ostringstream output{}; PX(do_averages(input, output), output.str()) >>= "non-numeric input - line ignored" "\n" "non-numeric input - line ignored" "\n"; } //////////////////////////////////////////////////////////// } int main() { typical_good_input(); some_empty_inputs(); some_invalid_inputs(); // fails_on_my_mac_only(); } #endif
# TODO STEP 8 - Throw an exception instead of returning the indication whether there has been incompletely processed input with a `bool`-result throw an exception. - The simple-most solution would be to just `throw` the message, eg. "non-numeric value in input line" to be displayed by `do_averages` before continuing. Ie. the type to be caught by the `catch`-block would be `char const*`. ------------------------------------------------------------------ TODO (optional - meant for further self-study only): - Come up with more sophisticated ways to construct an error message in `do_single_average`. eg. build an `std::string` naming the offending (non-numeric) character and its position in the input line. - Of course, if an `std::string` is thrown instead of a simple string literal in double quotes, the type expected by catch needs to be changed accordingly. - HINT: After a failed application of `operator>>` like ```cpp float value; iss >> value; ``` the not yet processed part of an `std::istringstream` (representing a single line of input) may be retrieved like this: ```cpp if (iss.fail() && !iss.eof()) // incompletely processed line iss.clear(); // clear the fail state std::string remainder{}; // variable used to read ... std::getline(iss, remainder); // ... what still remains } ```
#include "do_averages.h" #include <iostream> // std::cin // std::cout // std::istream // std::ostream #include <sstream> // std::istringstream // std::ostringstream #include <string> // std::getline // std::string struct sum_count { float sum; int count; }; bool do_single_average(std::string line, sum_count& result) { std::istringstream iss{line}; float value; while (iss >> value) { result.sum += value; ++result.count; } bool const have_received_some_values_but_dont_see_eol{ (result.count > 0) && !iss.eof() }; bool const fail_bit_set_but_not_together_with_eof_bit{ iss.fail() && !iss.eof() }; bool const some_non_numeric_input{ have_received_some_values_but_dont_see_eol || fail_bit_set_but_not_together_with_eof_bit }; return not some_non_numeric_input; } void do_averages(std::istream& in, std::ostream& out) { std::string line; while (std::getline(in, line)) { sum_count sc = {0.0f, 0}; if (not do_single_average(line, sc)) { out << "non-numeric input - line ignored" << std::endl; continue; } if (sc.count == 0) return; out << sc.sum/sc.count << std::endl; } } void do_averages() { do_averages(std::cin, std::cout); }
#ifndef PXT_header_only #include "pxt.h" #endif #include <iostream> namespace PXT_namespace { std::ostream& PXT_class::out_stream{PXT_ostream}; PXT_class::Result PXT_class::counter{0, 0}; PXT_class::Result::~Result() { if (failed > 0) { PXT_class::out_stream << "** " << failed << " of " << total << " tests failed **" << std::endl; } else if (total > 0) { PXT_class::out_stream << "** ALL " << total << " TESTS PASSED **" << std::endl; } } std::ostream& PXT_class::source_location() const { return out_stream << file_ << ' ' << '[' << func_ << ':' << line_ << ']' << ' ' << texpr_; } void PXT_class::plain_output() { source_location() << " == " << streamed_result.str() << std::endl; } void PXT_class::two_line_compare() { done_ = true; ++counter.total; if (streamed_result.str() != expected_result.str()) { ++counter.failed; source_location() << '\n' << " = received: " << streamed_result.str() << '\n' << " ! expected: " << expected_result.str() << std::endl; } } void PXT_class::multi_line_compare() { std::string streamed_line{}; std::string expected_line{}; std::ostringstream common{}; while (std::getline(streamed_result, streamed_line), (expected_result >> std::ws), std::getline(expected_result, expected_line), !streamed_result.eof() && !expected_result.eof() && (streamed_line == expected_line)) { common << " = " << expected_line << '\n'; } done_ = true; ++counter.total; if (streamed_result.eof() && expected_result.eof()) return; // no difference ++counter.failed; if (streamed_result.eof()) { // less streamed than expected source_location() << '\n' << common.str() << " + expected: " << expected_line << std::endl; return; } if (expected_result.eof()) { // less expected than streamed source_location() << '\n' << common.str() << " + received: " << streamed_line << std::endl; return; } source_location() << '\n' // difference in streamed to expected << common.str() << " ~ received: " << streamed_line << '\n' << " ~ expected: " << expected_line << std::endl; } } // namespace
#include <iosfwd> void do_averages(std::istream&, std::ostream&); void do_averages();
#ifndef PXT_off #ifndef PXT_ostream #define PXT_ostream std::cout #endif #define PX(...)\ PXT_namespace::PXT_class{__func__, __FILE__, __LINE__, #__VA_ARGS__, (__VA_ARGS__)} #if defined(PXT_HAVE_BOOST_TYPEINDEX)\ || defined(__has_include) && __has_include(<boost/type_index.hpp>) #include <boost/type_index.hpp> #define PT(...)\ PXT_namespace::PXT_helper(__func__, __FILE__, __LINE__, #__VA_ARGS__,\ boost::typeindex::type_id_with_cvr<__VA_ARGS__>()) #endif #if !defined(PX)\ || !defined(PT) struct PXT_dummy{ template<typename T> void operator==(T const&) const {} template<typename T> void operator*=(T const&) const {} template<typename T> void operator>>=(T const&) const {} template<typename T> void operator%=(T const&) const {} }; #if !defined(PX) #define PX(...) PXT_dummy{} #endif #if !defined(PT) #define PT(...) PXT_dummy{} #endif #endif #include <sstream> #include <iostream> namespace PXT_namespace { class PXT_class { bool done_{}; char const* func_; char const* file_; int const line_{}; char const* texpr_; std::stringstream streamed_result{}; std::stringstream expected_result{}; std::ostream& source_location() const; void plain_output(); void two_line_compare(); void multi_line_compare(); void glob_pattern_compare(); struct Result { unsigned long long total; unsigned long long failed; ~Result(); }; static Result counter; public: static std::ostream& out_stream; static bool ignore_expecations; template<typename T> PXT_class(char const* func, char const* file, int line, char const* texpr, T const& expr) : func_{func}, file_{file}, line_{line}, texpr_{texpr} { streamed_result.copyfmt(out_stream); streamed_result << expr; } ~PXT_class() { if (not done_) plain_output(); } template<typename T> void operator==(T const& expr) { expected_result.copyfmt(streamed_result); expected_result << expr; two_line_compare(); } void operator>>=(std::string lines) { expected_result << lines; multi_line_compare(); } void operator*=(std::string smatch) { glob_pattern_compare(); } }; } // namespace #ifdef PXT_header_only #include "pxt.cpp" #endif #endif

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue