Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Write and read a composite data type to/from a std::stream: example 1

 

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:

 

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?

 

 

 

 

 

 

 

Technical facts

 

Application type(s)

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: CppCompositeDataTypeToStreamExample1.pro

 

QT       -= core gui
QMAKE_CXXFLAGS += -std=c++11 -Werror -Wextra
TARGET = CppCompositeDataTypeToStreamExample1
CONFIG   += console
SOURCES += main.cpp

 

 

 

 

 

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-)");
  }
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml