Converting string expression to boolean logic - C# - c#

I want to convert a string expression to a real boolean expression.
The expression below will be an input (string):
"(!A && B && C) || (A && !B && C) || (A && B && !C) || (A && B && C)"
The variables A, B and C will have your boolean values (true or false).
How I can transforming a string expression, replace the logic values and validate using C#?

If you don't want to use some available libraries to parse that string you need to separate those characters and implement the logic based on comparison. So for example say we have "a || b", we can loop though each character and decide the appropriate operation based on char == '|'. For more complex situation I'd use a stack to keep track of each results, like this one that can handle && and || without parentheses:
public bool ConvertToBool(string op, bool a, bool b)
{
var st = new Stack<bool>();
var opArray = op.ToCharArray();
var orFlag = false;
var andFlag = false;
for (var i = 0; i < opArray.Length; i++)
{
bool top;
switch (opArray[i])
{
case '|':
i++;
orFlag = true;
break;
case '&':
i++;
andFlag = true;
break;
case 'a':
if (orFlag)
{
top = st.Pop();
st.Push(top || a);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && a);
andFlag = false;
continue;
}
st.Push(a);
break;
case 'b':
if (orFlag)
{
top = st.Pop();
st.Push(top && b);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && b);
andFlag = false;
continue;
}
st.Push(b);
break;
}
}
return st.Pop();
}

Related

C# for case in string(easy)

