shushus

Спринт 10. Зови меня по имени. Задание 2.

Mar 8th, 2023
495
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.88 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. main.cpp
  3. -----------------------------------------------------------------------
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <iostream>
  7. #include <numeric>
  8. #include <vector>
  9.  
  10. #include "xml.h"
  11.  
  12. using namespace std;
  13.  
  14. struct Spending {
  15.     string category;
  16.     int amount;
  17. };
  18.  
  19. int CalculateTotalSpendings(const vector<Spending>& spendings) {
  20.     return accumulate(spendings.begin(), spendings.end(), 0,
  21.                       [](int current, const Spending& spending) {
  22.                           return current + spending.amount;
  23.                       });
  24. }
  25.  
  26. string FindMostExpensiveCategory(const vector<Spending>& spendings) {
  27.     assert(!spendings.empty());
  28.     auto compare_by_amount = [](const Spending& lhs, const Spending& rhs) {
  29.         return lhs.amount < rhs.amount;
  30.     };
  31.     return max_element(begin(spendings), end(spendings), compare_by_amount)->category;
  32. }
  33.  
  34. vector<Spending> LoadFromXml(istream& input) {
  35.     std::vector<Spending> result;
  36.    
  37.     auto tags = Load(input).GetRoot().Children();
  38.    
  39.     for (auto tag : tags) {
  40.         Spending helper;
  41.        
  42.         helper.amount = tag.AttributeValue<int>("amount");
  43.         helper.category = tag.AttributeValue<string>("category");
  44.        
  45.         result.push_back(move(helper));
  46.     }
  47.     return result;
  48. }
  49.  
  50. int main() {
  51.     const vector<Spending> spendings = LoadFromXml(cin);
  52.     cout << "Total "sv << CalculateTotalSpendings(spendings) << '\n';
  53.     cout << "Most expensive is "sv << FindMostExpensiveCategory(spendings) << '\n';
  54. }
  55. -----------------------------------------------------------------------
  56. xml.h
  57. -----------------------------------------------------------------------
  58. #pragma once
  59.  
  60. #include <istream>
  61. #include <sstream>
  62. #include <string>
  63. #include <string_view>
  64. #include <unordered_map>
  65. #include <vector>
  66.  
  67. class Node {
  68. public:
  69.     Node(std::string name, std::unordered_map<std::string, std::string> attrs);
  70.  
  71.     const std::vector<Node>& Children() const;
  72.     void AddChild(Node node);
  73.     std::string_view Name() const;
  74.  
  75.     template <typename T>
  76.     T AttributeValue(const std::string& name) const;
  77.  
  78. private:
  79.     std::string name_;
  80.     std::vector<Node> children_;
  81.     std::unordered_map<std::string, std::string> attrs_;
  82. };
  83.  
  84. class Document {
  85. public:
  86.     explicit Document(Node root);
  87.  
  88.     const Node& GetRoot() const;
  89.  
  90. private:
  91.     Node root_;
  92. };
  93.  
  94. Document Load(std::istream& input);
  95.  
  96. template <typename T>
  97. inline T Node::AttributeValue(const std::string& name) const {
  98.     std::istringstream attr_input(attrs_.at(name));
  99.     T result;
  100.     attr_input >> result;
  101.     return result;
  102. }
  103. -----------------------------------------------------------------------
  104. xml.cpp
  105. -----------------------------------------------------------------------
  106. #include "xml.h"
  107.  
  108. using namespace std;
  109.  
  110. pair<string_view, string_view> Split(string_view line, char by) {
  111.     size_t pos = line.find(by);
  112.     string_view left = line.substr(0, pos);
  113.  
  114.     if (pos < line.size() && pos + 1 < line.size()) {
  115.         return {left, line.substr(pos + 1)};
  116.     } else {
  117.         return {left, string_view()};
  118.     }
  119. }
  120.  
  121. string_view Lstrip(string_view line) {
  122.     while (!line.empty() && isspace(line[0])) {
  123.         line.remove_prefix(1);
  124.     }
  125.     return line;
  126. }
  127.  
  128. string_view Unquote(string_view value) {
  129.     if (!value.empty() && value.front() == '"') {
  130.         value.remove_prefix(1);
  131.     }
  132.     if (!value.empty() && value.back() == '"') {
  133.         value.remove_suffix(1);
  134.     }
  135.     return value;
  136. }
  137.  
  138. Node LoadNode(istream& input) {
  139.     string root_name;
  140.     getline(input, root_name);
  141.  
  142.     Node root(root_name.substr(1, root_name.size() - 2), {});
  143.     for (string line; getline(input, line) && line[1] != '/';) {
  144.         auto [node_name, attrs] = Split(Lstrip(line), ' ');
  145.         attrs = Split(attrs, '>').first;
  146.         unordered_map<string, string> node_attrs;
  147.         while (!attrs.empty()) {
  148.             const auto [head, tail] = Split(attrs, ' ');
  149.             const auto [name, value] = Split(head, '=');
  150.             if (!name.empty() && !value.empty()) {
  151.                 node_attrs[string(Unquote(name))] = string(Unquote(value));
  152.             }
  153.             attrs = tail;
  154.         }
  155.  
  156.         root.AddChild(Node(string(node_name.substr(1)), move(node_attrs)));
  157.     }
  158.     return root;
  159. }
  160.  
  161. Document Load(istream& input) {
  162.     return Document{LoadNode(input)};
  163. }
  164.  
  165. Node::Node(string name, unordered_map<string, string> attrs)
  166.     : name_(move(name))
  167.     , attrs_(move(attrs)) {
  168. }
  169.  
  170. const vector<Node>& Node::Children() const {
  171.     return children_;
  172. }
  173.  
  174. Document::Document(Node root)
  175.     : root_(move(root)) {
  176. }
  177.  
  178. const Node& Document::GetRoot() const {
  179.     return root_;
  180. }
  181.  
  182. void Node::AddChild(Node node) {
  183.     children_.push_back(move(node));
  184. }
  185.  
  186. string_view Node::Name() const {
  187.     return name_;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment