如何用前导零填充 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"
再次感慨:
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.1
对 127.0.0.1
有效。
0177.1
或 0x7f.1
也是如此
我在网上看到用 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"
再次感慨:
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.1
对 127.0.0.1
有效。
0177.1
或 0x7f.1