Dear All,

I have function that works like this. Here # represnts one word while * is for one alphabet. Can anyone help me changing this code where # is for 0-N words, means it works if at # there is no word between dots, while for * there must be one word, not an alphabet. Any help would be highly appreciated.

main():
std::string aa = "usa.#.* ";
std::string aa = "usa.weather.u" ;
if (wildcmp(aa,rrr))

        Console::WriteLine("match found");

     else
     Console::WriteLine("match not found");

function:

int wildcmp(const char *wild, const char *string) {
  // comparing wilcard binding key with routing key
  const char *cp = nullptr, *mp = nullptr;

  while ((*string) && (*wild != '#'))
  {

     if ((*wild != *string) && (*wild != '*'))
     {
      return 0;
      }
    wild++;
    string++;
  } 

 while (*string) {
          if (*wild == '#') {

            if (!*++wild) 
            {
              return 1;
           }
        mp = wild;
        cp = string+1;
        } 
   else if ((*wild == *string) || (*wild == '*')) {
      wild++;
      string++;
    } 
    else {
      wild = mp;
      string = cp++;
    }
  }

  while (*wild == '#') {
    wild++;
  }
  return !*wild;
}

Recommended Answers

All 30 Replies

Since you seem to be using C++/CLI (along with STL), I'm going to assume CLI is acceptable.
The following example replaces your special characters with Regular Expression syntax.
You can tweak the Replace parameters to be exactly what you want, but you can see what was done here:

#include "stdafx.h"
using namespace System;
using namespace System::Text::RegularExpressions;

bool wildcmp(String^ input, String^ pattern)
{
   String^ strNewPattern = pattern->Replace("#", "\\w+")->Replace("*", ".");
   return Regex::IsMatch(input, strNewPattern);
}

int main(array<System::String ^> ^args)
{
   String^ strPattern = "usa.#.*";
   String^ strInput = "usa.weather.u";

   if (wildcmp(strInput, strPattern))
   {
      Console::WriteLine("Matched");
   }
   else
   {
      Console::WriteLine("Did not match");
   }

   return 0;
}
commented: nice answer +0

Thanks for your effort. this program is working for

String^ strPattern = "*.stock.#";
String^ strInput = "usd.stock.eur";

But its giving"did not matched for

String^ strPattern = "*.stock.#";
String^ strInput = "usd.stock";

my requirement is # represents 0-N words. even it should say no to "stock.nasdaq".

I hope you can understand what I want to have.

it is saying no to "stock.nasdaq " But the problem is only of "usd.stock" that implements the real logic.

Isn't the # supposed to represent just ONE character?

No, # represents 0-N words, it should pass the string even if there is word or not. and * means that there must be one word . PLEASE HELP

*(star) can substitute for exactly one word.
# (hash) can substitute for zero or more words.

First set of requirements:

Here # represnts one word while * is for one alphabet
*

Second set of requirements:

*(star) can substitute for exactly one word.
# (hash) can substitute for zero or more words.
*

If you swap the hash and the star in my example, it will work based on your first set of requirements.

If you want to use the second set of requirements, how will you recognize one character? ...as a word?

The second set of requirement is the real one I want in my program. I want to recognise the words in both cases not charaters.

OK, this is closer, but I would need to see more examples of what you would be filtering to prove this works in all cases:

#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Text::RegularExpressions;

bool wildcmp(String^ input, String^ pattern)
{
   String^ strNewPattern =
      "^" + 
      pattern->Replace(".", "\\.")
      ->Replace("#", "(\\b\\w+\\b){0,}")
      ->Replace("*", "\\b\\w*\\b") + "$";
   return Regex::IsMatch(input, strNewPattern);
}

int main(array<System::String ^> ^args)
{
   String^ strPattern = "usa.#.*";

   List<String^>^ lst_strInputs =
      Enumerable::ToList<String^>(
         gcnew array<String^>{"usa.weather.u", "usa.weather"});

   for each(String^ strInput in lst_strInputs)
   {
      Console::WriteLine(wildcmp(strInput, strPattern) ? "Matched" : "Did not match");
   }

   return 0;
}

Thank you very much for your reply. actually I checked it like this.

#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Text::RegularExpressions;

bool wildcmp(String^ input, String^ pattern)
{
   String^ strNewPattern =
      "^" + 
      pattern->Replace(".", "\\.")
      ->Replace("#", "(\\b\\w+\\b){0,}")
      ->Replace("*", "\\b\\w*\\b") + "$";
   return Regex::IsMatch(input, strNewPattern);
}

int main(array<System::String ^> ^args)
{
   String^ strPattern = "*.stock.#";

   List<String^>^ lst_strInputs =  Enumerable::ToList<String^>(gcnew array<String^>{"stock.nasdaq", "usd.stock"});

   for each(String^ strInput in lst_strInputs)
   {
      Console::WriteLine(wildcmp(strInput, strPattern) ? "Matched" : "Did not match");
   }

    Console::ReadLine();
}

its output is:
Did not match
Did not match

while my requirement is, for second string it should give output.
Matched

for "usd.stock" matching "*.stock.#" here * means there must be one word and # means there could be no word. So answer must be matched. Can I ask why we need to put strings in the form of array?

Let me give you another example.

strinput= usd.stock  

It should match with two string pattern.

strpattern= *.stock.#;
strpattern=usd.*;

tell me if you need more information.

What should it NOT match?

it should not match #, if there is no word in place of #. while for * word is must.

I need to see some strings that will NOT match the pattern.

As in already given example with string pattern

strpattern= *.stock.#;

strinput= usd.stock  

Here it should say "matched" and it checked *. stock and has ignored #.

But if

strinput= stock.nasdaq

it should say "not matched" as in string input the first part of pattern that is "star *" must be matched with any word and cannot be ignored.

All you need to do then is manipulate which regular expression best fits your definition of the hash and the star in the example I gave.
What's confusing ME is the definition of one WORD versus ZERO or MORE WORDS.

Yah you are right. Thats quite confusing but actually that is the requirement .

There must be one WORD, when its a star and for hash could be one and even nothing.

So have you looked at a particular Regular Expression that will properly substitute for the pattern characters you are using?

I am sorry I coudnt understand what you wanna say.

The technique I used is replacing the hash-mark and the asterisk with "Regular Expressions".
In the dot net world, we have the Regex class that is built just such a thing.
You can have a Regex that matches almost any type of pattern as long as you can express it correctly.

The System::Text::RegularExpressions; namespace holds the functions that do the Regex.

I am simply replacing your pattern characters (hash and star) with Regular Expressions that should find what you expect.

if you please have a look ove this link Click Here
specially topic exchange idea given here I wanna do something like that.

I understand that.
What I'm trying to understand is how ONE word is not the same as ZERO-or-MORE words.

THEN I need to see:
1) a literal string that passes the ONE word test.
2) a literal string that passes the ZERO-or-MORE words test.
3) a literal string that fails the ONE word test.
4) a literal string that fails the ZERO-or-MORE words test. <<PROBLEM

commented: Thanks for your help I appreciate your gestures of kindness towards my problem. +1

in this function if we say that pattern is "lazy.#" it should pass the string "lazy" as well.
I am looking for other examples as well.

We created three patterns: Queue1 is bound with ".orange." and Queue2 with "..rabbit" and "lazy.#".

These bindings can be summarised as:

* Q1 is interested in all the orange animals.
* Q2 wants to hear everything about rabbits, and everything about lazy animals.

A message with a string set to "quick.orange.rabbit" will be delivered to both queues. Message "lazy.orange.elephant" also will go to both of them. On the other hand "quick.orange.fox" will only go to the first queue, and "lazy.brown.fox" only to the second. "lazy.pink.rabbit" will be delivered to the second queue only once, even though it matches two bindings. "quick.brown.fox" doesn't match any binding so it will be discarded.

What happens if we break our contract and send a string with one or four words, like "orange" or "quick.orange.male.rabbit"? Well, these strings won't match any bindings and will be lost.

On the other hand "lazy.orange.male.rabbit", even though it has four words, will match the last binding and will be delivered to the second queue.

let me know if you have any problem in understanding. Thanks for your help I appreciate your gestures of kindness towards my problem.

...then back to my original example:
How does it NOT work?
What about the proposed change a couple of posts after that?
How does THAT not work?

If in program I gave pattern "lazy.# ". It should accpet the lazy.stock.nasdaq.
While its not doing so. However it woks well for *star patterns.

How about this?:

#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Text::RegularExpressions;

bool wildcmp(String^ input, String^ pattern)
{
   String^ strNewPattern =
      "^" + 
      pattern->Replace(".", "\\.")
      ->Replace("*", "\\b\\w*\\b")
      ->Replace("#", "(\\w*)*.*")
      + "$";
   return Regex::IsMatch(input, strNewPattern);
}

int main(array<System::String ^> ^args)
{
   String^ strPattern = "usa.#";

   List<String^>^ lst_strInputs =
      Enumerable::ToList<String^>(
         gcnew array<String^>{"usa.weather.usa", "usa.weather"});

   for each(String^ strInput in lst_strInputs)
   {
      Console::WriteLine(wildcmp(strInput, strPattern) ? "Matched" : "Did not match");
   }

   return 0;
}

I noticed a flaw in the first example, but have not fully tested this one.

commented: nice effort +0

Nice effort but I would check this one from every aspect and let you know. Thank you very much.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.