c# how to convert char to VirtualKeyCode? - c#

I've been looking over here, but usually question is other way roud "how to convert virtualkey to char".
So I need to ask how to convert char into virtualkeycode?
I can perfectly fine work with F1, Ctrl etc., but can't figure out how to convert A to VK_A etc. in some convenient way.
I'm trying to let external configuration file hold some variables which then have to be used as virtualkeycodes in actual application.
I can recognize pairs like
Alt+F2, Shift+Control+F1 ... etc.
As those are just Enum 0-12 and then VirtualKeyCode.F1 + index
But I can't figure out those
Alt+F, Shift+Control+A ... etc.
I'm probably missing something very straightforward but unfortunately i can't see it.
Thanks
Edit:
Thanks to help from here I'm now able to convert "Ctrl+X" or "Shift-A" into VirtualKeyCode with this bit of code (still more like testing code)
public static void ParseKeys(string text)
{
Key key = 0;
Key mod = 0;
int current = 0;
string[] result;
string[] separators = new string[] { "+", "-" };
result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (string entry in result)
{
if (entry.Trim() == Keys.Control.ToString() || entry.Trim() == "Ctrl")
mod = Key.LeftCtrl;
if (entry.Trim() == Keys.Alt.ToString())
mod = Key.LeftAlt;
if (entry.Trim() == Keys.Shift.ToString())
mod = Key.LeftShift;
if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
mod = Key.LWin;
current++;
}
KeysConverter keyconverter = new KeysConverter();
key = (Key)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
var vmod = KeyInterop.VirtualKeyFromKey(mod);
System.Diagnostics.Trace.WriteLine((VirtualKeyCode)vmod + " = " + (VirtualKeyCode)key);
}
usage
ParseKeys("Alt+X");
I found out I would need to handle combinations like "Alt+Ctrl+X" or "Ctrl+X+Q" but indeed this code is for A+B combo. Can somebody please suggest some elegant solution to have at the end this:
VirtualKeyCode[] outsequence = { VirtualKeyCode.A , VirtualKeyCode.B, VirtualKeycode.C }
?
Thanks!

Related

C# issue when calculating a reference

I put together this little script whose goal is to calculate a reference according to the document type chosen in a form, and to concatenate a number that's auto-incremented. I am however getting this error when saving:
the string or binary data would be truncated
string typeDocAbbr = doc.GetStringValue("Document_type_Abbr");
string textRef = doc.GetStringValue("text_reference");
if (typeDocAbbr == "DIV")
returnValue = string.Format("{0}-{1}", typeDocAbbr, textRef);
if ((typeDocAbbr == "FIC") || (typeDocAbbr == "FTC") || (typeDocAbbr == "FDP"))
returnValue = string.Format("{0}-{1}", typeDocAbbr, textRef);
else
{
int chrono = 0;
string schrono = "";
if(string.IsNullOrEmpty(doc.GetStringValue("Reference")))
{
if (!string.IsNullOrEmpty(typeDocAbbr))
{
EDITOR.Documents.DataSource.ChronoManagerWrapper cmw =
new EDITOR.Documents.DataSource.ChronoManagerWrapper();
string Key = typeDocAbbr;
chrono = cmw.GetNewChrono("Process Studio", Key);
if (chrono < 10)
schrono = "0" + chrono.ToString();
else
schrono = chrono.ToString()};
}
}
returnValue = string.Format("{0}-{1}", typeDocAbbr, schrono);
}
This error :
the string or binary data would be truncated
is NOT on the code you shown. It is a SQL Server error.
It means that DB field is too small for the value you tried to insert.
Okay people, my bad.
I actually figured out where I went wrong. The returnValue of the script I shared went to feed a column the max size of which was 10 for some reason. However, as some of you so nicely pointed out to a beginner like me, the error was originating from the table, not the script, indicating that the value was too big for the column (that's what she said).
Thank you for some constructive criticism!

Get length of Substring from string

I have a following string 12 OT 14:51 2407 005 00:06 200 0009715008742 0.Now i have broken this string into string array based on space with following code..
string[] arrUser = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Now i have to select these above arrUser elements.Now as per my requirement i have to get the array element location from the original string till it reaches the next character(word) in the string .For example..
If i have selected 12 it should be like (0,2)
If i have selected 14:51 it should be like (7,12)
How to get this .Please help me ..
Am sorry i am not able to describe it better .Not getting to desc.
Thanks in advance..
You could do this a number of ways, the easiest of which is probably just to use string.IndexOf(string). You can just grab the index of the starting character, and you know the length from your input. That's that, then.
But if you want to be a bit more efficient (and fun--I'll admit that I answered this a bit just for the fun of it) about it, I'd probably just do it all in one pass. I haven't tested this, but it should do what you'd be looking for. Pretty simple.
public IEnumerable<Tuple<string, int>> SplitWithIndexes(string str, char splitChar)
{
StringBuilder ret = new StringBuilder();
int retStartIndex = 0;
for (int v = 0; v < str.Length; v++)
{
char c = str[v];
if (c == splitChar)
{
yield return new Tuple<string, int>(ret.ToString(), retStartIndex);
ret.Clear();
retStartIndex = v + 1;
}
else
{
ret.Append(c);
}
}
yield return new Tuple<string, int>(ret.ToString(), retStartIndex);
}

How to parse the following string

I am trying to generate a formula which could be anything like this, this is just a sample,
A + B + C > D - A
Now, A, B, C, D, etc are Column Names of a sheet (like excel sheet) i will be accessing in memory.
I need to generate a Rule, like the above A + B + C > D - A which will decide what kind of values user can add in a Cell.
Currently this is how i have begun:
string toValidate = "A + B + C > D + E - A";
string lhs = "", rhs = "";
string[] comparisonOperators = new string[] { "=", ">", "<", "<>", "!=" };
char[] arithmeticOperators = { '+', '-', '/', '*' };
toValidate = toValidate.Replace(#" ", "");
for (int i = 0; i < comparisonOperators.Length; i++)
{
if (toValidate.Contains(comparisonOperators[i]))
{
operatorIndex = toValidate.IndexOf(comparisonOperators[i]);
break;
}
}
lhs = toValidate.Substring(0, operatorIndex);
rhs = toValidate.Substring(operatorIndex + 1);
string[] columnLhsList = lhs.Split(arithmeticOperators);
string[] columnRhsList = rhs.Split(arithmeticOperators);
However even though i have the strings as lhs and rhs and even my operator which > in the above code, i am not able to understand how can i apply the formula on the sheet itself. I just need to know which Column has which operator associated.
Since i have the individual column names, but not the operator before them, for e.g,
+ before A - before A in another case.
How do i parse the above please help.
It is, however, a very fun question if you want to make simple formula parsers like this yourself.
I advice you to check out this article, since it is very clearly written and understandable because of it.
Shunting-yard Algorithm
Personally, I would never try/dare to create my own formula expression parser. Instead, I would (and did) use one of the may available ones, e.g. NCalc over at CodePlex.com.
Using these tools, it is as easy as writing
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
to get your formula evaluated.
Usually such libraries are very solid, well tested and have a rich function set. It would take ages (if ever) to do such a high quality library on my own.
To further cite the NCalc website, you can even use variables like e.g.:
Expression e = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");
e.Parameters["Pi2"] = new Expression("Pi * [Pi]");
e.Parameters["X"] = 10;
e.EvaluateParameter +=
delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());

c# longest common words sample

i am looking for a longest common words c# implementation. Most of the samples i have came across are comparing character by character.
in otherwords,
string1 = access
string2 = advised
should return null output from the function
any sample codes?
I think this problem is usually referred to as the Longest common substring problem. The Wikipedia article contains pseudocode, and C# implementations can be found on the Web.
If by word you mean these letter things, seperated from the others by punktuation, try this:
private String longestCommonWord(String s1, String s2)
{
String[] seperators = new String[] { " ", ",", ".", "!", "?", ";" };
var result = from w1 in s1.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where (from w2 in s2.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where w2 == w1
select w2).Count() > 0
orderby w1.Length descending
select w1;
if (result.Count() > 0)
{
return result.First();
}
else
{
return null;
}
}
This probably is not the most elegant way to do it, but it works for me. =)
Turning the algorithm which computes LCS of arrays of characters into one that does it to arrays of anything else -- like, say, an array of words -- is usually pretty straightforward. Have you tried that?
If you need some hints, here's an article I wrote a couple years ago on how to implement Longest Common Subsequence on an array of words in JScript. You should be able to adapt it to C# without too much difficulty.
http://blogs.msdn.com/ericlippert/archive/2004/07/21/189974.aspx
Finding differences in strings is called the Longest Common Subsequence problem. The following is a generic solution to the LCS problem, written in C#:
static int[,] GetLCSDifferenceMatrix<T>(
Collection<T> baseline,
Collection<T> revision)
{
int[,] matrix = new int[baseline.Count + 1, revision.Count + 1];
for (int baselineIndex = 0; baselineIndex < baseline.Count; baselineIndex++)
{
for (int revisionIndex = 0; revisionIndex < revision.Count; revisionIndex++)
{
if (baseline[baselineIndex].Equals(revision[revisionIndex]))
{
matrix[baselineIndex + 1, revisionIndex + 1] =
matrix[baselineIndex, revisionIndex] + 1;
}
else
{
int possibilityOne = matrix[baselineIndex + 1, revisionIndex];
int possibilityTwo = matrix[baselineIndex, revisionIndex + 1];
matrix[baselineIndex + 1, revisionIndex + 1] =
Math.Max(possibilityOne, possibilityTwo);
}
}
}
return matrix;
}
This code gives you a "difference" matrix, which can then be used to construct the difference from the two inputs. For unit tests and example usage, see http://sethflowers.com/2012/01/18/basic-diff-with-a-generic-solution-to-the-longest-common-subsequence-problem.html.

Testing for repeated characters in a string

I'm doing some work with strings, and I have a scenario where I need to determine if a string (usually a small one < 10 characters) contains repeated characters.
`ABCDE` // does not contain repeats
`AABCD` // does contain repeats, ie A is repeated
I can loop through the string.ToCharArray() and test each character against every other character in the char[], but I feel like I am missing something obvious.... maybe I just need coffee. Can anyone help?
EDIT:
The string will be sorted, so order is not important so ABCDA => AABCD
The frequency of repeats is also important, so I need to know if the repeat is pair or triplet etc.
If the string is sorted, you could just remember each character in turn and check to make sure the next character is never identical to the last character.
Other than that, for strings under ten characters, just testing each character against all the rest is probably as fast or faster than most other things. A bit vector, as suggested by another commenter, may be faster (helps if you have a small set of legal characters.)
Bonus: here's a slick LINQ solution to implement Jon's functionality:
int longestRun =
s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
So, OK, it's not very fast! You got a problem with that?!
:-)
If the string is short, then just looping and testing may well be the simplest and most efficient way. I mean you could create a hash set (in whatever platform you're using) and iterate through the characters, failing if the character is already in the set and adding it to the set otherwise - but that's only likely to provide any benefit when the strings are longer.
EDIT: Now that we know it's sorted, mquander's answer is the best one IMO. Here's an implementation:
public static bool IsSortedNoRepeats(string text)
{
if (text.Length == 0)
{
return true;
}
char current = text[0];
for (int i=1; i < text.Length; i++)
{
char next = text[i];
if (next <= current)
{
return false;
}
current = next;
}
return true;
}
A shorter alternative if you don't mind repeating the indexer use:
public static bool IsSortedNoRepeats(string text)
{
for (int i=1; i < text.Length; i++)
{
if (text[i] <= text[i-1])
{
return false;
}
}
return true;
}
EDIT: Okay, with the "frequency" side, I'll turn the problem round a bit. I'm still going to assume that the string is sorted, so what we want to know is the length of the longest run. When there are no repeats, the longest run length will be 0 (for an empty string) or 1 (for a non-empty string). Otherwise, it'll be 2 or more.
First a string-specific version:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Now we can also do this as a general extension method on IEnumerable<T>:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Then you can call "AABCD".LongestRun() for example.
This will tell you very quickly if a string contains duplicates:
bool containsDups = "ABCDEA".Length != s.Distinct().Count();
It just checks the number of distinct characters against the original length. If they're different, you've got duplicates...
Edit: I guess this doesn't take care of the frequency of dups you noted in your edit though... but some other suggestions here already take care of that, so I won't post the code as I note a number of them already give you a reasonably elegant solution. I particularly like Joe's implementation using LINQ extensions.
Since you're using 3.5, you could do this in one LINQ query:
var results = stringInput
.ToCharArray() // not actually needed, I've left it here to show what's actually happening
.GroupBy(c=>c)
.Where(g=>g.Count()>1)
.Select(g=>new {Letter=g.First(),Count=g.Count()})
;
For each character that appears more than once in the input, this will give you the character and the count of occurances.
I think the easiest way to achieve that is to use this simple regex
bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, #"(\w)\1");
If you need more information about the match (start, length etc)
Match match = null;
string testString = "ABCDE AABCD";
match = Regex.Match(testString, #"(\w)\1+?");
if (match.Success)
{
string matchText = match.Value; // AA
int matchIndnex = match.Index; // 6
int matchLength = match.Length; // 2
}
How about something like:
string strString = "AA BRA KA DABRA";
var grp = from c in strString.ToCharArray()
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in grp)
{
Console.WriteLine(
string.Format("Character:{0} Appears {1} times",
item.Key.ToString(), item.Count));
}
Update Now, you'd need an array of counters to maintain a count.
Keep a bit array, with one bit representing a unique character. Turn the bit on when you encounter a character, and run over the string once. A mapping of the bit array index and the character set is upto you to decide. Break if you see that a particular bit is on already.
/(.).*\1/
(or whatever the equivalent is in your regex library's syntax)
Not the most efficient, since it will probably backtrack to every character in the string and then scan forward again. And I don't usually advocate regular expressions. But if you want brevity...
I started looking for some info on the net and I got to the following solution.
string input = "aaaaabbcbbbcccddefgg";
char[] chars = input.ToCharArray();
Dictionary<char, int> dictionary = new Dictionary<char,int>();
foreach (char c in chars)
{
if (!dictionary.ContainsKey(c))
{
dictionary[c] = 1; //
}
else
{
dictionary[c]++;
}
}
foreach (KeyValuePair<char, int> combo in dictionary)
{
if (combo.Value > 1) //If the vale of the key is greater than 1 it means the letter is repeated
{
Console.WriteLine("Letter " + combo.Key + " " + "is repeated " + combo.Value.ToString() + " times");
}
}
I hope it helps, I had a job interview in which the interviewer asked me to solve this and I understand it is a common question.
When there is no order to work on you could use a dictionary to keep the counts:
String input = "AABCD";
var result = new Dictionary<Char, int>(26);
var chars = input.ToCharArray();
foreach (var c in chars)
{
if (!result.ContainsKey(c))
{
result[c] = 0; // initialize the counter in the result
}
result[c]++;
}
foreach (var charCombo in result)
{
Console.WriteLine("{0}: {1}",charCombo.Key, charCombo.Value);
}
The hash solution Jon was describing is probably the best. You could use a HybridDictionary since that works well with small and large data sets. Where the letter is the key and the value is the frequency. (Update the frequency every time the add fails or the HybridDictionary returns true for .Contains(key))

Categories