This write and read a composite data type to/from a std::stream example demonstrates a near-foolproof way. The program its setup is fine: a composite data type is created, written to file, a new composite data type is read from that same file and the program tests if the two are identical.
The assumptions for this approach to work are:
- Text may not contain a bell ('\b') character
Note that the program will issue a failed assert when the assumption is violated. Wonder, how often have you given a bell character as input?
Operating system(s) or programming environment(s)
- Lubuntu 12.10 (quantal)
- Qt Creator 2.5.2
- G++ 4.7.2
Libraries used:
- STL: GNU ISO C++ Library, version 4.7.2
Qt project file: CppCompositeDataTypeToStreamExample1.pro
QT -= core gui QMAKE_CXXFLAGS += -std=c++11 -Werror -Wextra TARGET = CppCompositeDataTypeToStreamExample1 CONFIG += console SOURCES += main.cpp
#include <iostream> #include <iterator> #include <cassert> #include <algorithm> #include <fstream> #include <string> #include <vector> ///Write a std::vector<std::string> to std::ostream //From http://richelbilderbeek.nl/CppVectorToStreamExample2.htm std::ostream& operator<<(std::ostream& os, const std::vector<std::string>& w) { //Copy the original std::vector std::vector<std::string> v = w; //Preformat data std::for_each(v.begin(),v.end(), [&os](std::string& s) { //The only assertion done on the input //Note that users nearly every use bell characters in their text inputs assert(std::count(s.begin(),s.end(),'\b') == 0 && "Text must not contain a bell character"); std::replace(s.begin(),s.end(),' ','\b'); if (s == "</>") s = "<\b/>"; } ); //Check data #ifndef NDEBUG std::for_each(v.begin(),v.end(), [&os](const std::string& s) { assert(s != "</>" && "Text shoule not be '</>' anymore"); assert(std::count(s.begin(),s.end(),' ') == 0 && "Text should not contain spaces anymore"); } ); #endif //Write start tag os << "<>\n"; //Write data std::for_each(v.begin(),v.end(), [&os](const std::string& s) { os << s << '\n'; } ); //Write end tag os << "</>"; return os; } ///Read a std::vector<std::string> from std::ostream //From http://richelbilderbeek.nl/CppVectorToStreamExample2.htm std::istream& operator>>(std::istream& is, std::vector<std::string>& v) { //Read start tag { std::string s; is >> s; assert(s == std::string("<>")); } //Read data until end tag while (1) { std::string s; is >> s; if (s == std::string("</>")) return is; if (s == "<\b/>") s = "</>"; std::replace(s.begin(),s.end(),'\b',' '); v.push_back(s); } } ///The composite data type that will be written/read to/from stream struct Data { Data( const std::string& s = "", const std::vector<std::string>& v = {}, const std::vector<std::string>& w = {} ) : m_s(s), m_v(v), m_w(w) {} std::string m_s; std::vector<std::string> m_v; std::vector<std::string> m_w; }; bool operator==(const Data& lhs, const Data& rhs) { return lhs.m_s == rhs.m_s && lhs.m_v == rhs.m_v && lhs.m_w == rhs.m_w; } bool operator!=(const Data& lhs, const Data& rhs) { return !(lhs == rhs); } std::ostream& operator<<(std::ostream& os, const Data& d) { //Write s { std::string s = d.m_s; std::replace(s.begin(),s.end(),' ','\b'); os << s << '\n'; } os << d.m_v << '\n' << d.m_w; return os; } std::istream& operator>>(std::istream& is, Data& d) { //Read s { std::string s; is >> s; std::replace(s.begin(),s.end(),'\b',' '); d.m_s = s; } is >> d.m_v >> d.m_w; return is; } int main() { //Go ahead, create an entry that breaks the code! const Data data( "<> </>", { "aahs", "aals", "abac", "abas", "</>", " </>", " </> ", "_</>", "</>_", "</></>", "</> </>", "</>_</>", "abba", "abbe", "abbs", "abed", "abet", "abid" } , { "aahs", "aals", "abac", "abas", "</>", " </>", " </> ", "_</>", "</>_", "</></>", "</> </>", "</>_</>", "abba", "abbe", "abbs", "abed", "abet", "abid" } ); const std::string filename = "tmp.txt"; //Write to file { std::ofstream f(filename.c_str()); f << data; } //Read from file { Data other_data; std::ifstream f(filename.c_str()); f >> other_data; assert(data == other_data && "Because the algorithm is excellent, this will never happen B-)"); } }