这是一个简单的类,它使用 boost::xpressive 来完成验证 IP 地址类型的工作,然后您可以解析其余部分以获得结果。
用法:
const std::string ip_address_str = "127.0.0.1:3282";
IpAddress ip_address = IpAddress::Parse(ip_address_str);
std::cout<<"Input String: "<<ip_address_str<<std::endl;
std::cout<<"Address Type: "<<IpAddress::TypeToString(ip_address.getType())<<std::endl;
if (ip_address.getType() != IpAddress::Unknown)
{
std::cout<<"Host Address: "<<ip_address.getHostAddress()<<std::endl;
if (ip_address.getPortNumber() != 0)
{
std::cout<<"Port Number: "<<ip_address.getPortNumber()<<std::endl;
}
}
类的头文件,IpAddress.h
#pragma once
#ifndef __IpAddress_H__
#define __IpAddress_H__
#include <string>
class IpAddress
{
public:
enum Type
{
Unknown,
IpV4,
IpV6
};
~IpAddress(void);
/**
* \brief Gets the host address part of the IP address.
* \author Abi
* \date 02/06/2010
* \return The host address part of the IP address.
**/
const std::string& getHostAddress() const;
/**
* \brief Gets the port number part of the address if any.
* \author Abi
* \date 02/06/2010
* \return The port number.
**/
unsigned short getPortNumber() const;
/**
* \brief Gets the type of the IP address.
* \author Abi
* \date 02/06/2010
* \return The type.
**/
IpAddress::Type getType() const;
/**
* \fn static IpAddress Parse(const std::string& ip_address_str)
*
* \brief Parses a given string to an IP address.
* \author Abi
* \date 02/06/2010
* \param ip_address_str The ip address string to be parsed.
* \return Returns the parsed IP address. If the IP address is
* invalid then the IpAddress instance returned will have its
* type set to IpAddress::Unknown
**/
static IpAddress Parse(const std::string& ip_address_str);
/**
* \brief Converts the given type to string.
* \author Abi
* \date 02/06/2010
* \param address_type Type of the address to be converted to string.
* \return String form of the given address type.
**/
static std::string TypeToString(IpAddress::Type address_type);
private:
IpAddress(void);
Type m_type;
std::string m_hostAddress;
unsigned short m_portNumber;
};
#endif // __IpAddress_H__
类的源文件,IpAddress.cpp
#include "IpAddress.h"
#include <boost/xpressive/xpressive.hpp>
namespace bxp = boost::xpressive;
static const std::string RegExIpV4_IpFormatHost = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]+(\\:[0-9]{1,5})?$";
static const std::string RegExIpV4_StringHost = "^[A-Za-z0-9]+(\\:[0-9]+)?$";
IpAddress::IpAddress(void)
:m_type(Unknown)
,m_portNumber(0)
{
}
IpAddress::~IpAddress(void)
{
}
IpAddress IpAddress::Parse( const std::string& ip_address_str )
{
IpAddress ipaddress;
bxp::sregex ip_regex = bxp::sregex::compile(RegExIpV4_IpFormatHost);
bxp::sregex str_regex = bxp::sregex::compile(RegExIpV4_StringHost);
bxp::smatch match;
if (bxp::regex_match(ip_address_str, match, ip_regex) || bxp::regex_match(ip_address_str, match, str_regex))
{
ipaddress.m_type = IpV4;
// Anything before the last ':' (if any) is the host address
std::string::size_type colon_index = ip_address_str.find_last_of(':');
if (std::string::npos == colon_index)
{
ipaddress.m_portNumber = 0;
ipaddress.m_hostAddress = ip_address_str;
}else{
ipaddress.m_hostAddress = ip_address_str.substr(0, colon_index);
ipaddress.m_portNumber = atoi(ip_address_str.substr(colon_index+1).c_str());
}
}
return ipaddress;
}
std::string IpAddress::TypeToString( Type address_type )
{
std::string result = "Unknown";
switch(address_type)
{
case IpV4:
result = "IP Address Version 4";
break;
case IpV6:
result = "IP Address Version 6";
break;
}
return result;
}
const std::string& IpAddress::getHostAddress() const
{
return m_hostAddress;
}
unsigned short IpAddress::getPortNumber() const
{
return m_portNumber;
}
IpAddress::Type IpAddress::getType() const
{
return m_type;
}
我只为 IPv4 设置了规则,因为我不知道 IPv6 的正确格式。但我很确定实现它并不难。 Boost Xpressive 只是一个基于模板的解决方案,因此不需要将任何 .lib 文件编译到您的 exe 中,我认为这是一个加分项。
顺便说一下,简单地分解正则表达式的格式...
^ = 字符串开头
$ = 字符串结尾
[] = 可以出现的一组字母或数字
[0-9] = 0 到 9 之间的任何一位数字
[0-9]+ = 0 到 9 之间的一位或多位数字
这 '。'对于正则表达式有特殊含义,但由于我们的格式在 ip 地址格式中有 1 个点,我们需要指定我们想要一个 '.'使用'\.'在数字之间。但由于 C++ 需要 '\' 的转义序列,我们必须使用 "\\."
? = 可选组件
所以,简而言之,"^[0-9]+$" 代表一个正则表达式,对于整数也是如此。
"^[0-9]+ \.$" 表示以 '.' 结尾的整数
"^[0-9]+\.[0-9]?$" 是整数以“。”结尾或小数。
对于整数或实数,正则表达式为 "^[0-9]+(\.[0-9]*)?$"。
RegEx 一个介于 2 到 3 个数字之间的整数是 "^[0-9]{2,3}$"。
现在来分解一下ip地址的格式:
"^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]+(\\:[0-9]{1,5})?$"
这是同义词:“^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9 ]+(\:[0-9]{1,5})?$",表示:
[start of string][1-3 digits].[1-3 digits].[1-3 digits].[1-3 digits]<:[1-5 digits]>[end of string]
Where, [] are mandatory and <> are optional
第二个 RegEx 比这更简单。它只是一个字母数字值后跟可选冒号和端口号的组合。
顺便说一句,如果您想测试 RegEx,您可以使用 this site。
编辑:我没有注意到您可以选择使用 http 而不是端口号。为此,您可以将表达式更改为:
"^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]+(\\:([0-9]{1,5}|http|ftp|smtp))?$"
这接受以下格式:
127.0.0.1
127.0.0.1:3282
127.0.0.1:http
217.0.0.1:ftp
18.123.2.1:smtp