CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  其它技术问题

饼子堂比武贴——判断合法的IP地址

楼主laomai(老迈)2005-12-30 14:17:55 在 C/C++ / 其它技术问题 提问

这次的比武内容是写一个函数,判断输入的字符串(传入时已经保证为空,且以\0结束)是否为合法的IP地址。语言为C。  
          具体要求:  
  1、如果字符串范围在”0.0.0.0到255.255.255.255“内,为合法,返回1;否则非法,返回0。  
  2、每个不能非零数字前不能有0,如032.32.34.56或者12.028.93.78均视为不规范写法  
  3、尽量不要使用c的库函数  
  4、尽量不要重新复制一遍字符串  
  5、尽量不要修改原字符串  
  6、使用合适个数个局部变量  
  7、尽量做到占用的内存少,速度快,效率高  
  目前帖子先给0分,待有好的答案后酌情加分,呵呵  
   
  问题点数:0、回复次数:168Top

1 楼laomai(老迈)回复于 2005-12-30 14:19:01 得分 0

再补充一点,数字形式都是十进制形式的Top

2 楼fiftymetre(50米深蓝)回复于 2005-12-30 14:19:03 得分 0

1Top

3 楼healer_kx(甘草(楼主揭贴吧,我们这些上班灌水的也不容易))回复于 2005-12-30 14:21:35 得分 0

师父...我  
  string   ip  
   
  ip.repalce('.',   '   ')  
   
  tokens   =   ip.gettokens()  
   
  foreach   num   in   tokens  
          check   num  
   
  Top

4 楼goodname(叶落知秋)回复于 2005-12-30 14:28:35 得分 0

使用合适的c的库函数或者不使用库函数均可。Top

5 楼piaozi2003()回复于 2005-12-30 14:50:05 得分 0

UNIX下比较简单的,用脚本+正则表达式写个可执行脚本,然后在C的函数里执行脚本,检查返回值!哈哈!暴简单,或者直接把脚本作为字符串写在C里,然后调用执行函数执行就可以了,又快又方便Top

6 楼Echone902(阿莫)回复于 2005-12-30 14:54:55 得分 0

看看Top

7 楼piaozi2003()回复于 2005-12-30 15:01:12 得分 0

然后考虑到题目要求的第二条,在匹配经典的IPv4地址的正则表达式后在用grep去掉各部分的前导0就可以了,哈哈!比单纯的去用C做方便多了!Top

8 楼lexchou(龍子龍孫)(本人已死)(有事烧纸)回复于 2005-12-30 15:17:40 得分 0

#define   IS_BYTE(a)   ((a)>=0   &&   (a)<=255)  
  int   check_ip(char*s)  
  {  
  int   a(-1),b(-1),c(-1),d(-1);  
  sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d);  
   
  return   IS_BYTE(a)   &&   IS_BYTE(b)   &&   IS_BYTE(c)   &&   IS_BYTE(d);  
  }  
   
   
  int   main(int   argc,   char*   argv[])  
  {  
  char*ips[]={"127.0.0.1","127.0.0.267"};  
  for(int   i=0;i<sizeof(ips)/sizeof(char*);i++)  
  printf("%s   %s   right   ip\n",ips[i],check_ip(ips[i])?"is":"isn't");  
   
  }  
   
  heheTop

9 楼lexchou(龍子龍孫)(本人已死)(有事烧纸)回复于 2005-12-30 15:23:24 得分 0

改以下:  
  #define   IS_BYTE(a)   ((a)>=0   &&   (a)<=255)  
  int   check_ip(char*s)  
  {  
  int   a(-1),b(-1),c(-1),d(-1);  
  char   holder[100]={0};  
  sscanf(s,"%d.%d.%d.%d%s",&a,&b,&c,&d,holder);  
  return   IS_BYTE(a)   &&   IS_BYTE(b)   &&   IS_BYTE(c)   &&   IS_BYTE(d)   &&   strlen(holder)==0;  
  }  
   
  int   main(int   argc,   char*   argv[])  
  {  
  char*ips[]={  
  "127.0.0",  
  "127.0.0.267",  
  "127.4.2.33ff",  
  "127.4.2.33"  
   
  };  
  for(int   i=0;i<sizeof(ips)/sizeof(char*);i++)  
  printf("%s   %s   right   ip\n",ips[i],check_ip(ips[i])?"is":"isn't");  
   
  }Top

10 楼fct0906(bighammer)回复于 2005-12-30 15:43:35 得分 0

做了一个普通版本的,没什么奇思妙想,旨在抛砖引玉  
   
  int   isValideIP(const   char*   addr)  
  {  
  assert(addr);  
   
  int   lastdot   =   0,    
  dotcnt   =   0,  
  i   =   0,  
  val   =   0;  
  char   ch   =   addr[i++];  
   
  while(ch   !=   0){  
  if((ch   <   '0'   ||   ch   >   '9')   &&   ch   !=   '.')    
  return   0;  
  if(i   -   lastdot   ==   1){  
  if(ch   ==   '.'   ||   ch   =   '0')  
  return   0;  
  }  
  val   *=   10;  
  val   +=   ch   -   '0';  
  if(   val   >   255)    
  return   0;  
  if(   ch   ==   '.'){  
  dotcnt++;  
  if(dotcnt   >   3)  
  return   0;  
  lastdot   =   i;  
  val   =   0;  
  }  
  ch   =   addr[i++];  
  }  
  }Top

11 楼fct0906(bighammer)回复于 2005-12-30 15:45:06 得分 0

晕倒,忘了在最后return   1;了Top

12 楼fct0906(bighammer)回复于 2005-12-30 15:52:27 得分 0

呜呜,发现了一个bug。。。  
  将修改过的再粘上:  
   
   
  int   isValideIP(const   char*   addr)  
  {  
  assert(addr);  
   
  int   lastdot   =   0,    
  dotcnt   =   0,  
  i   =   0,  
  val   =   0;  
  char   ch   =   addr[i++];  
   
  while(ch   !=   0){  
  if((ch   <   '0'   ||   ch   >   '9')   &&   ch   !=   '.')    
  return   0;  
  if(i   -   lastdot   ==   1){  
  if(ch   ==   '.')    
  return   0;  
  if(ch   ==   '0')   &&   (addr[i]   !=   '.')   //  
  return   0;  
  }  
  val   *=   10;  
  val   +=   ch   -   '0';  
  if(   val   >   255)    
  return   0;  
  if(   ch   ==   '.'){  
  dotcnt++;  
  if(dotcnt   >   3)  
  return   0;  
  lastdot   =   i;  
  val   =   0;  
  }  
  ch   =   addr[i++];  
  }  
  return   1;  
  }  
  Top

13 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2005-12-30 16:04:09 得分 0

/*还没入饼子堂,这里揍个热闹*/  
   
  #include   <stdio.h>  
   
   
  bool   IsIP(char   *ip)  
  {  
  int   pos=0;/*指示这是数字的第几个*/  
  int   count=0;/*数字个数*/  
  int   point=0;/*IP分隔符'.'个数*/  
  if(ip==NULL)   return   0;/*虽然题目说传入时已经保证不为空,但对传入的指针作判断,据说是个好习惯*/  
  while(*ip   !=   '\0')  
  {  
  if((*ip<'0'   ||   *ip>'9'   )   &&   *ip!='.'   )   return   0;/*非法字符*/  
  if(*ip=='0'     &&   pos==0   )   return   0;/*第一个字符为0*/  
  pos++;ip++;count++; /**/  
  if(*ip=='.'   ||   *ip=='\0')  
  {  
  if(count>3)   return   0;/*数字超长*/  
  if(count==3)    
  {  
  if(*(ip-count)>'2'       ||/*数字超大*/  
  *(ip-count)=='2'       &&   *(ip-count+1)>'5'   ||  
  *(ip-count)=='2'       &&   *(ip-count+1)=='5'     &&   *(ip-1)>'5'   )  
  return   0;  
  }  
  }  
  if(*ip=='.')  
  {  
  ip++;  
  point++;  
  pos=0;count=0;/*进入下段数字*/  
  }  
  }  
  if(point   !=3   )   return   0;/*IP分隔符'.'个数太多或太少*/  
  return   1;  
  }  
   
  int   main()  
  {  
  char   *c="202.20.20.260";  
  if(!IsIP(c))   printf("error:   %s     \n",c);  
  else   printf("OK   \n");  
  return   0;  
  }Top

14 楼txj_killer(流浪的天行)回复于 2005-12-30 16:17:58 得分 0

char   tab[24][11]   =   {{1,2,3,4,4,4,4,4,4,4,-1},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5},  
  {4,4,4,4,4,4,4,4,4,4,5},  
  {4,4,4,4,4,6,1,1,1,1,5},  
  {1,1,1,1,1,1,1,1,1,1,5},  
  {7,8,9,10,10,10,10,10,10,10,-1},  
  {1,1,1,1,1,1,-1,-1,-1,-1,5},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11},  
  {10,10,10,10,10,10,10,10,10,10,11},  
  {10,10,10,10,10,12,7,7,7,7,11},  
  {7,7,7,7,7,7,7,7,7,7,11},  
  {13,14,15,16,16,16,16,16,16,16,-1},  
  {7,7,7,7,7,7,-1,-1,-1,-1,11},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,17},  
  {16,16,16,16,16,16,16,16,16,16,17},  
  {16,16,16,16,16,18,13,13,13,13,17},  
  {13,13,13,13,13,13,13,13,13,13,17},  
  {19,20,21,22,22,22,22,22,22,22,-1},  
  {13,13,13,13,13,13,-1,-1,-1,-1,17},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},  
  {22,22,22,22,22,22,22,22,22,22,-1},  
  {22,22,22,22,22,23,19,19,19,19,-1},  
  {19,19,19,19,19,19,19,19,19,19,-1},  
  {19,19,19,19,19,19,-1,-1,-1,-1,-1}};  
   
  int   isValIP(const   char*   ip)  
  {  
  if(ip   !=   NULL)  
  {  
  int   stat   =   0;  
  for(const   char*   tmp   =   ip;   *tmp   !=   '\0';   ++tmp)  
  {  
  if('0'   <=   *tmp   &&   *tmp   <=   '9')  
  stat   =   tab[stat][*tmp   -   '0'];  
  else   if(*tmp   ==   '.')  
  stat   =   tab[stat][10];  
  }  
  if(stat   >=   19   &&   stat   <=   23)  
  return   1;  
  }  
  return   0;  
  }Top

15 楼txj_killer(流浪的天行)回复于 2005-12-30 16:18:53 得分 0

把正则表达式写正确花了点时间,汗颜啊。。。Top

16 楼txj_killer(流浪的天行)回复于 2005-12-30 16:22:57 得分 0

那个循环头部要改成这样:  
  for(const   char*   tmp   =   ip;   *tmp   !=   '\0'   &&   stat   >   0;   ++tmp)  
   
  否则就越界鸟。。。汗死。。。Top

17 楼arden1019(CSCUM)回复于 2005-12-30 16:28:28 得分 0

lexchou哥哥:C里面有int   a(-1),b(-1),c(-1),d(-1);   这样的句子么?  
   
  不过你的程序,很好,学习了...  
  Top

18 楼foochow(无聊,灌水......)回复于 2005-12-30 16:39:12 得分 0

卖烧饼,卖烧饼.....Top

19 楼windking21(想玩玩WOW 真的那么难吗)回复于 2005-12-30 17:05:59 得分 0

改以下:  
  #define   IS_BYTE(a)   ((a)>=0   &&   (a)<=255)  
  int   check_ip(char*s)  
  {  
  int   a(-1),b(-1),c(-1),d(-1);  
  char   holder[100]={0};  
  sscanf(s,"%d.%d.%d.%d%s",&a,&b,&c,&d,holder);  
  return   IS_BYTE(a)   &&   IS_BYTE(b)   &&   IS_BYTE(c)   &&   IS_BYTE(d)   &&   strlen(holder)==0;  
  }  
   
  int   main(int   argc,   char*   argv[])  
  {  
  char*ips[]={  
  "127.0.0",  
  "127.0.0.267",  
  "127.4.2.33ff",  
  "127.4.2.33"  
   
  };  
  for(int   i=0;i<sizeof(ips)/sizeof(char*);i++)  
  printf("%s   %s   right   ip\n",ips[i],check_ip(ips[i])?"is":"isn't");  
   
  }  
   
   
   
  "127.4.02.33"     不符合要求啊...不过已经不错了Top

20 楼arden1019(CSCUM)回复于 2005-12-30 17:14:40 得分 0

txj_killer(流浪的天行)   :  
   
  能讲讲你的算法么?我头大了...Top

21 楼txj_killer(流浪的天行)回复于 2005-12-30 17:20:15 得分 0

我就是写的正则表达式,然后转换为有限自动机,具体算法参见形式语言与自动机理论、编译原理等书籍。Top

22 楼txj_killer(流浪的天行)回复于 2005-12-30 17:21:24 得分 0

这个玩意儿的正则表达式如下:  
   
  (((1[0-9]?)|[3-9]|(2[0-4]?))[0-9]?|2(5[0-5]?|[6-9])|0)\.(((1[0-9]?)|[3-9]|(2[0-4]?))[0-9]?|2(5[0-5]?|[6-9])|0)\.(((1[0-9]?)|[3-9]|(2[0-4]?))[0-9]?|2(5[0-5]?|[6-9])|0)\.(((1[0-9]?)|[3-9]|(2[0-4]?))[0-9]?|2(5[0-5]?|[6-9])|0)Top

23 楼dragonzxh(河马MiaMia~柯奶奶和黑爷爷的儿子叫柯南...~)回复于 2005-12-30 17:26:22 得分 0

偶来写个最烂的,没有用任何库函数的。有错大家表骂偶。。。。  
   
   
  #define   IS_CHECK_VALUE(a,valueFirst,valueSecond)   (((a)>=(valueFirst))&&((a)<=(valueSecond)))  
  char*   Foo(char   Array[])  
  {  
  int   value   =   0;  
  static   int   j   =0;  
  if   (Array   ==   NULL)  
  {  
  return   Array;  
  }  
  char*   p   =   Array;  
  for   (int   i=0;p!=NULL;p++,i++)  
  {  
  char*   store   =   Array;  
  if   (*p=='.')  
  {  
  store[i]='\0';  
  //ArrayStore[j]   =   store;  
  if   (i>3)//3   is   Num   1   is   '\0'  
  return   "False";  
  switch(i)    
  {  
  case   1:  
  if(!IS_CHECK_VALUE(store[0],'1','9'))  
  return   "False";  
  break;  
  case   2:  
  if   (!(IS_CHECK_VALUE(store[0],'1','9')&&IS_CHECK_VALUE(store[1],'0','9')))  
  return   "False";  
  case   3:  
  if   (!(IS_CHECK_VALUE(store[0],'1','2')&&IS_CHECK_VALUE(store[1],'0','5')&&IS_CHECK_VALUE(store[2],'0','9')))  
  if   (!(store[1]=='5'&&IS_CHECK_VALUE(store[2],0,5)))  
  return   "False";  
  return   "False";  
  default:  
  break;  
  }  
   
  j++;  
  p++;  
  return   Foo(p);  
  }  
  if   (*p=='\0')  
  {  
  j++;  
  return   Array;  
  }  
  }  
  return   Array;  
  }  
  void   main()  
  {  
  char   Array[]   =   {"259.123.123.023"};  
   
  if   (Foo(Array)!="False")  
  {  
  cout<<"TRUE"<<endl;  
  }  
   
  system("pause");  
  }  
   
  Top

24 楼cunsh(村少)回复于 2005-12-30 17:54:20 得分 0

评三好饼子的题?Top

25 楼zhuanyejiefen(不给我分,下次就不顶你帖子了)回复于 2005-12-30 18:57:26 得分 0

插句嘴  
  请问饼子指什么Top

26 楼wohenbuzhidao(沉没)回复于 2005-12-30 19:01:14 得分 0

先踩个脚,想想Top

27 楼Jupin(T357)回复于 2005-12-30 19:05:04 得分 0

  回复人:txj_killer(流浪的天行)   (   一级(初级))   信誉:100   2005-12-30   17:20:00   得分:0  
  ?    
  我就是写的正则表达式,然后转换为有限自动机,具体算法参见形式语言与自动机理论、编译原理等书籍。  
   
   
  能提供一些相关资源连接吗?Top

28 楼txj_killer(流浪的天行)回复于 2005-12-30 19:43:05 得分 0

这方面电子版的资源暂时没有,纸版的书Jupin(T357)到china-pub搜搜看,有很多经典书籍都值得一读:)Top

29 楼llf_hust()回复于 2005-12-30 20:15:03 得分 0

bool   Cip::CipCheckIp(char   *str)//a   rough   check  
  {  
        int   dot_count   =   0;  
        int   num_count   =   0;  
        int   num_val   =   0;  
        while((*str))  
      {  
            if((*str)   !=   '.')  
            {  
                  if((*str)   <=   '9'   &&   (*str)   >=   '0')  
                  {  
                          ++   num_count;  
                          num_val   =   num_val   *   10   +   (*str)   -   '0';  
                  }  
                  else  
                        return   false;  
              }  
              else  
              {  
                      ++   dot_count;  
                      if(num_count   <   1   ||   num_count   >   4   ||   num_val   <   0   ||   num_val   >255)  
                      //check   if   the   current   segment   is   1~3   numbers  
                      return   false;  
                      num_count   =   0;  
                      num_val   =   0;  
                }  
                ++   str;  
          }  
          if(dot_count   !=   3)  
                  return   false;  
          return   true;  
  }  
  Top

30 楼Jupin(T357)回复于 2005-12-30 20:19:38 得分 0

 
  我也写一个:  
  (?<IP1>25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)\.(?<IP2>25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)\.(?<IP3>25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)\.(?<IP4>25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)Top

31 楼lbaby(春天来了...)回复于 2005-12-30 21:10:11 得分 0

懒,看Top

32 楼hellobcb(学海无涯,回头是岸)回复于 2005-12-30 22:22:39 得分 0

如果准许用库函数的话:  
  #include   <stdio.h>  
  #include   <string.h>  
  #include   <stdlib.h>  
  int   IpCheck(char   *IP)  
  {  
      char   *temp,*end;  
      int   numDot=0;  
      long   length;  
       
  for(temp=strtok(IP,   ".");  
          temp   !=   NULL;  
          temp=strtok(NULL,   "."))  
        {  
        numDot++;  
        length=strtol(temp,&end,4);  
                if(length<0   ||   length>255   ||   strlen(end)!=0)  
          return   0;  
          }  
     
      if(numDot   !=   4)  
      return   0;  
      return   1;  
    }  
   
  int   main()  
  {  
  char   IP[15];  
  scanf("%s",IP);  
  printf("\n输入的IP%s合法",IpCheck(IP)?"":"不");  
      return   0;  
    }Top

33 楼fdimim(猿莫求愚√))回复于 2005-12-31 08:29:02 得分 0

markTop

34 楼alizhongren(天外孤星)回复于 2005-12-31 08:53:07 得分 0

悄悄地问一句   什么是“饼子堂”?Top

35 楼lone_512(圣斗士)回复于 2005-12-31 08:56:50 得分 0

int   testIP(char   sourceIP[])  
  {  
  uint   i   =   0;      
  uint   k   =   0;    
  uint   n1,n2,n3;  
  uint   n;  
  char   str[3];  
  char   str1[3];  
  while(1)  
  {  
  k   =   0;  
  for(   i   =   0;   i   <   strlen(sourceIP);   i++)  
  {  
  if(sourceIP[i]   ==   '.')  
  {  
  str[k]   =   i;  
  k++;  
  }  
  else    
  if(!isdigit(sourceIP[i]))  
  {  
  return   -1;  
  }  
  }  
  if(k   ==   3)  
  {  
  n1   =   str[0];  
  n2   =   str[1];  
  n3   =   str[2];  
  if(n1+1   ==   n2   ||   n2+1   ==   n3   ||   n1   ==   0   ||   n3   ==   strlen(sourceIP)-1)  
  {  
  return   -1;  
  }  
   
  else  
  {  
  memcpy(str1,sourceIP,n1);  
  n   =   atoi(str1);  
  if(n   >=   0   &&   n   <=   255)  
  {  
  memcpy(str1,sourceIP+n1+1,n2-n1-1);  
  n   =   atoi(str1);  
  if(n   >=   0   &&   n   <=   255)  
  {  
  memcpy(str1,sourceIP+n2+1,n3-n2-1);  
  n   =   atoi(str1);  
  if(n   >=   0   &&   n   <=   255)  
  {  
  memcpy(str1,sourceIP+n3+1,strlen(sourceIP)-n3-1);  
  n   =   atoi(str1);  
  if(n   >=   0   &&   n   <=   255)  
  {  
  return   0;  
  }  
  }  
  }  
  }  
  return   -1;  
  }  
   
  }  
   
  else  
  {  
  return   -1;  
  }  
  }  
  }  
  Top

36 楼ringphone(临风)回复于 2005-12-31 09:13:18 得分 0

markTop

37 楼weinickli(总有路,总没走)回复于 2005-12-31 09:50:26 得分 0

dingTop

38 楼goodname(叶落知秋)回复于 2005-12-31 09:51:42 得分 0

llf_hust()   的写法比较符合我心目中的写法。Top

39 楼nipcdll()回复于 2005-12-31 09:53:38 得分 0

学习Top

40 楼goodname(叶落知秋)回复于 2005-12-31 09:57:16 得分 0

稍觉有些不太完美的地方是对于运行效率来讲,  
  对dot_count变量的处理还有改进的空间。Top

41 楼goodname(叶落知秋)回复于 2005-12-31 10:06:27 得分 0

对于回复人:   lexchou(龍子龍孫)(本人已死)(有事烧纸)   的使用  
  sscanf的算法(我测试的修改后的帖子)  
   
  这个函数对于使用了类似127.0.0.           1中间出现空格的情况还不能正确辨认出来。Top

42 楼goodname(叶落知秋)回复于 2005-12-31 10:20:17 得分 0

回复人:   fct0906(bighammer)   的写法对于  
  127.0.0.1似乎无法正确辨认Top

43 楼txj_killer(流浪的天行)回复于 2005-12-31 10:30:04 得分 0

更正:  
  状态驱动少了两行:  
  else  
                  stat   =   -1;  
  汗。。。最近写代码比较少,手生,老出这种低级错误。。。  
  完整代码如下(同时去除全局表):  
   
  int   isValIP(const   char*   ip)  
  {  
  static   char   tab[24][11]   =   {{1,2,3,4,4,4,4,4,4,4,-1},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5},  
  {4,4,4,4,4,4,4,4,4,4,5},  
  {4,4,4,4,4,6,1,1,1,1,5},  
  {1,1,1,1,1,1,1,1,1,1,5},  
  {7,8,9,10,10,10,10,10,10,10,-1},  
  {1,1,1,1,1,1,-1,-1,-1,-1,5},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11},  
  {10,10,10,10,10,10,10,10,10,10,11},  
  {10,10,10,10,10,12,7,7,7,7,11},  
  {7,7,7,7,7,7,7,7,7,7,11},  
  {13,14,15,16,16,16,16,16,16,16,-1},  
  {7,7,7,7,7,7,-1,-1,-1,-1,11},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,17},  
  {16,16,16,16,16,16,16,16,16,16,17},  
  {16,16,16,16,16,18,13,13,13,13,17},  
  {13,13,13,13,13,13,13,13,13,13,17},  
  {19,20,21,22,22,22,22,22,22,22,-1},  
  {13,13,13,13,13,13,-1,-1,-1,-1,17},  
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},  
  {22,22,22,22,22,22,22,22,22,22,-1},  
  {22,22,22,22,22,23,19,19,19,19,-1},  
  {19,19,19,19,19,19,19,19,19,19,-1},  
  {19,19,19,19,19,19,-1,-1,-1,-1,-1}};  
  if(ip   !=   NULL)  
  {  
  int   stat   =   0;  
  for(const   char*   tmp   =   ip;   *tmp   !=   '\0'   &&   stat   >   0;   ++tmp)  
  {  
  if('0'   <=   *tmp   &&   *tmp   <=   '9')  
  stat   =   tab[stat][*tmp   -   '0'];  
  else   if(*tmp   ==   '.')  
  stat   =   tab[stat][10];  
  else  
  stat   =   -1;  
  }  
  if(stat   >=   19   &&   stat   <=   23)  
  return   1;  
  }  
  return   0;  
  }Top

44 楼goodname(叶落知秋)回复于 2005-12-31 10:32:23 得分 0

回复人:   A_B_C_ABC(黄瓜儿才起蒂蒂)   的写法无法辨认127.0.0.1  
  Top

45 楼txj_killer(流浪的天行)回复于 2005-12-31 10:35:20 得分 0

汗,又错了,  
  for(const   char*   tmp   =   ip;   *tmp   !=   '\0'   &&   stat   >   0;   ++tmp)  
  此行应为:  
  for(const   char*   tmp   =   ip;   *tmp   !=   '\0'   &&   stat   >=   0;   ++tmp)  
   
  这次应该不会再错了。。。Top

46 楼goodname(叶落知秋)回复于 2005-12-31 10:48:20 得分 0

回复人:   txj_killer(流浪的天行)的不能辨认127.0.0.1Top

47 楼tubowangxy()回复于 2005-12-31 10:55:11 得分 0

学习!不过看乱乎了!Top

48 楼txj_killer(流浪的天行)回复于 2005-12-31 10:59:52 得分 0

回复人:   txj_killer(流浪的天行)的不能辨认127.0.0.1  
  ——————————————————————————————————————  
  你用的肯定是前面的bug代码,如后面所说改正后绝对可以辨认Top

49 楼goodname(叶落知秋)回复于 2005-12-31 12:43:40 得分 0

回复人:   hellobcb(学海无涯,回头是岸)   (   )   信誉:100    
  的写法输入127.0.0.1不能正确辨认Top

50 楼Kernall()回复于 2005-12-31 12:47:22 得分 0

手动构造自动机Top

51 楼goodname(叶落知秋)回复于 2005-12-31 13:00:05 得分 0

回复人:   lone_512(圣斗士)   (   )   信誉:100    
  的写法有些复杂,不过大致意思是先取得点的位置,然后再拷贝  
  但是存放位置,却使用的char类型,这里我给你出了一个输入串的例子  
  第一个点之前有128个1,所以程序运行就越界了。  
   
   
  1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.1.1.1Top

52 楼goodname(叶落知秋)回复于 2005-12-31 13:11:08 得分 0

回复人:   dragonzxh(河马MiaMia~小雨特批C++非技术区技术灌水员~)    
  写的不是c语言的函数(不知道是否调试过?)  
  没有具体测试,但是看起来不知道是否对0<=x<=255作了正确的判断。  
   
  回复人:   txj_killer(流浪的天行)   (   )    
  修正后的代码,测试了一下,没有测出问题来,但是着实难以理解。  
  里面用了一个264个元素的二位数组,呵呵。  
  根据我们题目的要求,似乎有些占的内存稍微大了点,但是感觉运行速度应该比较快  
  等大家都写齐了,可以做个简单的测试,对于运行效率。  
   
   
  Top

53 楼Jupin(T357)回复于 2005-12-31 13:14:56 得分 0

这方面电子版的资源暂时没有,纸版的书Jupin(T357)到china-pub搜搜看,有很多经典书籍都值得一读:)  
   
  我只会用lex,但是你这种的写法,不像是用lex得到的啊,你是使用什么工具生成状态转移表的?  
  谢谢Top

54 楼goodname(叶落知秋)回复于 2005-12-31 13:21:59 得分 0

对于如何提高判断的效率,我的几点认识  
  1.  
  对于其字符串的判断,我认为,只要多于3个点的,就可以认定不合法了  
  没必要把整个字符串再进行处理了。  
  2.  
  对于点分的每一个段都是0-255的,所以多于3位,肯定是不合法的了,  
  没有必要再进行处理本段了,可以直接返回假了。  
  (llf_hust()   的代码对于这点并没有相关的处理,只是当碰到下一个点的时候判断了一下  
  所以如果碰到两个点之间特别长的位数的字符串,那么效率会严重下降)  
  其实,这里还有一个简单的特点,就是如果是个3位数字的话,那么开头的必定是0或者1  
  不知道这点特点能否用上。  
  3.  
  当你判断到第3个点之后,如果再往后长于3位的,肯定是非法的串了。  
   
   
  希望各位发出自己满意的作品来,具体要求参见楼顶的老迈。Top

55 楼goodname(叶落知秋)回复于 2005-12-31 13:24:01 得分 0

修正:  
  那么开头的必定是0(老迈的要求看来开头不能为0)或者1或者2Top

56 楼hellobcb(学海无涯,回头是岸)回复于 2005-12-31 13:58:22 得分 0

回复人:   hellobcb(学海无涯,回头是岸)   (   )   信誉:100    
  的写法输入127.0.0.1不能正确辨认  
  ------------------------------------  
  修改一下:  
  #include   <stdio.h>  
  #include   <string.h>  
  #include   <stdlib.h>  
  int   IpCheck(char   *IP)  
  {  
      char   *temp,*end;  
      int   numDot=0;  
      long   length;  
       
  for(temp=strtok(IP,   ".");  
          temp   !=   NULL;  
          temp=strtok(NULL,   "."))  
        {  
        numDot++;  
        length=strtol(temp,&end,10);//此处做了修改  
                if(length<0   ||   length>255   ||   strlen(end)!=0)  
          return   0;  
          }  
     
      if(numDot   !=   4)  
      return   0;  
      return   1;  
    }  
   
  int   main()  
  {  
  char   IP[15];  
  scanf("%s",IP);  
  printf("\n输入的IP%s合法",IpCheck(IP)?"":"不");  
      return   0;  
    }  
  Top

57 楼bborn(生命在于折腾)回复于 2005-12-31 14:07:07 得分 0

看看我的小程序  
  引用了txj_killer(流浪的天行)   的代码  
  http://bborn.cn/blog/article.asp?id=89  
  http://bborn.cn/blog/article.asp?id=87  
   
   
  可以屏幕取ip并查询Top

58 楼crcr(游侠)回复于 2005-12-31 14:14:17 得分 0

int   isValideIP(const   char*   addr)  
  {  
  assert(addr);  
   
  int   lastdot   =   0,    
  dotcnt   =   0,  
  i   =   0,  
  val   =   0;  
  char   ch   =   addr[i++];  
   
  while(ch   !=   0){  
  if((ch   <   '0'   ||   ch   >   '9')   &&   ch   !=   '.')    
  return   0;  
  if(i   -   lastdot   ==   1){  
  if(ch   ==   '.'   ||   ch   =   '0')  
  return   0;  
  }  
  val   *=   10;  
  val   +=   ch   -   '0';  
  if(   val   >   255)    
  return   0;  
  if(   ch   ==   '.'){  
  dotcnt++;  
  if(dotcnt   >   3)  
  return   0;  
  lastdot   =   i;  
  val   =   0;  
  }  
  ch   =   addr[i++];  
  }  
  }  
   
  Top

59 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2005-12-31 14:37:43 得分 0

和第一版改动不大:  
   
   
  #include   <stdio.h>  
   
   
  bool   IsIP(char   *ip)  
  {  
  int   pos=0;/*指示这是数字的第几个*/  
  int   count=0;/*数字个数*/  
  int   point=0;/*IP分隔符'.'个数*/  
  if(ip==NULL)   return   0;/*虽然题目说传入时已经保证不为空,但对传入的指针作判断,据说是个好习惯*/  
  while(*ip   !=   '\0')  
  {  
  if((*ip<'0'   ||   *ip>'9'   )   &&   *ip!='.'   )   return   0;/*非法字符*/  
  if(*ip=='0'     &&   pos==0     &&   (*(ip+1)!='.')   )   return   0;/*第一个字符为0*/  
  pos++;ip++;count++;/**/  
  if(*ip=='.'   ||   *ip=='\0')  
  {  
  if(count>3)   return   0;/*数字超长*/  
  if(count==3)    
  {  
  if(*(ip-count)>'2'       ||/*数字超大*/  
  *(ip-3)=='2'       &&   *(ip-2)>'5'   ||  
  *(ip-3)=='2'       &&   *(ip-2)=='5'     &&   *(ip-1)>'5'   )  
  return   0;  
  }  
  }  
  if(*ip=='.')  
  {  
  ip++;  
  point++;  
  pos=0;count=0;/*进入下段数字*/  
  }  
  }  
  if(point   !=3   )   return   0;/*IP分隔符'.'个数太多或太少*/  
  return   1;  
  }  
   
  int   main()  
  {  
  char   *c="127.0.0.1";  
  if(!IsIP(c))   printf("error:   %s     \n",c);  
  else   printf("OK   :   %s     \n",c);  
  return   0;  
  }  
   
  Top

60 楼megaboy(飞天御剑流之杀神一刀斩)回复于 2005-12-31 15:10:38 得分 0

这个过程其实只需要对0和.以及数值的大小进行判断就OK了,数值的大小不需要费时地用乘法和加法进行转换,直接判断数字的数量及大小就可,只需要几个判断就OK。整个过程只需要遍历一次。  
   
  int   scanip(char   *cpSource)  
  {  
  char   *cpTemp=cpSource;  
  int   iCount=0;  
  if(*cpSource   <   0x30   ||   *cpSource   >   0x39)   return   0;  
  if(*cpSource   ==   0x30   &&   *(cpSource+1)   !=   '.')   return   0;  
  while(*++cpSource)  
  {  
  if(!(*cpSource   ==   '.'   ||   (*cpSource   >=0x30   &&   *cpSource   <=   0x39)))   return   0;  
  if(*cpSource   ==   0x30)  
  {  
  if(*(cpSource-1)   ==   '.')  
  {  
  if(*(cpSource+1)   !=   '.'   &&   *(cpSource+1)   !=   '\0')   return   0;  
  }  
  }  
  if(*cpSource   ==   '.')  
  {  
  if(++iCount   >   3   ||   *(cpSource+1)   ==   '.'   ||   *(cpSource+1)   ==   '\0'   ||   cpSource-cpTemp   >   3)   return   0;  
  if(cpSource-cpTemp   ==   3)  
  {  
  if(*cpTemp   >   0x32)   return   0;  
  if(*cpTemp   ==   0x32)  
  {  
  if(*(cpTemp+1)   >   0x35)   return   0;  
  if(*(cpTemp+1)   ==   0x35)   if(*(cpTemp+2)   >   0x35)   return   0;  
  }  
  }  
  cpTemp   =   cpSource+1;  
  }  
  }  
  if(iCount   !=   3)   return   0;  
  return   1;  
  }Top

61 楼goodname(叶落知秋)回复于 2005-12-31 15:41:54 得分 0

回复人:   hellobcb(学海无涯,回头是岸)    
  的新的程序认为127.0.0.       1中间包括空格的情况是合法的地址Top

62 楼goodname(叶落知秋)回复于 2005-12-31 16:01:13 得分 0

回复人:   crcr(游侠)   (   )  
  的新的程序认为127.0.0.       1中间包括空格的情况是合法的地址  
   
  回复人:   A_B_C_ABC(黄瓜儿才起蒂蒂)    
  运行正确,暂时没有找到反例,但是对于  
  int   point=0;/*IP分隔符'.'个数*/  
  的处理仍然不理想,只要有3个点以上,在循环内就可以返回假了Top

63 楼goodname(叶落知秋)回复于 2005-12-31 16:03:21 得分 0

回复人:   megaboy(飞天御剑流之杀神一刀斩)    
  的程序认为  
  127.0.0.1111是个合法的ip地址Top

64 楼txj_killer(流浪的天行)回复于 2005-12-31 16:18:36 得分 0

回复人:   txj_killer(流浪的天行)   (   )    
  修正后的代码,测试了一下,没有测出问题来,但是着实难以理解。  
  里面用了一个264个元素的二位数组,呵呵。  
  根据我们题目的要求,似乎有些占的内存稍微大了点,但是感觉运行速度应该比较快  
  等大家都写齐了,可以做个简单的测试,对于运行效率。  
   
  _______________________________________________________  
   
  这个代码就是个最简单的自动机,相应正则表达式我前面已经放出来了,只需要一个正则分析程序就可以得出相应状态转换表(也就是我用的那个数组了),正则分析程序我用的是我以前写的一个东东,使用加点项算法,现在改进中,适当的时候我会放出源码。  
   
  就运行速度来说,我还是相信我的那个是最快的,一次遍历,而且遍历过程只有状态转换(简单赋值),没有任何多余操作。至于空间占用,是会比其它代码多一些,但是二百多byte实在是可以忽略不计,一个缓冲页面都是几k,除非是在非常苛刻的嵌入式环境,否则这点内存占用可以当它不存在了,呵呵^_^Top

65 楼goodname(叶落知秋)回复于 2005-12-31 16:24:43 得分 0

呵呵,目前我就是想要用到嵌入式的开发上。  
  设备对通讯控制器的ip地址进行判断。Top

66 楼txj_killer(流浪的天行)回复于 2005-12-31 16:27:34 得分 0

to:Jupin(T357)  
   
  刚刚看到你的回复,我的正则是自己仿造javascript规则简化了一下定的,如上所说,正则分析也是用自己写的一个东东,源码适当的时候我会放出:)Top

67 楼lexchou(龍子龍孫)(本人已死)(有事烧纸)回复于 2005-12-31 16:31:13 得分 0

我的代码能算最短的了   (#-_-)Top

68 楼txj_killer(流浪的天行)回复于 2005-12-31 16:32:24 得分 0

to:goodname(叶落知秋)  
   
  寒,那就比较惨了,如果是关键路径上的功能,速度第一,可以考虑这样损失一点内存,甚至可以考虑把这个算法固化。但如果只是偶尔用用,还是用别的算法好了。  
   
  另外,这个状态转换表应该是还能压缩的,相关算法计划过一阵子研究,呵呵^_^Top

69 楼ztwz(-_-b(偶要像海绵一样的狂吸水水!))回复于 2005-12-31 16:36:57 得分 0

顶...  
  学习。。。。Top

70 楼megaboy(飞天御剑流之杀神一刀斩)回复于 2005-12-31 16:43:57 得分 0

HOHO,真的哦,程序修改一下:  
   
   
  int   scanip(char   *cpSource)  
  {  
  char   *cpTemp=cpSource;  
  int   iCount=0;  
  if(*cpSource   <   0x30   ||   *cpSource   >   0x39)   return   0;  
  if(*cpSource   ==   0x30   &&   *(cpSource+1)   !=   '.')   return   0;  
  do  
  {  
                                  ++cpSource;  
  if(!(*cpSource   ==   '.'   ||   *cpSource   ==   '\0'   ||   (*cpSource   >=0x30   &&   *cpSource   <=   0x39)))   return   0;  
  if(*cpSource   ==   0x30)  
  {  
  if(*(cpSource-1)   ==   '.')  
  {  
  if(*(cpSource+1)   !=   '.'   &&   *(cpSource+1)   !=   '\0')   return   0;  
  }  
  }  
  if(*cpSource   ==   '.'     ||   *cpSource   ==   '\0')  
  {  
  if(*cpSource   ==   '.'   &&   (++iCount   >   3   ||   *(cpSource+1)   ==   '.'   ||   *(cpSource+1)   ==   '\0'))   return   0;  
  if(cpSource-cpTemp   >   3)   return   0;  
  if(cpSource-cpTemp   ==   3)  
  {  
  if(*cpTemp   >   0x32)   return   0;  
  if(*cpTemp   ==   0x32)  
  {  
  if(*(cpTemp+1)   >   0x35)   return   0;  
  if(*(cpTemp+1)   ==   0x35)   if(*(cpTemp+2)   >   0x35)   return   0;  
  }  
  }  
  cpTemp   =   cpSource+1;  
  }  
  }  
  while(*cpSource);  
  if(iCount   !=   3)   return   0;  
  return   1;  
  }Top

71 楼goodluckyxl(被人遗忘的狗)回复于 2005-12-31 17:17:10 得分 0

1.检测格式   '.'的数目合理性  
  2.检测每个域的数据合理性  
  3.检测域的长度(考虑0打头形式是否合理)和边界合理性    
  overTop

72 楼hellobcb(学海无涯,回头是岸)回复于 2005-12-31 18:50:12 得分 0

回复人:   goodname(叶落知秋)   (   )   信誉:100     2005-12-31   15:41:00     得分:   0      
     
     
        回复人:   hellobcb(学海无涯,回头是岸)    
  的新的程序认为127.0.0.       1中间包括空格的情况是合法的地址  
       
     
  ---------------------------  
  我的编译器显示为非法  
  gccTop

73 楼happydivid(泓笑)回复于 2005-12-31 19:19:25 得分 0

考完试,回来就见如此强贴!  
  学习!!Top

74 楼Jupin(T357)回复于 2005-12-31 21:41:48 得分 0

刚刚看到你的回复,我的正则是自己仿造javascript规则简化了一下定的,如上所说,正则分析也是用自己写的一个东东,源码适当的时候我会放出:)  
   
  等   待:)  
  想想,应该把lex的那个搬过来用,也是可以的,今晚试试看Top

75 楼justrun2005(机枪)回复于 2005-12-31 23:11:15 得分 0

简单说下思路,代码就不写了。  
  显然ip都有4个段被3个“.”隔开。所以设一整变量记录之,初值为一每遇到一个点加一。  
  下面是判断段内值是否合法的循环:  
  当元素大于'0'小于等于'9'时且其后元素不是'.'进入循环,先判断元素是不是'\0',如果是自然得出错误结论。如果该元素也不是'   ',将之val=(val)*10+ip[i]-30   val是整型初为0,并判断val的值是否在0--255之间,否则什么也不做继续循环到下一元素。如果比255大了显然不合法直接报错结束程序。  
  下面是段数记录的循环:  
  如果段数小于5进入循环,判断段内值合法性的循环就在这个循环内包含,内循环结束后要将val清零,两个循环都基于同一个下标变量i。也就是说i的值保留到下一次循环。  
   
  看起来难度不大。刚考完期末试,身心疲惫中。村长看着给分吧。Top

76 楼justrun2005(机枪)回复于 2005-12-31 23:17:46 得分 0

汗,竟然把0漏了。  
  简单说下思路,代码就不写了。  
  显然ip都有4个段被3个“.”隔开。所以设一整变量记录之,初值为一每遇到一个点加一。  
  下面是判断段内值是否合法的循环:  
  当元素大于'0'小于等于'9'时且其后元素不是'.'进入循环,先判断元素是不是'\0',如果是自然得出错误结论。如果该元素也不是'   ',将之val=(val)*10+ip[i]-30   val是整型初为0,并判断val的值是否在0--255之间,否则什么也不做继续循环到下一元素。如果比255大了显然不合法直接报错结束程序。  
  下面是段数记录的循环:  
  如果段数小于5进入循环,先判断当前元素是否等于'0',否则进入上面判断段内值合法性的循环,上个循环就在这个循环内包含,内循环结束后要将val清零,两个循环都基于同一个下标变量i。也就是说i的值保留到下一次循环。  
   
  看起来难度不大。刚考完期末试,身心疲惫中。村长看着给分吧Top

77 楼boyzhang(张郎)(爱你爱到Windows没BUG的那天)回复于 2006-01-01 00:20:57 得分 0

'最有效的判断方法     :)  
  dim   Ret   as   string  
  dim   IP   as   string  
  ip=inputbox("请输入要判断的IP地址")  
  ret=msgbox(ip   &   "是一个合法的IP地址吗?",vbyesno,"询问?")  
  if   ret=vbyes   then  
                  '合法  
  else  
                  '非法  
  end   ifTop

