C++判断IP地址字符串的合法性

目前的解决方法可以归为以下三类:

1、自己动手写:以'.'将IP字符串分割成子串,再依次判断每个子串的每个字符是否都是数字,最后转换成值,判断是否在0~255的范围。

/* 
功能: 
    判断IP地址是否有效 
接口函数: 
    booli sIPAddressValid ( const char *  pszIPAddr ) 
输入:  
    pszIPAddr  字符串 
输出: 
    true 有效的IP地址,false,无效的IP地址 
约束: 
    1.输入IP为XXX.XXX.XXX.XXX格式 
    2.字符串两端含有空格认为是合法IP 
    3.字符串中间含有空格认为是不合法IP 
    4.类似于 01.1.1.1, 1.02.3.4  IP子段以0开头为不合法IP 
    5.子段为单个0 认为是合法IP,0.0.0.0也算合法I 
*/  
#include <iostream>  
#include <cstring>  
using namespace std;  
  
bool isIPAddressValid(const char* pszIPAddr)  
{  
    if (!pszIPAddr) return false; //若pszIPAddr为空  
    char IP1[100],cIP[4];  
    int len = strlen(pszIPAddr);  
    int i = 0,j=len-1;  
    int k, m = 0,n=0,num=0;  
    //去除首尾空格(取出从i-1到j+1之间的字符):  
    while (pszIPAddr[i++] == ' ');  
    while (pszIPAddr[j--] == ' ');  
      
    for (k = i-1; k <= j+1; k++)  
    {  
        IP1[m++] = *(pszIPAddr + k);  
    }       
    IP1[m] = '\0';  
      
    char *p = IP1;  
  
    while (*p!= '\0')  
    {  
        if (*p == ' ' || *p<'0' || *p>'9') return false;  
        cIP[n++] = *p; //保存每个子段的第一个字符,用于之后判断该子段是否为0开头  
  
        int sum = 0;  //sum为每一子段的数值,应在0到255之间  
        while (*p != '.'&&*p != '\0')  
        {  
          if (*p == ' ' || *p<'0' || *p>'9') return false;  
          sum = sum * 10 + *p-48;  //每一子段字符串转化为整数  
          p++;  
        }  
        if (*p == '.') {  
            if ((*(p - 1) >= '0'&&*(p - 1) <= '9') && (*(p + 1) >= '0'&&*(p + 1) <= '9'))//判断"."前后是否有数字,若无,则为无效IP,如“1.1.127.”  
                num++;  //记录“.”出现的次数,不能大于3  
            else  
                return false;  
        };  
        if ((sum > 255) || (sum > 0 && cIP[0] =='0')||num>3) return false;//若子段的值>255或为0开头的非0子段或“.”的数目>3,则为无效IP  
  
        if (*p != '\0') p++;  
        n = 0;  
    }  
    if (num != 3) return false;  
    return true;  
}  
  
void main()  
{  
    char IP[] = " 254.1.1.1 ";  
    //char IP[100];  
    //cin >> IP;  
    bool tf = isIPAddressValid(IP);  
    cout << tf<<endl;  
    system("pause");  
}  

别人给的一个解决方案也很不错,充分利用了atoi函数的特性:遇到有字符的时候,只转换字符前的数字;转换完毕把字符串数组指针向后移。

2、使用inet_addr(const char * str)函数。inet_addr()的功能是将一个点分十进制的IP转换成一个长整数型数(u_long类型)。丢给这个函数一个字符串,能成功转换就是合法的IP地址字符串,转换失败返回INADDR_NONE。若是不允许非标准形式的IP地址,则再加上对'.'的个数的判断。另外,INADDR_NONE即为255.255.255.255,因此此地址字符串不能正确转换。

3、利用正则表达式!这个编写代码的效率又高又容易保证正确性,又容易维护。需要用boost中的regex库。唯一的缺点是,这是个静态链接库,编译的时候会慢一点,打包的时候体积也会增加。

// boostTest.cpp : 定义控制台应用程序的入口点。  
//  
  
#include "stdafx.h"  
#include <iostream>     
#include <boost/xpressive/xpressive_dynamic.hpp>  
  
//BOOST用正则表达式验证ip地址合法  
bool CheckIP(const char *ip)  
{  
    using namespace boost::xpressive;  
    /* 定义正则表达式 */  
    cregex reg_ip = cregex::compile("(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])");   
    return  regex_match(ip, reg_ip);  
}  
  
int _tmain(int argc, _TCHAR* argv[])    
{    
    std::wcout<<"ip:"<<CheckIP("1247.0.0.1");  
  
    getchar();    
    return 0;    
}  

perl正则表达式语法
        perl正则表达式语法可参见《perl语言入门》第7、8、9章或boost的文档。这里列出的语法是不全面的,而且部分说明可能并不清楚。

        . 任意字符;使用match_no_dot_null标志时不匹配NULL字符; 使用match_not_dot_newline时不匹配换行字符

        ^ 匹配行的开始
        $ 匹配行的结束
        * 重复零次或则更多,例如a*b可匹配b,ab,aab,aaaaaaab
        + 重复一次以上,例如a+b可匹配ab,aab,aaaaaaaab。但不能匹配b了
        ? 零次或则一次,例如ca?b匹配cb,cab但不匹被caab    
        a{n} 匹配字符''a''重复n次
        a{n,},字符a重复n次以上(含n次)
        a{n,m} a重复n到m次(含)

        *?   匹配前一个原子零次以上
        +?   匹配前一个原子一次以上
        ??   匹配前一个原子零次以上
        {n,}?  匹配前一个原子n次以上(含)
        {n,m?  匹配前一个原子n到m次(含)

        | 或操作,例如ab(d|ef)匹配abd或则abef
        [] 字符集操作,例如[abc]将匹配任何单个字符''a'',''b'',''c''
        [a-d],表示a、b、c、d
        ^否操作,例如[^a-c]表示a至c之外的所有字符


4、swscanf()函数,简洁高效

BOOL isIpFormatRight(LPTSTR ipAddress)
{//判断IP地址是否合法
int a,b,c,d;
if ((swscanf(ipAddress,L"%d.%d.%d.%d",&a,&b,&c,&d)==4)
&&(a>=0&&a<=255)
&&(b>=0&&b<=255)
&&(c>=0&&c<=255)
&&(d>=0&&d<=255))
{
return TRUE;
}
return FALSE;
}



  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值