Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------------------------------
- main.cpp
- -----------------------------------------------------------------------
- #include <algorithm>
- #include <cassert>
- #include <iostream>
- #include <numeric>
- #include <vector>
- #include "xml.h"
- using namespace std;
- struct Spending {
- string category;
- int amount;
- };
- int CalculateTotalSpendings(const vector<Spending>& spendings) {
- return accumulate(spendings.begin(), spendings.end(), 0,
- [](int current, const Spending& spending) {
- return current + spending.amount;
- });
- }
- string FindMostExpensiveCategory(const vector<Spending>& spendings) {
- assert(!spendings.empty());
- auto compare_by_amount = [](const Spending& lhs, const Spending& rhs) {
- return lhs.amount < rhs.amount;
- };
- return max_element(begin(spendings), end(spendings), compare_by_amount)->category;
- }
- vector<Spending> LoadFromXml(istream& input) {
- std::vector<Spending> result;
- auto tags = Load(input).GetRoot().Children();
- for (auto tag : tags) {
- Spending helper;
- helper.amount = tag.AttributeValue<int>("amount");
- helper.category = tag.AttributeValue<string>("category");
- result.push_back(move(helper));
- }
- return result;
- }
- int main() {
- const vector<Spending> spendings = LoadFromXml(cin);
- cout << "Total "sv << CalculateTotalSpendings(spendings) << '\n';
- cout << "Most expensive is "sv << FindMostExpensiveCategory(spendings) << '\n';
- }
- -----------------------------------------------------------------------
- xml.h
- -----------------------------------------------------------------------
- #pragma once
- #include <istream>
- #include <sstream>
- #include <string>
- #include <string_view>
- #include <unordered_map>
- #include <vector>
- class Node {
- public:
- Node(std::string name, std::unordered_map<std::string, std::string> attrs);
- const std::vector<Node>& Children() const;
- void AddChild(Node node);
- std::string_view Name() const;
- template <typename T>
- T AttributeValue(const std::string& name) const;
- private:
- std::string name_;
- std::vector<Node> children_;
- std::unordered_map<std::string, std::string> attrs_;
- };
- class Document {
- public:
- explicit Document(Node root);
- const Node& GetRoot() const;
- private:
- Node root_;
- };
- Document Load(std::istream& input);
- template <typename T>
- inline T Node::AttributeValue(const std::string& name) const {
- std::istringstream attr_input(attrs_.at(name));
- T result;
- attr_input >> result;
- return result;
- }
- -----------------------------------------------------------------------
- xml.cpp
- -----------------------------------------------------------------------
- #include "xml.h"
- using namespace std;
- pair<string_view, string_view> Split(string_view line, char by) {
- size_t pos = line.find(by);
- string_view left = line.substr(0, pos);
- if (pos < line.size() && pos + 1 < line.size()) {
- return {left, line.substr(pos + 1)};
- } else {
- return {left, string_view()};
- }
- }
- string_view Lstrip(string_view line) {
- while (!line.empty() && isspace(line[0])) {
- line.remove_prefix(1);
- }
- return line;
- }
- string_view Unquote(string_view value) {
- if (!value.empty() && value.front() == '"') {
- value.remove_prefix(1);
- }
- if (!value.empty() && value.back() == '"') {
- value.remove_suffix(1);
- }
- return value;
- }
- Node LoadNode(istream& input) {
- string root_name;
- getline(input, root_name);
- Node root(root_name.substr(1, root_name.size() - 2), {});
- for (string line; getline(input, line) && line[1] != '/';) {
- auto [node_name, attrs] = Split(Lstrip(line), ' ');
- attrs = Split(attrs, '>').first;
- unordered_map<string, string> node_attrs;
- while (!attrs.empty()) {
- const auto [head, tail] = Split(attrs, ' ');
- const auto [name, value] = Split(head, '=');
- if (!name.empty() && !value.empty()) {
- node_attrs[string(Unquote(name))] = string(Unquote(value));
- }
- attrs = tail;
- }
- root.AddChild(Node(string(node_name.substr(1)), move(node_attrs)));
- }
- return root;
- }
- Document Load(istream& input) {
- return Document{LoadNode(input)};
- }
- Node::Node(string name, unordered_map<string, string> attrs)
- : name_(move(name))
- , attrs_(move(attrs)) {
- }
- const vector<Node>& Node::Children() const {
- return children_;
- }
- Document::Document(Node root)
- : root_(move(root)) {
- }
- const Node& Document::GetRoot() const {
- return root_;
- }
- void Node::AddChild(Node node) {
- children_.push_back(move(node));
- }
- string_view Node::Name() const {
- return name_;
- }
Advertisement
Add Comment
Please, Sign In to add comment