78 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-01-01 09:51:38 得分 0

前两个版本未经仔细测试。其中第二个版本对127.0.1.0判断错误。  
  这第三个版本,再有人发现判断错误的,我愿开帖送50分。  
   
   
   
  #include   <stdio.h>  
   
   
  int   IsIP(char   *ip)  
  {  
  int   pos=0;/*指示这是数字的第几个*/  
  int   count=0;/*数字个数*/  
  int   point=0;/*IP分隔符'.'个数*/  
  if(ip==NULL)   return   0;/*虽然题目说传入时已经保证不为空,但对传入的指针作判断,据说是个好习惯*/  
  while(*ip   !=   '\0')  
  {  
  if((*ip<'0'   ||   *ip>'9'   )   &&   *ip   !=   '.'   )   return   0;/*非法字符*/  
  if(*ip=='0'     &&   pos==0     &&   (*(ip+1)!='.'     &&   *(ip+1)!='\0')   )   return   0;/*第一个字符为0*/  
  if(*ip   !=     '.'   )  
  {  
  pos++;ip++;count++;  
  }  
  else  
  {  
  if(count>3   ||/*数字超长*/  
                    count==0/*出现了两个点之间没有数字*/  
                      )   return   0;  
  if(count==3)    
  {  
  if(*(ip-count)>'2'       ||/*数字超大*/  
  *(ip-3)=='2'       &&   *(ip-2)>'5'   ||  
  *(ip-3)=='2'       &&   *(ip-2)=='5'     &&   *(ip-1)>'5'   )  
  return   0;  
  }  
  ip++;  
  point++;  
  pos=0;count=0;/*进入下段数字*/  
  }  
  }  
          /*串结尾处理*/  
  if(count>3   ||/*数字超长*/  
  count==0/*最后一个字符为'.'*/  
  )   return   0;  
  if(count==3)    
  {  
  if(*(ip-count)>'2'       ||/*数字超大*/  
  *(ip-3)=='2'       &&   *(ip-2)>'5'   ||  
  *(ip-3)=='2'       &&   *(ip-2)=='5'     &&   *(ip-1)>'5'   )  
  return   0;  
  }  
   
  if(point   !=3   )   return   0;/*IP分隔符'.'个数太多或太少*/  
  return   1;  
  }  
  /*当出出现127.1.2.3.4.5.6.7.8.9这样的长非法IP时,    
  函数的里的循环必须执行完才能判断是否非法,有人  
  说效率不高。简单的解决办法是在每次point增加时  
  判断其是否大于3,若大于3则return   0。我的考虑  
  是这样的,很多的非法IP应是非法字符或数字域不对,  
  出现这种长非法IP的可能性非常小。“每次point增加时  
  判断其是否大于3”对这种长非法IP的判断,效率是有所  
  提高,但对其他情况的判断效率却有所下降,结果对大多数  
  判断得不尝失。*/  
   
  int   main()  
  {  
  char   *c="127.111.2.3";  
  if(IsIP(c))   printf("OK   :   %s     \n",c);  
  else printf("error:   %s     \n",c);  
  return   0;  
  }  
  Top

79 楼hellobcb(学海无涯,回头是岸)回复于 2006-01-01 12:03:20 得分 0

#include   <stdio.h>  
  int   IpCheck1(char   *IP)  
  {  
  int   numI=0;  
  int   numD=0;  
  char   numT[3];  
  while(*IP)  
  {  
      if(*IP   >=   '0'   &&   *IP   <=   '9'   &&   numI<3)  
            {    
  if(numI==0)  
      {  
        if(*IP   !=   '0')     //允许211.0123.4.3这种情况的存在,虽然不规范  
              numT[numI++]=*IP;  
                        }  
    else              
        numT[numI++]=*IP;  
         
  if(numI   ==   3)  
        {  
            if(numT[0]>'2')    
            return   0;  
        else   if(numT[0]   ==   '2')  
            {  
  if(numT[1]   >   '5')  
        return   0;  
  else   if(numT[1]   ==   '5')  
        if(numT[2]>'5')             return   0;  
            }  
  }  
          }  
  else   if(*IP   ==   '.')  
        {    
          if(numI   ==0   )   //如果一开始就出现'.'  
  return   0;  
          numI=0;  
          numD++;  
        }  
  else  
        return   0;  
  IP++;  
  }  
  if(numD++   !=   3)//   '.'应该有三个  
        return   0;  
  return   1;  
  }  
   
  int   main()  
  {  
  char   IP[15];  
  gets(IP);  
  printf("\n输入的IP%s合法",IpCheck1(IP)?"":"不");  
      return   0;  
    }Top

80 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2006-01-01 12:30:42 得分 0

靠,原来是叶子大哥用呀,我还以为老迈用呢......  
   
  我把程序发给老迈了,就没帖出来  
   
  感觉还算过得去,明天帖出来看看吧,自己没测出什么问题,不过可能是因为自己考虑的不全  
  Top

81 楼hongmu(红木)回复于 2006-01-01 14:44:26 得分 0

呵呵,这个题的快速实现应该是一次把一个字装入寄存器中,并进行其中单一字节的检测。  
  需要注意的是大小端和机器字长(64位的CPU效率会更高),其具体检测过程用加减和位运算应该可以满足,分支过程不会太多。  
   
  -------------------------------------------  
  上面那位的正则表达式扫描器的算法并没有利用好寄存器Top

82 楼superworker(走出江湖)回复于 2006-01-02 12:17:51 得分 0

献丑了,贴一个自己写的:  
  -------------------------------------------------------------------------------------  
  #include   <stdio.h>  
   
  int   myatoi(const   char   *   ipaddr,   char   **   pstr)   {  
          char   c[4]   =   {0,   0,   0,0};  
          int     k;  
          if(ipaddr   ==   NULL)   return   -1;  
          for(k   =   0;k   <   3;k   ++)   {  
                  if(*ipaddr   ==   '.'||*ipaddr   ==   0)   break;  
                  if(*ipaddr   <   '0'||*ipaddr   >   '9')   return   -1;  
                  c[k]   =   *ipaddr;  
                  ipaddr   ++;  
          }  
          *pstr   =   (char   *)ipaddr;  
          switch(k)   {  
          case   0:  
                  return   -1;  
          case   1:  
                  return   1;  
          case   2:  
                  if(c[0]   ==   '0')   return   -1;  
                  return     1;  
          case   3:  
                  if(c[0]   ==   '0')   return   -1;  
                  if(((c[0]   -   '0')   *   100   +   (c[1]   -   '0')   *   10   +   c[2]   -   48)   >   255)    
                          return   -1;  
                  return   1;  
          }  
  }  
   
  int   checkip(const   char   *   ipaddr)   {  
          int         k;  
          char   *   pstr;  
          for(k   =   0;k   <   4;k   ++)   {  
                  if(myatoi(ipaddr,   &pstr)   ==   -1)   return   0;  
                  if(*pstr   ==   0)   break;  
                  ipaddr   =   pstr   +   1;  
          }  
          if(k   !=   3||*pstr)   return   0;  
          return   1;  
  }  
   
  int   main(int   argc,   char   **   argv)   {  
          int   ret;  
          if(argc   !=   2)   {  
                  fprintf(stderr,   "Error,   parameter\n");  
                  return   1;  
          }  
          ret   =   checkip(argv[1]);  
          fprintf(stdout,   "checkip:   %d\n",   ret);  
          return   ret;  
  }  
  -------------------------------------------------------------------------------------Top

83 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2006-01-02 12:18:40 得分 0

