KnigaRead.com/

Д. Стефенс - C++. Сборник рецептов

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Д. Стефенс, "C++. Сборник рецептов" бесплатно, без регистрации.
Перейти на страницу:

Пример 14.1. Документ XML со списком животных цирка

<?xml version="1.0" encoding="UTF-8"?>

<!- Животные цирка Feldman Family Circus -->

<animalList>

 <animal>

  <name>Herby</name>

  <species>elephant</species>

  <dateOfBirth>1992-04-23</dateOfBirth>

  <veterinarian name="Dr. Hal Brown" phone="(801)595-9627"/>

  <trainer name="Bob Fisk" phone=(801)881-2260"/>

 </animal>

 <animal>

  <name>Sheldon</name>

  <species>parrot</species>

  <dateOfBirth>1998-09-30</dateOfBirth>

  <veterinarian name="Dr Kevin Wilson" phone="(801)466-6498"/>

  <trainer name="Eli Wendel" phone="(801)929-2506"/>

 </animal>

 <animal>

  <name>Dippy</name>

  <species>penguin</species>

  <dateOfBirth>2001-06-08</dateOfBirth>

  <veterinarian name= "Dr. Barbara Swayne" phone="(801)459-7746"/>

  <trainer name="Ben Waxman" phone="(801)882-3549"/>

 </animal>

</animalList>

Пример 14.2 показывает, как может выглядеть определение класса Animal. Animal имеет пять данных-членов, соответствующих кличке, виду, дате рождения, ветеринару и дрессировщику животного. Кличка и вид животного представляются строками типа std::string, дата его рождения представляется типом boost::gregorian::date из Boost.Date_Time, а его ветеринар и дрессировщик представляются экземплярами класса Contact, который определен также в примере 14.2. Пример 14.3 показывает, как можно использовать TinyXml для синтаксического анализа документа animals.xml, просмотра разобранного документа и заполнения вектора std::vector объектов Animal, используя извлеченные из документа данные.

Пример 14.2. Заголовочный файл animal.hpp

#ifndef ANIMALS_HPP_INCLUDED

#define ANIMALS_HPP_INCLUDED


#include <ostream>

#include <string>

#include <stdexcept> // runtime_error

#include <boost/date_time/gregorian/gregorian.hpp>

#include <boost/regex.hpp>


// Представляет ветеринара или дрессировщика

class Contact {

public:

 Contact() {}

 Contact(const std::string& name, const std::string& phone) :

  name_(name) {

  setPhone(phone);

 }

 std::string name() const { return name_; }

 std::string phone() const { return phone_; }

 void setName(const std::string& name) { name_ = name; }

 void setPhone(const std::string& phone) {

  using namespace std;

  using namespace boost;

  // Используйте Boost.Regex, чтобы убедиться, что телефон

  // задач в форме (ddd)ddd-dddd

  static regex pattern("\([0-9]{3}\)[0-9]{3}-[0-9]{4}");

  if (!regex_match(phone, pattern)) {

   throw runtime_error(string("bad phone number:") + phone);

  }

  phone_ = phone;

 }

private:

 std::string name_;

 std::string phone_;

};


// Сравнить на равенство два объекта класса Contact; используется в рецепте

// 14.9 (для полноты следует также определить operator!=)

bool operator--(const Contact& lhs, const Contact& rhs) {

 return lhs.name() == rhs.name() && lhs.phone() == rhs.phone();

}


// Записывает объект класса Contact в поток ostream

std::ostream& operator(std::ostream& out, const Contact& contact) {

 out << contact.name() << " " << contact.phone(); return out;

}


// Класс Animal представляет животное

class Animal {

public:

 // Конструктор по умолчанию класса Animal; этот конструктор будет вами

 // использоваться чаще всего Animal() {}

 // Конструирование объекта Animal с указанием свойств животного;

 // этот конструктор будет использован в рецепте 14.9

 Animal(const std::string& name,

  const std::string& species, const std::string& dob,

  const Contact& vet, const Contact& trainer) :

  name_(name), species_(species), vet_(vet), trainer_(trainer) {

   setDateOfBirth(dob)

  }

 // Функции доступа к свойствам животного

 std::string name() const { return name_; }

 std::string species() const { return species_; }

 boost::gregorian::date dateOfBirth() const { return dob_; )

 Contact veterinarian() const { return vet_; }

 Contact trainer() const { return trainer_; }


 // Функции задания свойств животного

 void setName(const std::string& name) { name_ = name; }

