// // // // // Lab. Calcolo II - Esempio di codice // // // // // // // // Example code: Reading and writing measurements. #include <iostream> #include <iomanip> #include <string> #include <fstream> #include <sstream> #include <list> #include <system_error> #include <cerrno> template<typename TNUM> class measurement; template<typename TNUM> std::ostream &operator<< (std::ostream &os, const measurement<TNUM> meas); template<typename TNUM> std::istream &operator>> (std::istream &is, measurement<TNUM> &meas); template<typename TNUM> class measurement { friend std::ostream &operator<< <TNUM> (std::ostream &os, const measurement<TNUM> meas); friend std::istream &operator>> <TNUM> (std::istream &is, measurement<TNUM> &meas); public: typedef TNUM value_type; // Creators measurement(const TNUM& value, const std::string date, const std::string observer) : m_value(value), m_date(date), m_observer(observer) {} measurement() {} // Destructor ~measurement() {} TNUM value() const { return m_value; } // Use as 'rvalue' TNUM& value() { return m_value; } // Use as 'lvalue' void value(const TNUM& new_value) { m_value = new_value; } // Value assignment const std::string &get_date() const { return m_date; } const std::string &get_observer() const { return m_observer; } private: TNUM m_value; std::string m_date; std::string m_observer; }; template<typename TNUM> std::ostream &operator<< (std::ostream &os, const measurement<TNUM> meas) { return os << meas.m_date << " - " << meas.m_observer << " - " << meas.m_value; } template<typename TNUM> std::istream &operator>> (std::istream &is, measurement<TNUM> &meas) { bool input_done = false; while(!input_done) { std::stringbuf rsbuf; std::string line; is.get(rsbuf); line=rsbuf.str(); if (!line.empty()) { is.clear(); // We may be at EOF after reading a valid record. std::string::size_type pos_sep1 = line.find_first_of('-'); std::string::size_type pos_sep2 = line.find_last_of('-'); if (pos_sep1 == std::string::npos || pos_sep2 == std::string::npos) continue; // Skip malformed lines meas.m_date = line.substr(0,pos_sep1-1); meas.m_observer = line.substr(pos_sep1+2, (pos_sep2-pos_sep1-3)); std::istringstream valuestr(line.substr(pos_sep2+1)); valuestr >> meas.m_value; input_done = true; } // Reading an empty string will set std::ios::failbit, which we // don't want to consider an error. if (is.rdstate() == std::ios::failbit) is.clear(); if (! is.good()) input_done = true; else { is.get(); // Skip past delimiter (newline). is.clear(); // Be happy if it doesn't succeed. } } return is; } int main(int argc, char *argv[]) { typedef measurement<double> measurement_t; std::list<measurement_t> measurements; std::ifstream input; if (argc <= 1) { std::cerr << "Usage: " << argv[0] << " <measurement file name to read>" << std::endl; return 1; } input.open(argv[1],std::ios::in); if (!input) { std::cerr << argv[0] << ": Error: Cannot read from " << argv[1] << ": " << std::system_error(errno, std::system_category()).what() << "." << std::endl; return 1; } while (input.good()) { measurement_t meas; input >> meas; if (input.good()) measurements.push_back(meas); } std::cout << "Successfully read " << measurements.size() << " elements." << std::endl; int meas_count = 0; // Note: we could write auto it=measurements.begin(), but would lose the // constness of the iterator. for (std::list<measurement_t>::const_iterator it=measurements.begin(); it != measurements.end(); ++it) { std::cout << std::setw(3) << ++meas_count << ") " << *it << std::endl; } return 0; }