Go back to Richel Bilderbeek's homepage.

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

 

 

 

 

 

(C++) Survey

 

Survey is a class for a survey.

 

 

 

 

 

survey.h

 

//---------------------------------------------------------------------------
/*
Survey, a collection of Questions
Copyright (C) 2011 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppSurvey.htm
//---------------------------------------------------------------------------
#ifndef SURVEY_H
#define SURVEY_H
//---------------------------------------------------------------------------
#include <string>
#include <vector>
//---------------------------------------------------------------------------
#include <boost/shared_ptr.hpp>
//---------------------------------------------------------------------------
struct Question;
//---------------------------------------------------------------------------
///A Survey is a collection of questions
struct Survey
{
  //Construct a Survey from a collection of questions
  Survey(std::vector<boost::shared_ptr<Question> > questions);

  //Construct a Survey from file
  Survey(const std::string& filename);

  ///Read the current question
  const Question * GetCurrentQuestion() const;

  ///Get the number of questions
  int GetNumberOfQuestions() const;

  ///Go to the next question
  void Next();

  ///Set the path of the current application
  static void SetPath(const std::string path);

  private:

  ///The questions
  std::vector<boost::shared_ptr<Question> > m_questions;

  ///An iterator pointing to the current question
  std::vector<boost::shared_ptr<Question> >::iterator m_current;

  ///The path of the application
  static std::string m_path;

  ///Convert a std::string to a Question
  static boost::shared_ptr<Question> Parse(const std::string& s);

  ///FileToVector reads a file and converts it to a std::vector<std::string>
  ///From http://www.richelbilderbeek.nl/CppFileToVector.htm
  static const std::vector<std::string> FileToVector(const std::string& filename);

  ///Replaces all occurences of a substring
  //From http://www.richelbilderbeek.nl/CppReplaceAll.htm
  static const std::string ReplaceAll(
    std::string s,
    const std::string& replaceWhat,
    const std::string& replaceWithWhat);

  ///Split a std::string
  //From http://www.richelbilderbeek.nl/CppSeperateString.htm
  static const std::vector<std::string> SeperateString(
    const std::string& input,
    const char seperator);

};
//---------------------------------------------------------------------------
#endif // SURVEY_H

 

 

 

 

 

survey.cpp

 

//---------------------------------------------------------------------------
#include <fstream>
//---------------------------------------------------------------------------
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/numeric/conversion/cast.hpp>
//---------------------------------------------------------------------------
#include "multiplechoicequestion.h"
#include "openquestion.h"
#include "survey.h"
//---------------------------------------------------------------------------
std::string Survey::m_path;
//---------------------------------------------------------------------------
Survey::Survey(std::vector<boost::shared_ptr<Question> > questions)
  : m_questions(questions)
{
  assert(std::find_if(m_questions.begin(),m_questions.end(),
    !boost::lambda::_1) == m_questions.end()
    && "All questions must be initialized");
  m_current = m_questions.begin();
}
//---------------------------------------------------------------------------
Survey::Survey(const std::string& filename)
{
  assert(boost::filesystem::exists(filename));
  if (!boost::filesystem::exists(filename))
  {
    throw std::logic_error("File does not exist");
  }
  const std::vector<std::string> v = FileToVector(filename);
  m_questions.reserve(v.size());
  BOOST_FOREACH(const std::string& s,v)
  {
    boost::shared_ptr<Question> q = Parse(s);
    if (q) m_questions.push_back(q);
  }
}
//---------------------------------------------------------------------------
///FileToVector reads a file and converts it to a std::vector<std::string>
///From http://www.richelbilderbeek.nl/CppFileToVector.htm
const std::vector<std::string> Survey::FileToVector(const std::string& filename)
{
  assert(boost::filesystem::exists(filename));
  std::vector<std::string> v;
  std::ifstream in(filename.c_str());
  std::string s;
  for (int i=0; !in.eof(); ++i)
  {
    std::getline(in,s);
    v.push_back(s);
  }
  return v;
}
//---------------------------------------------------------------------------
const Question * Survey::GetCurrentQuestion() const
{
  return (*m_current).get();
}
//---------------------------------------------------------------------------
int Survey::GetNumberOfQuestions() const
{
  return boost::numeric_cast<int>(m_questions.size());
}
//---------------------------------------------------------------------------
void Survey::Next()
{
  ++m_current;
  if (m_current == m_questions.end())
  {
    std::random_shuffle(m_questions.begin(),m_questions.end());
    m_current = m_questions.begin();
  }
}
//---------------------------------------------------------------------------
boost::shared_ptr<Question> Survey::Parse(const std::string& s)
{
  boost::shared_ptr<Question> q;
  //Obtain the string to split
  if (s.empty()) return q;

  //Replace \, by {comma}
  const std::string str_to_split = ReplaceAll(s,"\\,","{comma}");

  //Write string to split to debug
  std::vector<std::string> v = SeperateString(str_to_split,',');

  //Replace {comma} by a comma for each std::string in v
  BOOST_FOREACH(std::string& s,v) { s = ReplaceAll(s,"{comma}",","); }

  if ( v.empty()
    || v.size() < 3
    || v[0].empty()
    || v[1].empty()
    || v[2].empty())
  {
    return q;
  }

  //const std::string filename = m_path + '/' + v[0];
  const std::string& filename = v[0];
  const std::string& question = v[1];
  const std::string& answer   = v[2];

  if (v.size() == 3)
  {
    //Open question
    const std::vector<std::string> answers(SeperateString(answer,'/'));
    q.reset(new OpenQuestion(filename,question,answers));
  }
  else
  {
    //Multiple choice question
    const std::vector<std::string> false_answers(v.begin() + 3,v.end());
    q.reset(new MultipleChoiceQuestion(filename,question,answer,false_answers));
  }
  return q;
}
//---------------------------------------------------------------------------
const std::string Survey::ReplaceAll(
  std::string s,
  const std::string& replaceWhat,
  const std::string& replaceWithWhat)
{
  while(1)
  {
    const int pos = s.find(replaceWhat);
    if (pos==-1) break;
    s.replace(pos,replaceWhat.size(),replaceWithWhat);
  }
  return s;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppSeperateString.htm
const std::vector<std::string> Survey::SeperateString(
  const std::string& input,
  const char seperator)
{
  std::vector<std::string> v;
  boost::algorithm::split(v,input,
    std::bind2nd(std::equal_to<char>(),seperator),
    boost::algorithm::token_compress_on);
  return v;
}
//---------------------------------------------------------------------------
///Set the path of the current application
void Survey::SetPath(const std::string path)
{
  m_path = path;
}
//---------------------------------------------------------------------------

 

 

 

 

 

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