Implementation of string fuzzy matching _c language

Source: Internet
Author: User

Demand:

Access authorization profiles are sometimes configured in several dimensions, such as Company|product|sys configuration in this format:

1. Configuration "Sina|weibo|pusher" means that Sina company Weibo product Pusher system can access, and "Sina|weibo|sign" does not allow access

2. Configuration "Sina|*|pusher" means that the pusher system of all products of Sina Company can access

3. The configuration "*|*|pusher" means that all pusher systems of all products of the company are able to access

...

There are a lot of scenes like this, okay, simple things don't pull the eggs.

Realize:

In the face of this demand I think the first time is how to design the pattern string, how to quickly implement the function, because I now write a C service, so I first out of my mind is a lot of strchr (XXX, ' * '), STRCHR (xxx, ' | ') And so on, later found that this thing is not necessary to build their own wheels, there are ready-made functions can be used, that is fnmatch.

Google a bit, found that Fnmatch is not a lot of information, most of them are talking about PHP functions, so there is no way, can only write their own test.

#include <iostream>
#include <fnmatch.h>
#include <vector>
using namespace std;
 
int main ()
{
  const char* ORGIN_STR = "Sina|weibo|pusher";
  Char pattern_arr[][20] = {"
    sina|*|pusher"},
    {"sina|*|*"},
    {"*|weibo|*"},
    ///cannot be matched
    {"Sina" |pic|* "}, {" *|*|sign "}, {" *|weibo|sign "}, {" *|pic|sign "}, {
    " Sina|pic|sign "},
 
    {" *|*|* " }
  };
  static int pattern_arr_size = sizeof (Pattern_arr)/sizeof (pattern_arr[0));
 
  Vector<char *> vec_str;
  for (int i = 0; i < pattern_arr_size i + +)
  {
    vec_str.push_back (pattern_arr[i]);
  }
 
  int ret;
  int z = 0;
  while (Z < 1) {
    for (int i = 0; i < vec_str.size (); i++)
    {   
      ret = Fnmatch (vec_str.at (i), Orgin_str, fnm_p Athname);
      if (Fnm_nomatch = = ret) {
        cout<< "sorry I ' m failed [" << vec_str.at (I) << "]" <<endl;
      }   
    }   
    ++z}
}

Results:

Experiment one, the results are not bad, fully meet the needs:

The requirements are met, and I'm worried about a problem, which is performance, commenting out the cout output, and then tuning the while Z statement to 1,000,000 and recompiling and running:

Time./fnmatch

Seems to be a good efficiency, 2.1s 100W time matching, the average 2us once, performance requirements are met ...

Attached: The above article only describes the Linux system directly invoke the system function Fnmatch can be implemented, without considering the use of Windows.

I looked at the next Google-glog code this week, happened to find a similar fnmatch simple implementation, so combined to provide a cross-platform interface.

#ifdef os_windows/* Bits set in the FLAGS argument to ' Fnmatch '. Copy from FNMATCH.H (Linux)/#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match '/'. * * #define FNM_NOESCAPE (1 << 1)/* backslashes don ' t quote special chars. */#define FNM_PERIOD (1 << 2 )/* leading '. ' is matched only explicitly. * * #define FNM_NOMATCH 1 #define Fnmatch Fnmatch_win/**copy from google-glog*/bool Safefnmatch (const char* pattern
  , size_t patt_len,const char* str,size_t str_len) {size_t p = 0;
  size_t s = 0;
    while (1) {if (p = = Patt_len && s = = Str_len) return true;
    if (p = = Patt_len) return false;
    if (s = = Str_len) return p+1 = = Patt_len && pattern[p] = = ' * ';
    if (pattern[p] = = Str[s] | | | pattern[p] = = '? ')
      {p = 1;
      s + + 1;
    Continue
      } if (pattern[p] = = ' * ') {if (p+1 = = Patt_len) return true; do {if (Safefnmatch pattern+ (p+1), patt_len-(p+1),Str+s, Str_len-s)) {return true;
      } s + + 1;

      while (S!= str_len);
    return false;
  return false; }/** Note: The function of the last parameter flags is not yet implemented under the Windows platform!!! */int Fnmatch_win (const char *pattern, const char *name, int flags = 0) {if (Safefnmatch Pattern,strlen (pattern), name,s
  Trlen (name)) return 0;
else return fnm_nomatch;
  #else #include <fnmatch.h> #endif int main () {const char* ORGIN_STR = "Sina|weibo|pusher";
    Char pattern_arr[][20] = {"Sina|*|pusher"}, {"sina|*|*"}, {"*|weibo|*"},///cannot be matched {"sina|pic|*"},
  {"*|*|sign"}, {"*|weibo|sign"}, {"*|pic|sign"}, {"Sina|pic|sign"}, {"*|*|*"}};

  static int pattern_arr_size = sizeof (Pattern_arr)/sizeof (pattern_arr[0));
  Vector<char *> Vec_str;
  for (int i = 0; i < pattern_arr_size i + +) {Vec_str.push_back (pattern_arr[i]);
  } std::cout << "Origin Str:" << orgin_str << "\ n";
  int ret;for (int i = 0; i < vec_str.size (); i++) {ret = Fnmatch (vec_str.at (i), orgin_str, fnm_pathname);
    if (ret = = Fnm_nomatch) {cout<< "Sorry, I ' m failed: [" << vec_str.at (i) << "]\n";
    else {cout<< "OK, I ' m success: [" << vec_str.at (i) << "]\n";
} return 0;

 }

The output is as follows:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: