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

来源:互联网 发布:美工刀片怎么掰断 编辑:程序博客网 时间:2024/05/16 10:12

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

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;}



原创粉丝点击