 void setSpecies(const std::string& species) { species_ = species; }

 void setDateOfBirth(const std::string& dob) {

  dob_ = boost::gregorian::from_string(dob);

 }

 void setVeterinarian(const Contact& vet) { vet_ = vet; }

 void setTrainer(const Contact& trainer) { trainer_ = trainer; }

private:

 std::string name_;

 std::string species_;

 boost::gregorian::date dob_;

 Contact vet_;

 Contact trainer_;

};


// Сравнение на равенство двух объектов Animal; используется в рецепте 14.9

// (для полноты следует также определить operator!=)

bool operator==(const Animal& lhs, const Animal& rhs) {

 return lhs.name() == rhs.name() && lhs.species() == rhs.species() &&

  lhs.dateOfBirth() == rhs.dateOfBirth() &&

  lhs.veterinarian() == rhs.veterinarian() &&

  lhs.trainer() == rhs.trainer();

}


// Записывает объект Animal в поток ostream

std::ostream& operator<<(std::ostream& out, const Animal& animal) {

 out << "Animal {n"

  << " name=" << animal.name() << ";n"

  << " species=" << animal.species() << ";n"

  << date-of-birth=" << animal.dateOfBirth() << ";n"

  << " veterinarian=" << animal.veterinarian() << ";n"

  << " trainer=" << animal.trainer() << ";n"

  << "}";

 return out;

}

#endif // #ifndef ANIMALS_HPP_INCLUDED

Пример 14.3. Синтаксический анализ animals.xml с помощью TinyXml

#include <exception>

#include <iostream>  // cout

#include <stdexcept> // runtime_error

#include <cstdlib>   // EXIT_FAILURE

#include <cstring>   // strcmp

#include <vector>

#include <tinyxml.h>

#include "animal.hpp"


using namespace std;


// Извлекает текстовое содержимое элемента XML

const char* textValue("TiXmlElement* e) {

 TiXmlNode* first = fi->FirstChild();

 if (first != 0 && first == e->LastChild() &&

  first->Type() == TiXmlNode::TEXT) {

  // элемент «е» имеет один дочерний элемент типа TEXT;

  // возвратить дочерний элемент

  return first->Value();

 } else {

  throw runtime_error(string("bad ") + e->Value() + " element");

 }

}


// Конструирует объект класса Contact из элементов ветеринара или

// дрессировщика ("veterinarian" или "trainer")

Contact nodeToContact(TiXmlElement* contact) {

 using namespace std;

 const char *name, *phone;

 if (contact->FirstChild() == 0 &&

  (name = contact->Attribute("name")) &&

  (phone = contact->Attribute("phone"))) {

  // Элемент contact не имеет дочерних элементов и имеет атрибуты имени

  // и телефона ("name" и "phone"); используйте эти значения для

  // конструирования объекта Contact

  return Contact(name, phone);

 } else {

  throw runtime_error(string("bad ") + contact->Value() + " element");

 }

}


// Конструирует объект Animal из элемента животного ("animal")

Animal nodeToAnimal(TiXmlElement* animal) {

 using namespace std;

 // Убедиться, что animal соответствует элементу "animal"

 if (strcmp(animal->Value(), "animal") != 0) {

  throw runtime_error(string("bad animal: ") + animal->Value());

 }

 Animal result; // Возвратить значение

 TiXmlElement* element = animal->FirstChildElement();

 // Прочитать элемент клички животного

 if (element && strcmp(element->Value(), "name") == 0) {

  // Первым дочерним элементом объекта animal является кличка (элемент

  // name"); используйте ее текстовое значение для установки клички

  // в объекте result

  result.setName(textValue(element));

 } else {

  throw runtime_error("no name attribute");

 }

 // Прочитать элемент вида животного

 element = element->NextSiblingElement();

 if (element && strcmp(element->Value(), species") == 0) {

  // Вторым дочерним элементом animal является вид животного

  // (элемент "species"); используйте его текстовое значение для

  // установки вида в объекте result

  result.setSpecies(textValue(element));

 } else {

  throw runtime_error(""no species attribute");

 }

 // Прочитать элемент даты рождения

 element = element->NextSiblingElement();

 if (element && strcmp(element->Value(), "dateOfBirth") == 0) {

  // Третьим дочерним элементом animal является дата рождения

  // (элемент "dateOfBirth"));

  // используйте его текстовое значение для установки даты

  // рождения в объекте result

  result.setDateOfBirth(textValue(element));

 } else {

  throw runtime_error("no dateOfBirth attribute");

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*