so I have this code. I need to generate a for loop that checks all the characters in the string and checks if they are all valid(So numbers from 0->7). But I don't know how to write it, I tried something but it didn't work. Here are the examples:user enters: 77, code works, user enters 99, code doesn't work, user enters 5., code doesn't work, etc..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NALOGA1
{
class Program
{
static string decToOct(int stevilo)//v mojon primere 7
{
string izhod = "";
//7>0 DRŽI
while (stevilo > 0)
{
//izhodi se dodeli ostanek deljenja z 8 keri se spremeni v string
izhod = (stevilo % 8) + izhod;
//7/8;
stevilo /= 8;
}
return izhod;
}
static int Octtodesetisko(string stevilo)
{
double vsota = 0;
for (int i = stevilo.Length - 1; i >= 0; i--)
{
int stevka = stevilo[i] - '0';
vsota += (stevka * Math.Pow(8, i));
}
return (int)vsota;
}
static void Main(string[] args)
{
//3 podprogram-in progress
string prvastevilka = Console.ReadLine();
int prvasprememba = Int32.Parse(prvastevilka);
if (prvasprememba > 0)
{
Console.WriteLine(decToOct(prvasprememba));
}
else
{
Console.WriteLine("Napaka");
}
string drugastevilka = Console.ReadLine();
int drugasprememba = Octtodesetisko(drugastevilka);
foreach (char znak in drugastevilka)
{
if(znak!=1 || znak!=2 || znak!=3 || znak!=4 || znak!=5 || znak!=6 || znak!=7)
{
Console.WriteLine("Napaka");
}
else
{
Console.WriteLine("dela :D");
}
}
Console.ReadKey();
}
}
}
Personally, I would take advantage of the LINQ Enumerable.All method to express this in a very concise and readable way:
if (str.Any() && str.All(c => c >= '0' && c <= '7'))
{
Console.WriteLine("good");
}
else
{
Console.WriteLine("bad");
}
EDIT: No LINQ
It's not hard to translate what the LINQ Enumerable.All method does to a normal loop. It's just more verbose:
bool isValid = true;
foreach (char c in str)
{
if (c < '0' || c > '7')
{
isValid = false;
break;
}
}
if (str.Length != 0 && isValid)
{
Console.WriteLine("good");
}
else
{
Console.WriteLine("bad");
}
Firstly, there seems to be a mistake in the line
if(znak!=1 || znak!=2 || znak!=3 || znak!=4 || znak!=5 || znak!=6 || znak!=7)
I guess it should read
if(znak!='1' || znak!='2' || znak!='3' || znak!='4' || znak!='5' || znak!='6' || znak!='7')
which should be compressed to
if (znak >= '0' && znak <= '7')
You can use linq instead of the for loop here like this:
if (drugastevilka.All(c => c >= '0' && c <= '7')
Console.WriteLine("dela :D");
else
Console.WriteLine("Napaka");
But the best solution is probably to use a regular expression:
Regex regex = new Regex("^[0-7]+$");
if (regex.IsMatch(drugastevilka))
Console.WriteLine("dela :D");
else
Console.WriteLine("Napaka");
Edit: the linq solution shown accepts empty strings, the regex (as shown) needs at least 1 character. Exchange the + with a * and it will accept empty strings, too. But I don't think you want to accept empty strings.
You are messing up with the datatype
Can you try with below code
static string decToOct(int stevilo)//v mojon primere 7
{
int izhod = 0;
//7>0 DRŽI
while (stevilo > 0)
{
//izhodi se dodeli ostanek deljenja z 8 keri se spremeni v string
izhod = (stevilo % 8) + izhod;
//7/8;
stevilo /= 8;
}
return (izhod.ToString());
}
What about something like this?
class Program
{
static void Main(string[] args)
{
string someString = "1234567";
string someOtherString = "1287631";
string anotherString = "123A6F2";
Console.WriteLine(IsValidString(someString));
Console.WriteLine(IsValidString(someOtherString));
Console.WriteLine(IsValidString(anotherString));
Console.ReadLine();
}
public static bool IsValidString(string str)
{
bool isValid = true;
char[] splitString = str.ToCharArray(); //get an array of each character
for (int i = 0; i < splitString.Length; i++)
{
try
{
double number = Char.GetNumericValue(splitString[i]); //try to convert the character to a double (GetNumericValue returns a double)
if (number < 0 || number > 7) //we get here if the character is an int, then we check for 0-7
{
isValid = false; //if the character is invalid, we're done.
break;
}
}
catch (Exception) //this will hit if we try to convert a non-integer character.
{
isValid = false;
break;
}
}
return isValid;
}
}
IsValidString() takes a string, converts it to a Char array, then checks each value as such:
Get the numeric value
Check if the value is between 0-7
GetNumericValue will fail on a non-integer character, so we wrap it in a try/catch - if we hit an exception we know that isValid = false, so we break.
If we get a valid number, and it's not between 0-7 we also know that isValid = false, so we break.
If we make it all the way through the list, the string is valid.
The sample given above returns:
IsValidString(someString) == true
IsValidString(someOtherString) == false
IsValidString(anotherString) == false

Determine primitive types using roslyn

Using Roslyn, how to determine whether an ITypeSymbol is a primitive type or not?
The ITypeSymbol does not have the IsPrimitive property like Type.IsPrimitive
Is there a way to convert ITypeSymbol to Type or some other way to determine whether an ITypeSymbol is a primitive type?
Looks like the code to determine that is in the TypedConstant class, but it is internal and I couldn't find a public API that would nicely get me there. I ended up copying the method into to my project.
/// <remarks>
/// TypedConstant isn't computing its own kind from the type symbol because it doesn't
/// have a way to recognize the well-known type System.Type.
/// </remarks>
internal static TypedConstantKind GetTypedConstantKind(ITypeSymbol type, Compilation compilation)
{
Debug.Assert(type != null);
switch (type.SpecialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Char:
case SpecialType.System_String:
case SpecialType.System_Object:
return TypedConstantKind.Primitive;
default:
switch (type.TypeKind)
{
case TypeKind.Array:
return TypedConstantKind.Array;
case TypeKind.Enum:
return TypedConstantKind.Enum;
case TypeKind.Error:
return TypedConstantKind.Error;
}
if (compilation != null &&
compilation.IsSystemTypeReference(type))
{
return TypedConstantKind.Type;
}
return TypedConstantKind.Error;
}
}
Whether a type is primitive or not depends on your language. In C# DateTime is not a primitive, but it is in VB. Since ITypeSymbol is used for both languages, it does not have language-specific properties.
Try the following extension methods:
//eg: symbol.IsFullNameEquals("List`1", "Generic", "Collections", "System")
internal static bool IsFullNameEquals(this ISymbol symbol, params string[] nameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (nameParts == null || nameParts.Length == 0) throw new ArgumentNullException("nameParts");
var idx = 0;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == nameParts.Length) return false;
if (name != nameParts[idx]) return false;
idx++;
}
return idx == nameParts.Length;
}
//eg: var idx = symbol.MatchFullName(new []{"List`1", "Dictionary`2"}, new []{"Generic", "Collections", "System"});
//return value: -1: none; 0: symbol is List`1; 1: symbol is Dictionary`2
internal static int MatchFullName(this ISymbol symbol, string[] typeNames, string[] outerNameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (typeNames == null || typeNames.Length == 0) throw new ArgumentNullException("typeNames");
var fullLength = 1 + (outerNameParts != null ? outerNameParts.Length : 0);
int idx = 0, result = -1;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == fullLength) return -1;
if (idx == 0) {
for (var i = 0; i < typeNames.Length; i++) {
if (name == typeNames[i]) {
result = i;
break;
}
}
if (result == -1) return -1;
}
else {
if (name != outerNameParts[idx - 1]) return -1;
}
idx++;
}
if (idx == fullLength) return result;
return -1;
}

Reliably checking if a string is base64 encoded in .Net

Before I start: Yes, I have checked the other questions and answers on this topic both here and elsewhere.
I have found an example string that the .Net will base64 decode even though it isn't actually base64 encoded. Here is the example:
Rhinocort Aqueous 64mcg/dose Nasal Spray
The .Net method Convert.FromBase64String does not throw an exception when decoding this string so my IsBase64Encoded method happily returns true for this string.
Interestingly, if I use the cygwin base64 -d command using this string as input, it fails with the message invalid input.
Even more interestingly, the source that I thought that belongs to this executable (http://libb64.sourceforge.net/) "decodes" this same string with the same result as I am getting from the .Net Convert.FromBase64String. I will keep looking hoping to find a clue elsewhere but right now I'm stumped.
Any ideas?
There's a slightly better solution which also checks the input string length.
I recommend you do a check at the beginning. If the input is null or empty then return false.
http://www.codeproject.com/Questions/177808/How-to-determine-if-a-string-is-Base-decoded-or
When strings do pass Base64 decoding and the decoded data has special characters, then perhaps we can conclude that it was not valid Base64 (this depends on the encoding). Also, sometimes we're expecting the data being passed to be Base64, but sometimes it may not be properly padded with '='. Therefore, one method uses "strict" rules for Base64 and the other is "forgiving".
[TestMethod]
public void CheckForBase64()
{
Assert.IsFalse(IsBase64DataStrict("eyJhIjoiMSIsImIiOiI2N2NiZjA5MC00ZGRiLTQ3OTktOTlmZi1hMjhhYmUyNzQwYjEiLCJmIjoiMSIsImciOiIxIn0"));
Assert.IsTrue(IsBase64DataForgiving("eyJhIjoiMSIsImIiOiI2N2NiZjA5MC00ZGRiLTQ3OTktOTlmZi1hMjhhYmUyNzQwYjEiLCJmIjoiMSIsImciOiIxIn0"));
Assert.IsFalse(IsBase64DataForgiving("testing123"));
Assert.IsFalse(IsBase64DataStrict("ABBA"));
Assert.IsFalse(IsBase64DataForgiving("6AC648C9-C08F-4F9D-A0A5-3904CF15ED3E"));
}
public bool IsBase64DataStrict(string data)
{
if (string.IsNullOrWhiteSpace(data)) return false;
if ((new Regex(#"[^A-Z0-9+\/=]", RegexOptions.IgnoreCase)).IsMatch(data)) return false;
if (data.Length % 4 != 0) return false;
var e = data.IndexOf('=');
var l = data.Length;
if (!(e == -1 || e == l - 1 || (e == l - 2 && data[l - 1] == '='))) return false;
var decoded = string.Empty;
try
{
byte[] decodedData = Convert.FromBase64String(data);
decoded = Encoding.UTF8.GetString(decodedData);
}
catch(Exception)
{
return false;
}
//check for special chars that you know should not be there
char current;
for (int i = 0; i < decoded.Length; i++)
{
current = decoded[i];
if (current == 65533) return false;
if (!((current == 0x9 || current == 0xA || current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF))))
{
return false;
}
}
return true;
}
public bool IsBase64DataForgiving(string data)
{
if (string.IsNullOrWhiteSpace(data)) return false;
//it could be made more forgiving by replacing any spaces with '+' here
if ((new Regex(#"[^A-Z0-9+\/=]", RegexOptions.IgnoreCase)).IsMatch(data)) return false;
//this is the forgiving part
if (data.Length % 4 > 0)
data = data.PadRight(data.Length + 4 - data.Length % 4, '=');
var e = data.IndexOf('=');
var l = data.Length;
if (!(e == -1 || e == l - 1 || (e == l - 2 && data[l - 1] == '='))) return false;
var decoded = string.Empty;
try
{
byte[] decodedData = Convert.FromBase64String(data);
decoded = Encoding.UTF8.GetString(decodedData);
}
catch (Exception)
{
return false;
}
//check for special chars that you know should not be there
char current;
for (int i = 0; i < decoded.Length; i++)
{
current = decoded[i];
if (current == 65533) return false;
if (!((current == 0x9 || current == 0xA || current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF))))
{
return false;
}
}
return true;
}

Logic to decrease character values

I am working on a logic that decreases the value of an alphanumeric List<char>. For example, A10 becomes A9, BBA becomes BAZ, 123 becomes 122. And yes, if the value entered is the last one(like A or 0), then I should return -
An additional overhead is that there is a List<char> variable which is maintained by the user. It has characters which are to be skipped. For example, if the list contains A in it, the value GHB should become GGZ and not GHA.
The base of this logic is a very simple usage of decreasing the char but with these conditions, I am finding it very difficult.
My project is in Silverlight, the language is C#. Following is my code that I have been trying to do in the 3 methods:
List<char> lstGetDecrName(List<char> lstVal)//entry point of the value that returns decreased value
{
List<char> lstTmp = lstVal;
subCheckEmpty(ref lstTmp);
switch (lstTmp.Count)
{
case 0:
lstTmp.Add('-');
return lstTmp;
case 1:
if (lstTmp[0] == '-')
{
return lstTmp;
}
break;
case 2:
if (lstTmp[1] == '0')
{
if (lstTmp[0] == '1')
{
lstTmp.Clear();
lstTmp.Add('9');
return lstTmp;
}
if (lstTmp[0] == 'A')
{
lstTmp.Clear();
lstTmp.Add('-');
return lstTmp;
}
}
if (lstTmp[1] == 'A')
{
if (lstTmp[0] == 'A')
{
lstTmp.Clear();
lstTmp.Add('Z');
return lstTmp;
}
}
break;
}
return lstGetDecrValue(lstTmp,lstVal);
}
List<char> lstGetDecrValue(List<char> lstTmp,List<char> lstVal)
{
List<char> lstValue = new List<char>();
switch (lstTmp.Last())
{
case 'A':
lstValue = lstGetDecrTemp('Z', lstTmp, lstVal);
break;
case 'a':
lstValue = lstGetDecrTemp('z', lstTmp, lstVal);
break;
case '0':
lstValue = lstGetDecrTemp('9', lstTmp, lstVal);
break;
default:
char tmp = (char)(lstTmp.Last() - 1);
lstTmp.RemoveAt(lstTmp.Count - 1);
lstTmp.Add(tmp);
lstValue = lstTmp;
break;
}
return lstValue;
}
List<char> lstGetDecrTemp(char chrTemp, List<char> lstTmp, List<char> lstVal)//shifting places eg unit to ten,etc.
{
if (lstTmp.Count == 1)
{
lstTmp.Clear();
lstTmp.Add('-');
return lstTmp;
}
lstTmp.RemoveAt(lstTmp.Count - 1);
lstVal = lstGetDecrName(lstTmp);
lstVal.Insert(lstVal.Count, chrTemp);
return lstVal;
}
I seriously need help for this. Please help me out crack through this.
The problem you are trying to solve is actually how to decrement discreet sections of a sequence of characters, each with it's own counting system, where each section is separated by a change between Alpha and Numeric. The rest of the problem is easy once you identify this.
The skipping of unwanted characters is simply a matter of repeating the decrement if you get an unwanted character in the result.
One difficultly is the ambiguous definition of the sequences. e.g. what to do when you get down to say A00, what is next? "A" or "-". For the sake of argument I am assuming a practical implementation based loosely on Excel cell names (i.e. each section operates independently of the others).
The code below does 95% of what you wanted, however there is a bug in the exclusions code. e.g. "ABB" becomes "AAY". I feel the exclusions need to be applied at a higher level (e.g. repeat decrement until no character is in the exclusions list), but I don't have time to finish it now. Also it is resulting in a blank string when it counts down to nothing, rather than the "-" you wanted, but that is trivial to add at the end of the process.
Part 1 (divide the problem into sections):
public static string DecreaseName( string name, string exclusions )
{
if (string.IsNullOrEmpty(name))
{
return name;
}
// Split the problem into sections (reverse order)
List<StringBuilder> sections = new List<StringBuilder>();
StringBuilder result = new StringBuilder(name.Length);
bool isNumeric = char.IsNumber(name[0]);
StringBuilder sb = new StringBuilder();
sections.Add(sb);
foreach (char c in name)
{
// If we change between alpha and number, start new string.
if (char.IsNumber(c) != isNumeric)
{
isNumeric = char.IsNumber(c);
sb = new StringBuilder();
sections.Insert(0, sb);
}
sb.Append(c);
}
// Now process each section
bool cascadeToNext = true;
foreach (StringBuilder section in sections)
{
if (cascadeToNext)
{
result.Insert(0, DecrementString(section, exclusions, out cascadeToNext));
}
else
{
result.Insert(0, section);
}
}
return result.ToString().Replace(" ", "");
}
Part2 (decrement a given string):
private static string DecrementString(StringBuilder section, string exclusions, out bool cascadeToNext)
{
bool exclusionsExist = false;
do
{
exclusionsExist = false;
cascadeToNext = true;
// Process characters in reverse
for (int i = section.Length - 1; i >= 0 && cascadeToNext; i--)
{
char c = section[i];
switch (c)
{
case 'A':
c = (i > 0) ? 'Z' : ' ';
cascadeToNext = (i > 0);
break;
case 'a':
c = (i > 0) ? 'z' : ' ';
cascadeToNext = (i > 0);
break;
case '0':
c = (i > 0) ? '9' : ' ';
cascadeToNext = (i > 0);
break;
case ' ':
cascadeToNext = false;
break;
default:
c = (char)(((int)c) - 1);
if (i == 0 && c == '0')
{
c = ' ';
}
cascadeToNext = false;
break;
}
section[i] = c;
if (exclusions.Contains(c.ToString()))
{
exclusionsExist = true;
}
}
} while (exclusionsExist);
return section.ToString();
}
The dividing can of course be done more efficiently, just passing start and end indexes to the DecrementString, but this is easier to write & follow and not much slower in practical terms.
do a check if its a number if so then do a minus math of the number, if its a string then change it to char codes and then the char code minus 1
I couldn't stop thinking about this yesterday, so here's an idea. Note, this is just pseudo-code, and not tested, but I think the idea is valid and should work (with a few modifications).
The main point is to define your "alphabet" directly, and specify which characters in it are illegal and should be skipped, then use a list or array of positions in this alphabet to define the word you start with.
I can't spend any more time on this right now, but please let me know if you decide to use it and get it to work!
string[] alphabet = {a, b, c, d, e};
string[] illegal = {c, d};
public string ReduceString(string s){
// Create a list of the alphabet-positions for each letter:
int[] positionList = s.getCharsAsPosNrsInAlphabet();
int[] reducedPositionList = ReduceChar(positionList, positionList.length);
string result = "";
foreach(int pos in reducedPositionList){
result += alphabet[pos];
}
return result;
}
public string ReduceChar(string[] positionList, posToReduce){
int reducedCharPosition = ReduceToNextLegalChar(positionList[posToReduce]);
// put reduced char back in place:
positionList[posToReduce] = reducedCharPosition;
if(reducedCharPosition < 0){
if(posToReduce <= 0){
// Reached the end, reduced everything, return empty array!:
return new string[]();
}
// move to back of alphabet again (ie, like the 9 in "11 - 2 = 09"):
reducedCharPosition += alphabet.length;
// Recur and reduce next position (ie, like the 0 in "11 - 2 = 09"):
return ReduceChar(positionList, posToReduce-1);
}
return positionList;
}
public int ReduceToNextLegalChar(int pos){
int nextPos = pos--;
return (isLegalChar(nextPos) ? nextPos : ReduceToNextLegalChar(nextPos));
}
public boolean IsLegalChar(int pos){
return (! illegal.contains(alphabet[pos]));
}
enter code here
Without writing all your code for you, here's a suggestion as to how you can break this down:
char DecrementAlphaNumericChar(char input, out bool hadToWrap)
{
if (input == 'A')
{
hadToWrap = true;
return 'Z';
}
else if (input == '0')
{
hadToWrap = true;
return '9';
}
else if ((input > 'A' && input <= 'Z') || (input > '0' && input <= '9'))
{
hadToWrap = false;
return (char)((int)input - 1);
}
throw new ArgumentException(
"Characters must be digits or capital letters",
"input");
}
char DecrementAvoidingProhibited(
char input, List<char> prohibited, out bool hadToWrap)
{
var potential = DecrementAlphaNumericChar(input, out hadToWrap);
while (prohibited.Contains(potential))
{
bool temp;
potential = DecrementAlphaNumericChar(potential, out temp);
if (potential == input)
{
throw new ArgumentException(
"A whole class of characters was prohibited",
"prohibited");
}
hadToWrap |= temp;
}
return potential;
}
string DecrementString(string input, List<char> prohibited)
{
char[] chrs = input.ToCharArray();
for (int i = chrs.Length - 1; i >= 0; i--)
{
bool wrapped;
chrs[i] = DecrementAvoidingProhibited(
chrs[i], prohibited, out wrapped);
if (!wrapped)
return new string(chrs);
}
return "-";
}
The only issue here is that it will reduce e.g. A10 to A09 not A9. I actually prefer this myself, but it should be simple to write a final pass that removes the extra zeroes.
For a little more performance, replace the List<char>s with Hashset<char>s, they should allow a faster Contains lookup.
I found solution to my own answer with some other workarounds.
The calling function:
MyFunction()
{
//stuff I do before
strValue = lstGetDecrName(strValue.ToList());//decrease value here
if (strValue.Contains('-'))
{
strValue = "-";
}
//stuff I do after
}
In all there are 4 functions. 2 Main functions and 2 helper functions.
List<char> lstGetDecrName(List<char> lstVal)//entry point, returns decreased value
{
if (lstVal.Contains('-'))
{
return "-".ToList();
}
List<char> lstTmp = lstVal;
subCheckEmpty(ref lstTmp);
switch (lstTmp.Count)
{
case 0:
lstTmp.Add('-');
return lstTmp;
case 1:
if (lstTmp[0] == '-')
{
return lstTmp;
}
break;
case 2:
if (lstTmp[1] == '0')
{
if (lstTmp[0] == '1')
{
lstTmp.Clear();
lstTmp.Add('9');
return lstTmp;
}
if (lstTmp[0] == 'A')
{
lstTmp.Clear();
lstTmp.Add('-');
return lstTmp;
}
}
if (lstTmp[1] == 'A')
{
if (lstTmp[0] == 'A')
{
lstTmp.Clear();
lstTmp.Add('Z');
return lstTmp;
}
}
break;
}
List<char> lstValue = new List<char>();
switch (lstTmp.Last())
{
case 'A':
lstValue = lstGetDecrTemp('Z', lstTmp, lstVal);
break;
case 'a':
lstValue = lstGetDecrTemp('z', lstTmp, lstVal);
break;
case '0':
lstValue = lstGetDecrTemp('9', lstTmp, lstVal);
break;
default:
char tmp = (char)(lstTmp.Last() - 1);
lstTmp.RemoveAt(lstTmp.Count - 1);
lstTmp.Add(tmp);
subCheckEmpty(ref lstTmp);
lstValue = lstTmp;
break;
}
lstGetDecrSkipValue(lstValue);
return lstValue;
}
List<char> lstGetDecrSkipValue(List<char> lstValue)
{
bool blnSkip = false;
foreach (char tmpChar in lstValue)
{
if (lstChars.Contains(tmpChar))
{
blnSkip = true;
break;
}
}
if (blnSkip)
{
lstValue = lstGetDecrName(lstValue);
}
return lstValue;
}
void subCheckEmpty(ref List<char> lstTmp)
{
bool blnFirst = true;
int i = -1;
foreach (char tmpChar in lstTmp)
{
if (char.IsDigit(tmpChar) && blnFirst)
{
i = tmpChar == '0' ? lstTmp.IndexOf(tmpChar) : -1;
if (tmpChar == '0')
{
i = lstTmp.IndexOf(tmpChar);
}
blnFirst = false;
}
}
if (!blnFirst && i != -1)
{
lstTmp.RemoveAt(i);
subCheckEmpty(ref lstTmp);
}
}
List<char> lstGetDecrTemp(char chrTemp, List<char> lstTmp, List<char> lstVal)//shifting places eg unit to ten,etc.
{
if (lstTmp.Count == 1)
{
lstTmp.Clear();
lstTmp.Add('-');
return lstTmp;
}
lstTmp.RemoveAt(lstTmp.Count - 1);
lstVal = lstGetDecrName(lstTmp);
lstVal.Insert(lstVal.Count, chrTemp);
subCheckEmpty(ref lstVal);
return lstVal;
}

System.StringComparer that supports wildcard (*)

I'm looking for a fast .NET class/library that has a StringComparer that supports wildcard (*) AND incase-sensitivity.
Any Ideas?
You could use Regex with RegexOptions.IgnoreCase, then compare with the IsMatch method.
var wordRegex = new Regex( "^" + prefix + ".*" + suffix + "$", RegexOptions.IgnoreCase );
if (wordRegex.IsMatch( testWord ))
{
...
}
This would match prefix*suffix. You might also consider using StartsWith or EndsWith as alternatives.
Alternatively you can use these extended functions:
public static bool CompareWildcards(this string WildString, string Mask, bool IgnoreCase)
{
int i = 0;
if (String.IsNullOrEmpty(Mask))
return false;
if (Mask == "*")
return true;
while (i != Mask.Length)
{
if (CompareWildcard(WildString, Mask.Substring(i), IgnoreCase))
return true;
while (i != Mask.Length && Mask[i] != ';')
i += 1;
if (i != Mask.Length && Mask[i] == ';')
{
i += 1;
while (i != Mask.Length && Mask[i] == ' ')
i += 1;
}
}
return false;
}
public static bool CompareWildcard(this string WildString, string Mask, bool IgnoreCase)
{
int i = 0, k = 0;
while (k != WildString.Length)
{
if (i > Mask.Length - 1)
return false;
switch (Mask[i])
{
case '*':
if ((i + 1) == Mask.Length)
return true;
while (k != WildString.Length)
{
if (CompareWildcard(WildString.Substring(k + 1), Mask.Substring(i + 1), IgnoreCase))
return true;
k += 1;
}
return false;
case '?':
break;
default:
if (IgnoreCase == false && WildString[k] != Mask[i])
return false;
if (IgnoreCase && Char.ToLower(WildString[k]) != Char.ToLower(Mask[i]))
return false;
break;
}
i += 1;
k += 1;
}
if (k == WildString.Length)
{
if (i == Mask.Length || Mask[i] == ';' || Mask[i] == '*')
return true;
}
return false;
}
CompareWildcards compares a string against multiple wildcard patterns, and CompareWildcard compares a string against a single wildcard pattern.
Example usage:
if (Path.CompareWildcards("*txt;*.zip;", true) == true)
{
// Path matches wildcard
}
alternatively you can try following
class Wildcard : Regex
{
public Wildcard() { }
public Wildcard(string pattern) : base(WildcardToRegex(pattern)) { }
public Wildcard(string pattern, RegexOptions options) : base(WildcardToRegex(pattern), options) { }
public static string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern).
Replace("\\*", ".*").
Replace("\\?", ".") + "$";
}
}

Categories

Resources