C++運算符重載練習:編寫ipv4類

沒什麼,好久沒玩 C++ 了。打算複習一下,編寫個 ipv4 地址類娛樂一下。

IPv4地址

IPv4 地址是一個32位的數字,通常使用十進制和點.進行格式化,比如192.168.1.1。每一個部分都是一個8比特數,範圍從0到255。可以使用4個 unsigned char 存儲地址值。 爲了能夠直接從控制檯輸入和輸出格式化的 IP 地址,重載 operator>>operator<<

一言不合上代碼

#include <iostream>
#include <array>
#include <sstream>

class ipv4
{
    std::array<unsigned char, 4> data;
public:
    constexpr ipv4() : data{ {0} } {}
    constexpr ipv4(unsigned char const a, unsigned char const b,
                   unsigned char const c, unsigned char const d):
        data{ {a, b, c, d} } {}
    explicit constexpr ipv4(unsigned long a):
        data{ { static_cast<unsigned char>((a >> 24) & 0xFF),
                static_cast<unsigned char>((a >> 16) & 0xFF),
                static_cast<unsigned char>((a >>  8) & 0xFF),
                static_cast<unsigned char>(a & 0xFF) } } {}
    ipv4(ipv4 const &other) noexcept : data(other.data) {}

    ipv4& operator=(ipv4 const &other) noexcept
    {
        data = other.data;
        return *this;
    }

    std::string to_string() const
    {
        std::stringstream sstr;
        sstr << *this;
        return sstr.str();
    }

    constexpr unsigned long to_ulong() const noexcept
    {
        return (static_cast<unsigned long>(data[0]) << 24) |
               (static_cast<unsigned long>(data[1]) << 16) |
               (static_cast<unsigned long>(data[2]) << 8)  |
               static_cast<unsigned long>(data[3]);
    }

    friend std::ostream& operator<<(std::ostream& os, const ipv4& a)
    {
        os << static_cast<int>(a.data[0]) << '.'
           << static_cast<int>(a.data[1]) << '.'
           << static_cast<int>(a.data[2]) << '.'
           << static_cast<int>(a.data[3]);
        return os;
    }

    friend std::istream& operator>>(std::istream& is, ipv4& a)
    {
        char d1, d2, d3;
        int b1, b2, b3, b4;
        is >> b1 >> d1 >> b2 >> d2 >> b3 >> d3 >> b4;

        if (d1 == '.' && d2 == '.' && d3 == '.')
            a = ipv4(b1, b2, b3, b4);
        else
            is.setstate(std::ios_base::failbit);
        return is;
    }

    ipv4& operator++()
    {
        *this = ipv4(1 + to_ulong());
        return *this;
    }

    ipv4 operator++(int)
    {
        ipv4 result(*this);
        ++(*this);
        return result;
    }

    friend bool operator==(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return a1.data == a2.data;
    }

    friend bool operator!=(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return !(a1 == a2);
    }

    friend bool operator<(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return a1.to_ulong() < a2.to_ulong();
    }

    friend bool operator>(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return a2 < a1;
    }

    friend bool operator<=(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return !(a1 > a2);
    }

    friend bool operator>=(ipv4 const &a1, ipv4 const &a2) noexcept
    {
        return !(a1 < a2);
    }
};


int main() {
    ipv4 address(192, 168, 0, 1);
    std::cout << address << std::endl;

    ipv4 ip;
    std::cout << ip << std::endl;
    std::cin >> ip;
    if (!std::cin.fail())
        std::cout << ip << std::endl;

    // ip address range
    std::cout << "Input Range: ";
    ipv4 a1, a2;
    std::cin >> a1 >> a2;
    if (a2 > a1)
    {
        for (ipv4 a = a1; a <= a2; a++)
        {
            std::cout << a << std::endl;
        }
    }
    else
    {
        std::cerr << "invalid range!" << std::endl;
    }
}

運行效果

192.168.0.1
0.0.0.0
[input]192.168.0.10
192.168.0.10
Input Range: [input]192.168.0.2 192.168.0.7
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7

小結

沒什麼,好像挺簡單的。這個例子用來複習一下運算符重載是個很不錯的。通過運算符重載,枚舉給定範圍的 IP 地址非常地自然。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章