2. 编写 IP 地址类#
点击查看考点
类的基础语法, 运算符重载
使用上一题定义的 Ip
类编写程序, 完成如下操作,
输入两个 IPv4 地址并以二进制方式存放进文件.
从保存的文件中读取数据, 修改第二个 IPv4 地址的最后段为
0
, 并将两个 IPv4 地址输出到屏幕上.
点击查看解答参考
输入输出的实现更建议参考 运算符重载.
1#ifndef IP_HPP
2#define IP_HPP
3
4#include <iomanip>
5#include <istream>
6#include <ostream>
7#include <stdexcept>
8
9namespace detail {
10auto is_valid_ip_section(int ip_section) -> bool {
11 int const kLowerBound{0};
12 int const kUpperBound{255};
13
14 return kLowerBound <= ip_section && ip_section <= kUpperBound;
15}
16} // namespace detail
17
18class Ip {
19 public:
20 Ip() : first_(), second_(), third_(), fourth_() {}
21 Ip(int first, int second, int third, int fourth)
22 : first_(first), second_(second), third_(third), fourth_(fourth) {
23 throw_if_invalid_ip();
24 }
25
26 auto first() const -> int {
27 return first_;
28 }
29 auto second() const -> int {
30 return second_;
31 }
32 auto third() const -> int {
33 return third_;
34 }
35 auto fourth() const -> int {
36 return fourth_;
37 }
38
39 void set_first(int first) {
40 first_ = first;
41 throw_if_invalid_ip();
42 }
43 void set_second(int second) {
44 second_ = second;
45 throw_if_invalid_ip();
46 }
47 void set_third(int third) {
48 third_ = third;
49 throw_if_invalid_ip();
50 }
51 void set_fourth(int fourth) {
52 fourth_ = fourth;
53 throw_if_invalid_ip();
54 }
55
56 friend auto operator<<(std::ostream& ostream, Ip const& ip) -> std::ostream& {
57 ostream << std::setfill('0');
58
59 ostream << std::setw(3) << ip.first_;
60 ostream << '.' << std::setw(3) << ip.second_;
61 ostream << '.' << std::setw(3) << ip.third_;
62 ostream << '.' << std::setw(3) << ip.fourth_;
63 return ostream;
64 }
65
66 friend auto operator>>(std::istream& istream, Ip& ip) -> std::istream& {
67 // 这里输入也应该检测 IP 是不是在范围内, 这是 Ip 类的不变式
68 // - 一种方式是输入数据成员, 然后利用现有的构造函数 (其中会判定 IP 是不是在范围内) 和拷贝赋值函数进行
69 // - 另一种是把判定不变式抽象为一个函数, 在输入完成后调用
70
71 bool is_good = false;
72
73 int first = 0;
74 int second = 0;
75 int third = 0;
76 int fourth = 0;
77 if (istream >> first
78 && istream.get() == '.'
79 && istream >> second
80 && istream.get() == '.'
81 && istream >> third
82 && istream.get() == '.'
83 && istream >> fourth) {
84 is_good = true; // 格式正确
85 }
86
87 if (is_good) {
88 ip = Ip(first, second, third, fourth);
89 }
90
91 return istream;
92 }
93
94 private:
95 void throw_if_invalid_ip() const {
96 if (detail::is_valid_ip_section(first_)
97 && detail::is_valid_ip_section(second_)
98 && detail::is_valid_ip_section(third_)
99 && detail::is_valid_ip_section(fourth_)) {
100 return;
101 }
102 throw std::invalid_argument("Invalid IPv4");
103 }
104
105 int first_;
106 int second_;
107 int third_;
108 int fourth_;
109};
110
111#endif