#include   <stdio.h>  
   
  int   checkIp(const   char*   ip)   {  
  int   i   =   0;  
  int   count   =   0;  
  while   (1)  
  {  
  if   (count   >   3)  
  return   0;  
  if   (((*(ip   +   i)   ==   '1')   &&   (*(ip   +   i   +   1)   >=   '0'   &&   *(ip   +   i   +   1)   <=   '9')   &&   (*(ip   +   i   +   2)   >=   '0'   &&   *(ip   +   i   +   2)   <=   '9'))  
  ||   ((*(ip   +   i)   ==   '2')   &&   (*(ip   +   i   +   1)   >=   '0'   &&   *(ip   +   i   +   1)   <=   '5')   &&   (*(ip   +   i   +   2)   >=   '0'   &&   *(ip   +   i   +   2)   <=   '5')))  
  {  
  if   (*(ip   +   i   +   3)   !=   '\0'   &&   *(ip   +   i   +   3)   !=   '.')  
  return   0;  
  else   if   (*(ip   +   i   +   3)   ==   '\0'   ||   *(ip   +   i   +   4)   ==   '\0')  
            break;  
  else  
  {  
  i   =   i   +   4;  
  count   ++;  
  continue;  
  }  
  }  
  else   if   ((*(ip   +   i)   >   '0'   &&   *(ip   +   i)   <=   '9')   &&   (*(ip   +   i   +   1)   >=   '0'   &&   *(ip   +   i   +   1)   <=   '9'))  
  {  
  if   (*(ip   +   i   +   2)   !=   '\0'   &&   *(ip   +   i   +   2)   !=   '.')  
  return   0;  
  else   if   (*(ip   +   i   +   2)   ==   '\0'   ||   *(ip   +   i   +   3)   ==   '\0')  
            break;  
                          else  
  {  
  i   =   i   +   3;  
  count   ++;  
  continue;  
  }    
  }  
  else   if   (*(ip   +   i)   >=   '0'   &&   *(ip   +   i)   <=   '9')  
  {                          
  if   (*(ip   +   i   +   1)   !=   '\0'   &&   *(ip   +   i   +   1)   !=   '.')  
  return   0;  
  else   if   (*(ip   +   i   +   1)   ==   '\0'   ||   *(ip   +   i   +   2)   ==   '\0')  
            break;  
  else  
  {  
  i   =   i   +   2;  
  count   ++;  
  continue;  
  }  
  }  
  else    
  return   0;  
  }  
  if   (count   <   3)  
  {  
  return   0;  
  }  
  return   1;  
  }  
  int   main(int   argc,   char   *argv[])    
  {  
  char   *ipaddrs[]   =   {"127.0.0.1",   "A.2.3.6",   "0xd.4.7.",   ".....",   "123.123.123.123.123.",    
                                                "+.3.5.-3","6.58.123.57.0.","0.123.123.111.01.",   "1234.123.123.123",   "a,123,123,123"  
                                                ,"1.123.012.123",   "1.1a.111.111",   "1.12.02.12","123.123.123.12"};  
  int   j;  
  for   (j   =   0;   j   <   14;   j++)  
  {  
  if   (checkIp(ipaddrs[j]))   {  
  printf("%20s",ipaddrs[j]);  
  printf("     is     true\n");  
  }  
  else   {  
  printf("%20s",ipaddrs[j]);  
  printf("     is     false\n");  
  }  
  }  
  return   0;  
  }  
  Top

84 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2006-01-02 12:28:29 得分 0

完了,完了,本来看着还可以的代码,帖上来就死了,呵呵  
   
  用了两个变量,效率应该常数级的吧,也不用遍历全部字符串,只是不知道考虑的全不全,空间占用一定是不多,只是速度我不会算,呵呵,叶子哥帮看看吧  
   
  Top

85 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2006-01-02 12:31:22 得分 0

汗,本来代码写的难看米好意思发出来,不过看到天行的代码不错,想学习学习,只好把回复当mark用了...  
   
  一灌作风,连回三次..........,叶子哥表介意哈Top

86 楼Jupin(T357)回复于 2006-01-02 15:36:24 得分 0

static   int   s_chIpCheckState[][12]   =    
  {  
          {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},  
          {   2,   3,   6,   4,   4,   4,   4,   4,   4,   4,-1,-1},  
          {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,   7,-1},  
          {   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   7,-1},  
          {   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   7,-1},  
          {   2,   2,   2,   2,   2,   2,-1,-1,-1,-1,   7,-1},  
          {   4,   4,   4,   4,   4,   5,   2,   2,   2,   2,   7,-1},  
          {   8,   9,12,10,10,10,10,10,10,10,-1,-1},  
          {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,13,-1},  
          {10,10,10,10,10,10,10,10,10,10,13,-1},  
          {   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,13,-1},  
          {   8,   8,   8,   8,   8,   8,-1,-1,-1,-1,13,-1},  
          {10,10,10,10,10,11,   8,   8,   8,   8,13,-1},  
          {14,15,18,16,16,16,16,16,16,16,-1,-1},  
          {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,19,-1},  
          {16,16,16,16,16,16,16,16,16,16,19,-1},  
          {14,14,14,14,14,14,14,14,14,14,19,-1},  
          {14,14,14,14,14,14,-1,-1,-1,-1,19,-1},  
          {16,16,16,16,16,17,14,14,14,14,19,-1},  
          {20,21,24,22,22,22,22,22,22,22,-1,-1},  
          {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,   0},  
          {22,22,22,22,22,22,22,22,22,22,-1,   0},  
          {20,20,20,20,20,20,20,20,20,20,-1,   0},  
          {20,20,20,20,20,20,-1,-1,-1,-1,-1,   0},  
          {22,22,22,22,22,23,20,20,20,20,-1,   0},  
  };  
  int   bIsValidIp(char   *ipStr)  
  {  
   
  register   char   *pchTmp   =   ipStr;  
  int   chState   =   1;  
   
  for   (;   ;pchTmp++)  
  {  
  if   ('0'   <=   *pchTmp   &&   *pchTmp   <=   '9')  
  chState   =   s_chIpCheckState[chState][*pchTmp   -   '0'];  
  else   if   (*pchTmp   ==   '.')  
  chState   =   s_chIpCheckState[chState][10];  
  else   if   (*pchTmp   ==   '\0')  
  return   s_chIpCheckState[chState][11]   ==   0;  
  if   (chState   ==   -1)  
  return   0;  
  }  
  }  
  我也写一个依据有限状态机实现的。Top

87 楼languagec(各有所求)回复于 2006-01-02 20:54:55 得分 0

村长的帖呀!!  
  Top

88 楼dragonzxh(河马MiaMia~柯奶奶和黑爷爷的儿子叫柯南...~)回复于 2006-01-03 11:13:53 得分 0

靠.打死不离师兄弟,上阵不离父子兵,貌似点点师兄跟偶的写的一样滴...MMD...  
  偶都觉得够烂了,你还帖,哇哈哈哈哈Top

89 楼0000000009()回复于 2006-01-03 16:41:24 得分 0

只用一个临时变量,没用库函数的  
   
  int   f(char*   p)  
  {  
   
  int   t;  
   
  while(*p   !=   '\0')  
  {  
   
   
  if(   (*(p+1)=='.'   ||   *(p+1)=='\0'   )   &&   *p   ==   '0'   )  
  {  
  p   +=   2;  
  continue;  
  }  
   
  if(*p   <   '1'   ||   *p   >'9')  
  return   0;  
   
  t   =     (   (int)*p   -   48   )   *   10;  
   
  if(   *(++p)   ==   '\0')   break;  
   
  if(*(p)=='.')  
  {  
  p++;  
  continue;  
  }  
   
  if(*p   <   '0'   ||   *p   >'9')  
  return   0;  
   
  t   +=     (   (int)*p   -   48   );  
   
  if(*(++p)=='.')  
  {  
  p++;  
  continue;  
  }  
   
  if(   *p   ==   '\0')   break;  
   
  if(*p   <   '0'   ||   *p   >'9')  
  return   0;  
   
  t   *=   10;  
  t   +=     (   (int)*p   -   48   );  
   
  if(t>255)  
  return   0;  
   
  if(   *(++p)   ==   '\0')   break;  
  if(   *(p)   !=   '.')  
  return   0;  
   
  p++;  
  }  
   
  return   1;  
   
  };Top

90 楼steedhorse(晨星)回复于 2006-01-03 18:01:51 得分 0

“传入时已经保证为空”。。。.....  
  那还判个P啊,直接return   false;不就得了吗?  
   
  ^0^Top

91 楼BluntBlade(信仰迷离·重构之道,在于Redo/Undo之间)回复于 2006-01-03 18:57:28 得分 0

全是手工硬编码啊……那还要Lex做什么……Top

92 楼languagec(各有所求)回复于 2006-01-03 19:34:09 得分 0

我贴个测试程序吧,村长一个一个调也累的,我测试过这里的每一个程序,有几个能给出现有数据的正确结果.  
   
  #include   "stdio.h"  
   
   
  int   isLegalIp(char   *   )  
  {  
  }  
   
   
  int   main()  
  {  
   
  char   *   ip[]={  
  "0.0.0.0",  
  "00.11.22.33",  
  "2147483657.1.2.3",  
  ".2.35.12.4",  
  "1.02.3.5",  
  "1.2.3.5",  
  "5..1.1",  
  "2.3.6.5.",  
  "56,41.154.5"  
  };  
  int   size=sizeof(ip)/sizeof(ip[0]);  
  while(--size>=0)  
  {  
  if(isLegalIp(ip[size]))  
  printf("legal   %s\n",ip[size]);  
  else  
  printf("unlegal   %s\n",ip[size]);  
  }  
  return   0;  
  }Top

93 楼Shatty(西北游侠)回复于 2006-01-03 22:51:46 得分 0

学习ing!!Top

94 楼nchang(御月)回复于 2006-01-04 15:16:59 得分 0

