• C++实现的字符串模糊匹配


    C++基本没有正则表达式功能,当然像Boost里提供了正则。本文来源于博客园园友的一篇文章,请看:

    C/C++ 字符串模糊匹配

    很早之前就看过这篇文章,原作者的需求很明确、代码实现也很好。

    之所以又写这篇文章,是因为原作者只介绍了在Linux系统下直接调用系统函数fnmatch即可实现,而没有考虑在Windows在的使用。

    本人这周看了下Google-glog代码,恰巧发现了一个类似fnmatch的简单实现,因此综合起来提供了一个跨平台的接口。

    直接拿原作者的需求为例(再次感谢原作者大熊先生,我这是拿来主义了):

    需求:

      准入授权配置文件有时候分了好几个维度进行配置,例如 company|product|sys这种格式的配置:

    1.配置 "sina|weibo|pusher" 表示 sina公司weibo产品pusher系统能够准入,而"sina|weibo|sign"不允许准入

    2.配置 "sina|*|pusher” 表示sina公司所有产品的pusher系统都能够准入

    3.配置 “*|*|pusher” 表示所有公司的所有产品的pusher系统都能够准入

    代码实现如下:

      1 #ifdef OS_WINDOWS
      2 /* Bits set in the FLAGS argument to `fnmatch'. copy from fnmatch.h(linux) */
      3 #define    FNM_PATHNAME    (1 << 0) /* No wildcard can ever match `/'.  */
      4 #define    FNM_NOESCAPE    (1 << 1) /* Backslashes don't quote special chars.  */
      5 #define    FNM_PERIOD        (1 << 2) /* Leading `.' is matched only explicitly.  */
      6 #define    FNM_NOMATCH        1
      7 
      8 #define fnmatch fnmatch_win
      9 
     10 /**copy from Google-glog*/
     11 bool SafeFNMatch(const char* pattern,size_t patt_len,const char* str,size_t str_len)
     12 {
     13     size_t p = 0;
     14     size_t s = 0;
     15     while (1)
     16     {
     17         if (p == patt_len  &&  s == str_len)
     18             return true;
     19         if (p == patt_len)
     20             return false;
     21         if (s == str_len)
     22             return p+1 == patt_len  &&  pattern[p] == '*';
     23         if (pattern[p] == str[s]  ||  pattern[p] == '?')
     24         {
     25             p += 1;
     26             s += 1;
     27             continue;
     28         }
     29         if (pattern[p] == '*')
     30         {
     31             if (p+1 == patt_len) return true;
     32             do
     33             {
     34                 if (SafeFNMatch(pattern+(p+1), patt_len-(p+1), str+s, str_len-s))
     35                 {
     36                     return true;
     37                 }
     38                 s += 1;
     39             } while (s != str_len);
     40 
     41             return false;
     42         }
     43 
     44         return false;
     45     }
     46 }
     47 
     48 /**注意:Windows平台下尚未实现最后一个参数flags的功能!!!*/
     49 int fnmatch_win(const char *pattern, const char *name, int flags = 0)
     50 {
     51     if(SafeFNMatch(pattern,strlen(pattern),name,strlen(name)))
     52         return 0;
     53     else
     54         return FNM_NOMATCH;
     55 }
     56 
     57 #else
     58 #include <fnmatch.h>
     59 #endif
     60 
     61 int main()
     62 {
     63     const char* orgin_str = "sina|weibo|pusher";
     64     char pattern_arr[][20] = {
     65         {"sina|*|pusher"},
     66         {"sina|*|*"},
     67         {"*|weibo|*"},
     68         //不能被匹配的
     69         {"sina|pic|*"},
     70         {"*|*|sign"},
     71         {"*|weibo|sign"},
     72         {"*|pic|sign"},
     73         {"sina|pic|sign"},
     74 
     75         {"*|*|*"}
     76     };
     77     static int pattern_arr_size = sizeof(pattern_arr) / sizeof(pattern_arr[0]);
     78 
     79     vector<char *> vec_str;
     80     for(int i = 0; i < pattern_arr_size; i ++)
     81     {
     82         vec_str.push_back(pattern_arr[i]);
     83     }
     84 
     85     std::cout << "Origin Str: " << orgin_str << "
    
    ";
     86     int ret;
     87     for(int i = 0; i < vec_str.size(); i++)
     88     {
     89         ret = fnmatch(vec_str.at(i), orgin_str, FNM_PATHNAME);
     90         if(ret == FNM_NOMATCH)
     91         {
     92             cout<<"sorry, I'm failed: ["<< vec_str.at(i) <<"]
    ";
     93         }
     94         else
     95         {
     96             cout<<"OK, I'm success: ["<< vec_str.at(i) <<"]
    ";
     97         }
     98     }
     99 
    100     return 0;
    101 }

    完整代码请看:字符串模糊匹配(fnmatch).cpp输出如下:

    当然,fnmatch的实现是源码可见的,也可以直接把Linux下的实现改改用在Windows平台。

    fnmatch源码实现: http://www.opensource.apple.com/source/sudo/sudo-16/sudo/fnmatch.c

    fnmatch使用参考: http://linux.die.net/man/3/fnmatch

  • 相关阅读:
    C语言保留字
    N的阶乘末尾有多少个零?
    控制台初级玩法
    数据结构笔记#二分法查找
    数据结构应用实例#栈&单链表#简易计算器
    数据结构应用实例#栈#迷宫寻路
    数据结构笔记#栈
    #2028 Lowest Common Multiple Plus
    数据结构笔记#单链表
    #2018 母牛的故事
  • 原文地址:https://www.cnblogs.com/lizhenghn/p/3702417.html
Copyright © 2020-2023  润新知