如何用前导零填充 IP 地址

How to pad an IP address with leading zeroes

我在网上看到用 C 编写的解决方案,但我想要一种 C++ 方法来用零填充 IPv4 地址。

网上找到的C代码

using namespace std;

#include<iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void padZeroIP(char *str)
{
    int oct1=0;
    int oct2=0;
    int oct3=0;
    int oct4=0;

    int i = 0;

    const char s[2] = ".";
    char *token;
    
    /* get the first token */
    token = strtok(str, s);

    oct1 = atoi(token);
    
    /* walk through other tokens */
    while( token != NULL ) 
    {
        token = strtok(NULL, s);
        
        if(i==0)
            oct2 = atoi(token);
        else if(i==1)
            oct3 = atoi(token);
        else if(i==2)
            oct4 = atoi(token);
        i++;
    }

    sprintf(str,"%03d.%03d.%03d.%03d",oct1,oct2,oct3,oct4);
}

这是我的解决方案,首先使用 boost 根据分隔符(句点)分隔字符串。

// standard
#include <vector>
#include <string>

// boost
#include <boost/tokenizer.hpp>

std::vector<std::string> delimiter_str_to_svec(std::string delimiter_str, std::string delimiter)
{
    std::vector<std::string> svec;
    typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
    boost::char_separator<char> sepa(delimiter.c_str());
    tokenizer tokens(delimiter_str, sepa);

    for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
    {
        try
        {
            svec.push_back(*tok_iter);
        }
        catch (boost::bad_lexical_cast &)
        {
            std::cerr << "bad lexical cast; *tok_iter = " << *tok_iter << std::endl;
        }
    }

    return svec;
}

std::string pad_ip_with_zeroes(std::string ip_address)
{
    std::string ret;
    std::vector<std::string> ip_octets;

    // get octets of IP address
    ip_octets = delimiter_str_to_svec(ip_address, ".");

    // pad octets with zeroes
    for (size_t i = 0; i < ip_octets.size(); i++)
    {
        // add zeroes if there are less than 3 numbers
        if (ip_octets.at(i).length() < 3)
        {
            ip_octets.at(i).insert(0, (3 - ip_octets.at(i).length()), '0'); // insert zeroes at front of string
        }

        // add to return
        ret += ip_octets.at(i) + ".";
    }

    // remove last period
    ret.pop_back();

    return ret;
}

例子

192.168.2.2 变为 192.168.002.002,或 10.0.0.2 变为 010.000.000.002

#include <sstream>
#include <string>
#include <iomanip>

std::string padZeroIP(const std::string &str)
{
    std::istringstream iss(str);
    std::ostringstream oss;

    std::string token;
    bool first = true;

    while (std::getline(iss, token, '.'))
    {
        if (first)
            first = false;
        else
            oss << '.';

        int oct = std::stoi(token);
        oss << std::setw(3) << std::setfill('0') << oct;
    }

    return oss.str();
}
#include <iostream>

std::cout << padZeroIP("192.168.0.1"); // prints "192.168.000.001"

Online Demo

再次感慨:

std::string padZeroIP(const std::string& str)
{
    using boost::asio::ip::address_v4;
    auto ip = address_v4::from_string(str).to_bytes();

    std::string result(16, '[=10=]');

    std::snprintf(result.data(), result.size(), //
                  "%03d.%03d.%03d.%03d",        //
                  ip[0], ip[1], ip[2], ip[3]);

    result.resize(15);

    return result;
}

这并不假设输入是有效的,也不会重新发明轮子。看看吧Live On Coliru:

   127.0.0.1 -> 127.000.000.001
     1.1.1.1 -> 001.001.001.001

OVERKILL

请记住,IPv4 地址可以采用多种形式,例如127.1127.0.0.1 有效。 0177.10x7f.1

也是如此