用languagec(这个射手不太准)的测试过了的,不过我又针对我的程序加了几个unlegal:"12.12.255.0.14","176.56.33.333"  
  /*程序还是希望可以追求最简,而且逻辑清楚*/  
  bool   CheckIP(   char   *p)  
  {  
  int   i,val,count(0);  
  val   =   -1;   /*这里没有初始为0,而是做了个标志-1,就是为了判断是否会出现最高位为0的情况*/  
  while(*p   !=   '\0')  
  {  
  if(   *p   ==   '.')  
  {  
  if(val   <0   ||   val   >255)  
  return   false;  
  else  
  {  
  val   =   -1;  
  count++;  
  }  
  }  
  else  
  {  
  i   =   *p   -'0';  
  if(   i>=0   &&i<=9)  
  {  
  if(val   ==   0)  
  return   false;  
  else   if(val   ==   -1)  
  val   =   i;  
  else  
  val   =   val*10+i;  
  }  
                  else  
  return   false;  
  }  
  p++;  
  }  
  if(count   >   3   ||   val   <0   ||   val   >255)   /*这个判断是绝对不能少的*/  
  return   false;    
  return   true;  
  }  
  /*这是我目前可以想出的最直接最简洁的一种判断逻辑了,欢迎诸位拍砖,bow~~*/Top

95 楼Leomaxking(害怕孤独,但已习惯孤独)回复于 2006-01-04 18:02:49 得分 0

凑热闹Top

96 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2006-01-04 18:48:59 得分 0

回复人:   dragonzxh(河马MiaMia~小雨特批C++非技术区技术灌水员~)   (   )   信誉:100     2006-1-3   11:13:54     得分:   0      
     
     
         
  靠.打死不离师兄弟,上阵不离父子兵,貌似点点师兄跟偶的写的一样滴...MMD...  
  偶都觉得够烂了,你还帖,哇哈哈哈哈  
   
  //==========  
  呵呵,木有办法呀,不回复这个程序,就不敢灌水呀.......,容易被减性欲呀  
   
  这个就全当程序灌水了Top

97 楼virm(查无此人)回复于 2006-01-04 21:19:34 得分 0

经过测试的代码  
   
  /*   检查   是否合法的IP地址   */  
  #include   <stdio.h>  
   
  int   isLegalIp(char   *IP)  
  {  
  int   bytesleave=3;  
  char   lastChar='.';  
  int   curdigital=0;  
  while(*IP)  
  {  
  if(*IP   !=   '.'   &&   (*IP   >   '9'   &&   *IP   <   '0')   /*   必须为限定字符   */  
  ||   lastChar   ==   '.'   &&   *IP   ==   '.'   )   /*   两.之间必须有数字*/  
  return   0;  
  if(lastChar=='.'   &&   *IP=='0')   /*   处理   0   开头的数   */  
  {  
  char   nextchar   =   *(++IP);  
  if(!bytesleave) /*   最后一个数字0最后只能接   NULL   */  
  return   0==nextchar;  
  if('.'   !=   nextchar)   /*   非最后则必须接'.'   */  
  return   0;  
  --bytesleave;  
  }else   if(*IP   ==   '.'){ /*   处理分割符   */  
  if(!bytesleave--)  
  return   0;  
  curdigital   =   0;  
  }else{ /*   处理数字   */  
  curdigital   =   curdigital*10   +   *IP   -   '0';  
  if(curdigital   >   255)  
  return   0;  
  }  
  lastChar   =   *IP;  
  ++IP;  
  }  
  return   1;  
  }  
   
  int   main()  
  {  
   
  char   *   ip[]={  
  "0.0.0.0",  
  "00.11.22.33",  
  "2147483657.1.2.3",  
  ".2.ab.12.4",  
  "1.02.3.5",  
  "1.2.3.5",  
  "5..1.1",  
  "255.256.1.1",  
  "0.12.0.123",  
  "5.21.1.1",  
  "2.3.6.5.",  
  "56,41.154.5"  
  };  
  int   size=sizeof(ip)/sizeof(ip[0]);  
  while(--size>=0)  
  {  
  if(isLegalIp(ip[size]))  
  printf("legal   %s\n",ip[size]);  
  else  
  printf("unlegal   %s\n",ip[size]);  
  }  
  return   0;  
  }  
  Top

98 楼virm(查无此人)回复于 2006-01-04 21:31:55 得分 0

上一帖有误,最后返回的不是   return   1;   而是   return   !bytesleave;Top

99 楼YFY(天易)回复于 2006-01-04 22:26:28 得分 0

考虑考虑再写。Top

100 楼languagec(各有所求)回复于 2006-01-05 09:44:52 得分 0

#include   "stdio.h"  
  #define   ISNUM(X)   (   (X)>='0'   &&   (X)<='9')  
   
  int   LegalIp(char   *ip)  
  {  
  int   sum;  
  int   count=0;  
  char   *pre;  
  while(*ip)  
  {  
  if(ISNUM(*ip))  
  {  
  count++;  
  sum=0;  
  pre=ip;  
  while(   ISNUM(*ip)   )  
  {  
  sum=sum*10+   *ip-'0';  
  ip++;  
  if(sum>255) return   0;  
  }  
   
  if(sum==0   &&   ip-pre!=1) return   0;  
  if(sum!=0   &&   *pre=='0') return   0;  
   
  if(*ip=='.'   &&   count<4)  
  ip++;  
  else   if(*ip==0   &&   count==4)  
  return   1;  
  else  
  return   0;  
  }  
  else return   0;  
  }  
  return   1;  
  }  
   
  int   main()  
  {  
   
  char   *   ip[]={  
  "0.0.0.0",  
  "00.11.22.33",  
  "2147483657.1.2.3",  
  ".2.ab.12.4",  
  "1.02.3.5",  
  "1.2.3.5",  
  "5..1.1",  
  "255.256.1.1",  
  "0.12.0.123",  
  "5.21.1.1",  
  "2.3.6.5.",  
  "56,41.154.5",  
  "1.2.3.4.5"  
  };  
  int   size=sizeof(ip)/sizeof(ip[0]);  
  while(--size>=0)  
  {  
  if(LegalIp(ip[size]))  
  printf("legal   %s\n",ip[size]);  
  else  
  printf("unlegal   %s\n",ip[size]);  
  }  
  return   0;  
  }  
   
   
   
   
  Top

101 楼languagec(各有所求)回复于 2006-01-05 16:26:32 得分 0

对大家帖的代码进行了测试,测试结果如下:  
  在现有测试数据下得到的结果,环境   vc6.0  
   
  错误结果  
   
  A_B_C_ABC(黄瓜儿才起蒂蒂)    
  unlegal   1.2.3.4.5  
  unlegal   56,41.154.5  
  unlegal   2.3.6.5.  
  unlegal   255.256.1.1  
  unlegal   5..1.1  
  unlegal   1.02.3.5  
  unlegal   .2.ab.12.4  
  unlegal   2147483657.1.2.3  
  unlegal   00.11.22.33  
  unlegal   0.255.0.255  
  legal   1.2.3.5  
  legal   255.255.255.255  
  unlegal   0.0.0.0  
   
   
  txj_killer(流浪的天行)  
  unlegal   1.2.3.4.5  
  unlegal   56,41.154.5  
  unlegal   2.3.6.5.  
  unlegal   255.256.1.1  
  unlegal   5..1.1  
  unlegal   1.02.3.5  
  unlegal   .2.ab.12.4  
  legal   2147483657.1.2.3  
  unlegal   00.11.22.33  
  legal   0.255.0.255  
  legal   1.2.3.5  
  legal   255.255.255.255  
  legal   0.0.0.0  
   
  windking21(想玩玩WOW   真的那么难吗)    
  unlegal   1.2.3.4.5  
  unlegal   56,41.154.5  
  unlegal   2.3.6.5.  
  unlegal   255.256.1.1  
  unlegal   5..1.1  
  legal   1.02.3.5  
  unlegal   .2.ab.12.4  
  unlegal   2147483657.1.2.3  
  legal   00.11.22.33  
  legal   0.255.0.255  
  legal   1.2.3.5  
  legal   255.255.255.255  
  legal   0.0.0.0  
   
   
   
  dragonzxh(河马MiaMia~小雨特批C++非技术区技术灌水员~)    
  不符合题意  
   
   
  llf_hust()    
  unlegal   1.2.3.4.5  
  unlegal   56,41.154.5  
  unlegal   2.3.6.5.  
  unlegal   255.256.1.1  
  unlegal   5..1.1  
  legal   1.02.3.5  
  unlegal   .2.ab.12.4  
  unlegal   2147483657.1.2.3  
  legal   00.11.22.33  
  legal   0.255.0.255  
  legal   1.2.3.5  
  legal   255.255.255.255  
  legal   0.0.0.0  
   
   
    hellobcb(学海无涯,回头是岸)    
  执行时出错  
   
   
    lone_512(圣斗士)    
  unlegal   1.2.3.4.5  
  unlegal   56,41.154.5  
  unlegal   2.3.6.5.  
  un