Okay so I'm making an auto typer and I want the user to be able to enter the keys {}()^+ and have the application out put. I know that you need to format the symbols like SendKeys.Send({^}); but I cant get this to work. Heres what I have so far for my Timer Tick. Also, I have global int blockCount, which tells the program to move on to the next character in the blockText string.
It returns "Group delimiters are not balanced."
private void timer3_Tick(object sender, EventArgs e)
{
string blockText = richTextBox1.Text;
int blockLength = richTextBox1.TextLength;
btrand = RandomNumber(75, 200); //I have a method to make a rand num
timer3.Interval = btrand;
char[] specialChars = { '{', '}', '(', ')', '+','^' };
foreach (char letter in blockText)
{
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
SendKeys.Send("{" + specialChars[i] + "}");
blockText.Remove(blockText.IndexOf(specialChars[i].ToString()));
}
else
{
SendKeys.Send(letter.ToString());
}
}
}
blockCount++;
if (blockCount >= blockLength)
{
blockCount = 0;
}
}
Ok, quick analysis, so forgive me if I miss something.
You're doing a foreach using blockText as your collection, and manipulating it if a special char is found. This can be messy; I would think on another way to implement this.
You're looping through all special chars, and for each interaction that you can't identify a match you're sending the current letter. That means you're re-sending all non-special characters for the number of elements in the specialChars array minus one. I don't think that's what you've intended to do.
I would suggest an implementation like this:
foreach (char letter in blockText)
{
bool _specialCharFound = false;
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
_specialCharFound = true;
break;
}
}
if (_specialCharFound)
SendKeys.Send("{" + letter.ToString() + "}");
else
SendKeys.Send(letter.ToString());
}
There are more optimized ways to implement, but I would choose this one out of clarity of purpose and similarity to your original code.
Related
Here is what I have so far, it is set up to display the total number of words, which I need to keep, or modify to keep to allow the average number of letters in each word to be displayed, please assist anyone if you can. thank you so much!:
private void btnCheck_Click(object sender, EvenArgs e)
{
string words = tbxArgument.Text.Trim();
MessageBox.Show("Number of Words: " + CountWords(words));
}
private int CountWords(string words)
{
string[] allWords = words.Split(' ');
return allWords.Length;
}
Not sure If this is what you are trying to accomplish.
But this will give you the average length of all the words.
double totalCharacters = 0;
double avgCharacters = 0;
string[] words = new string[] {"Word1","Word2","Word3" } ;
foreach (string tmpString in words)
{
totalCharacters = totalCharacters + tmpString.Length;
}
avgCharacters = totalCharacters/words.Length;
This is a method that only interate over the string, without making splits that require allocate extra memory. Just an optimization, for entertainment:
public static double GetAvgLetters(string text, out int wordsCount)
{
wordsCount = 0;
if (string.IsNullOrWhiteSpace(text))
{
return double.NaN;
}
var lettersCount = 0;
var isLetter = text[0] != ' ';
var readingLetter = isLetter;
for (int i = 0; i < text.Length; i++)
{
isLetter = text[i] != ' ';
if (isLetter != readingLetter)
{
readingLetter = isLetter;
if (readingLetter)
{
lettersCount++;
}
else
{
wordsCount++;
}
}
else if (isLetter)
{
lettersCount++;
}
}
if (isLetter == readingLetter && isLetter)
{
wordsCount++;
}
return lettersCount / (double)wordsCount;
}
I simply iterate checking the changes between blank and not blank (to count words) and, while reading letters, counting letters. At the end, if we are reading letters and last char is a letter, we must add the last word to count.
string sentence = "This is a goodday";
string word = "good";
I know this can be done with .Contains() method. I was asked in an interview how to do it without contains method.
how to do it in english.
pick the first letter of word.
walk down sentence a character at a time till you find that letter
now look at the next letters in sentence to see if they are the rest of that word
yes - done
no - keep going
the thing to use is that word[x] is the x-1th character of word, so you just need 2 indexes and a loop or 2
Q: Check if a word exists in another string in c# without using any inbuilt function
A: Tricky
It depends on how detailed that "any inbuilt function" really is.
In general the algorithm is simple:
Loop through the string you're searching in
for each position, see if you've found the word
you do this by looping through all the characters in what we're looking for
and compare each character from the first string with one from the second
if they all matched, we've found a match
but then ... "without using any inbuilt function".
I assume this would mean, do not use the obvious ones, such as Contains, IndexOf, a regular expression, all those things.
But taken to the extreme, does that mean I cannot even know how long the strings are? Is s.Length a built-in function? And thus not allowed?
public bool Contains(string value, string whatWereLookingFor)
{
return IndexOf(value, whatWereLookingFor) >= 0;
}
public int Length(string s)
{
int result = 0;
for (int i = 0; i <= 2147483647; i++)
{
try
{
char c = s[i];
}
catch (IndexOutOfRangeException)
{
break;
}
result = i + 1;
}
return result;
}
public int IndexOf(string value, string whatWereLookingFor)
{
int iMax = Length(value);
int whatMax = Length(whatWereLookingFor);
for (int i = 0; i <= iMax - whatMax; i++)
{
bool isMatch = true;
for (int j = 0; j < whatMax; j++)
{
if (value[i + j] != whatWereLookingFor[j])
{
isMatch = false;
break;
}
}
if (isMatch)
return i;
}
return -1;
}
How about using a for loop?
Loop through the sentence checking for the first character of the work. Once you find that check for the next character of the word until you find the whole word (done - word exists in sentence) or a different character so you start again looking for the first character of the word until you run out of characters.
As the comments say, it would have been nicer to let us know what you answered.
try this:
static bool checkString(string inputString="",string word="")
{
bool returV=false;
if(inputString =="" || word=="")
return false;
int intexcS=0;
Dictionary<int,string> d = new Dictionary<int, string>();
foreach (char cW in word)
{
foreach (char cS in inputString)
{
if(cW==cS){
if(!d.ContainsKey(intexcS) && d.Count<word.Length){
d.Add(intexcS,cW.ToString());
}
}
intexcS++;
}
intexcS=0;
}
int i=0;
foreach(var iitem in d) { if(iitem.Value!=word[i].ToString()) returV=false; else returV=true; i++; }
return returV;
}
I made a Infix to Postfix convertor, and thought it worked, but when I went back and showed it to my teacher one of the examples he tested turns out wrong. :|
I would be grateful if someone could help me on this matter, and let me know what's wrong.
I skipped the parts about the buttons for inputting numbers and only posted the rest of it,
private void button20_Click(object sender, EventArgs e)
{
try
{
string infix = textBox1.Text;
infixTopostfix obj = new infixTopostfix(infix);
textBox1.Text = string.Empty;
Console.WriteLine("{0} is the Postfix of {1}", obj.createPrifex(), infix);
}
catch (Exception e1)
{
Console.WriteLine(e1.ToString());
}
}
The part above is for redirecting a console.writeline to my text box and its the button that does all the works and gives the final result.
Here is the main class:
class infixTopostfix
{
public infixTopostfix(string strTemp)
{
strInput = strTemp;
}
private int isOperand(char chrTemp)
{
char[] op = new char[6] { '*', '/', '+', '-', '^', '(' };
foreach (char chr in op)
if (chr == chrTemp)
{
return 1;
}
return 0;
}
private int isOperator(char chrTemp)
{
char[] op = new char[5] { '*', '/', '+', '-', '^' };
foreach (char chr in op)
if (chr == chrTemp)
{
return 1;
}
return 0;
}
private string strResualt = null;
private string strInput = null;
public string createPrifex()
{
int intCheck = 0;
//int intStackCount = 0;
object objStck = null;
for (int intNextToken = 0; intNextToken <= strInput.Length - 1; intNextToken++)
{
intCheck = isOperand(strInput[intNextToken]);
if (intCheck == 1)
stkOperatore.Push(strInput[intNextToken]);
else
if (strInput[intNextToken] == ')')
{
int c = stkOperatore.Count;
for (int intStackCount = 0; intStackCount <= c - 1; intStackCount++)
{
objStck = stkOperatore.Pop();
intCheck = isOperator(char.Parse(objStck.ToString()));
if (intCheck == 1)
{
strResualt += objStck.ToString();
}
}
}
else
strResualt += strInput[intNextToken];
}//end of for(int intNextToken...)
int intCount = stkOperatore.Count;
if (intCount > 0)
{
int c = stkOperatore.Count;
for (int intStackCount = 0; intStackCount <= c - 1; intStackCount++)
{
objStck = stkOperatore.Pop();
intCheck = isOperator(char.Parse(objStck.ToString()));
if (intCheck == 1)
{
strResualt += Convert.ToString(objStck);
}
}
}
return strResualt;
}
private System.Collections.Stack stkOperatore = new System.Collections.Stack();
}
}
Here is the input that fails:
A^B^(C-D/(E+F))-(G+H)^L*Z+Y
the result of this code which is incorrect:
ABCDEF+/-^^GH+-LZY+*^
The correct result:
ABCDEF+/-^^GH+L^Z*-Y+
When converting infix notation to postfix notation, AKA reverse polish notation, one must take into account operator precedence and operator associativity. These are usually implemented as a table and looked up in the table based on the operator character.
e.g.
Java
C#
C++
As I do not see any mention of precedence or associativity in your code; so I would say your code does not have a bug but an invalid algorithm.
The classic algorithm to convert infix to postfix is the shunting yard algorithm by Edsger Dijkstra and is probably the means closest to what you are trying to implement.
I would suggest that you work with pen an paper to understand the shunting algorithm then implement the algorithm using many test cases that progressively use more combinations of the operators.
The best explanation I know of is Shunting Yard Algorithm
If you Google for C# shunting yard you will find many implementations, just make sure if you use one it is correct. Many people like to post examples of this but often have a mistake. Verify they work against many test cases before you waste time with them.
int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(0, 9);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}
So, I'm doing this tutorial thing, and I've been stuck on this exercise for like 4 hours. And I can't figure out what's wrong with my For Loop.
The point of the exercise is to make my program thing tell me how many g's are in the word debugging. But you probably figured that out. Anyway, I'm not even sure that I have the right code for telling me that, because I think that I need to change the second part of the For Loop (the i < ) part.
But my problem is that it isn't registering the "if letter == "g" " at all. Because according to my locals window it says that letter=Debugging, which would make me think that g should be registering on my program 24 times, I think (because str.length is 9 letters long?) But it's registering as 0 no matter what I do.
You are extracting a string of 9 characters. It will never be equal to "g" (which only has one). Here's how I'd do it.
int count = 0;
foreach (char c in strText)
{
if (c == 'g')
count++;
}
Using the for loop:
for (int i = 0; i < strText.Length; i++)
{
if (strText[i] == 'g')
count++;
}
Take a look at the documentation for string.Substring(x, y).
Basically:
letter = strText.Substring(0, 9);
Isn't giving you a letter. Each time through it's giving you all 9 characters of the string strText. You might want to consider using the variable i for one of the values you pass to Substring.
(I've deliberately not given you the entire answer as you seem to want to understand, so, if the pointers I've given don't get you there, let me know and I'll expand my answer =)
Try this:
for (int i = 0; i <strText.Length; i++)
{
if(strText[i] == 'g')
{
LetterCount++;
}
}
textBox1.Text = "g appears " + LetterCount + " times";
The issue is that you are looking at the entire string when you compare to "g". By specifying an index you are telling it to look at a specific character in the string. Also, I removed your substring because it did not appear to be doing anything.
You're not using i at all in your for loop.
Do you mean
letter = strText.Substring(i, 1);
?
Well, you are taking substring that is long 9 charachters and comparing it to "g". It won't be equal.
You should try:
letter = strText.Substring(i,1);
Because String.Substring(int, int) takes two arguments: the offset and amount to take.
In your case, letter = strText.Substring(0, 9); will simply assign letter's value to "Debugging". If you want to check each letter individually, you need to write letter = strText.Substring(i, 1).
You're probably looking for something like this:
int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(i, 1);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}
letter = strText.Substring(0, 9);
at this point, 'letter' has the value "Debugging" since you're taking the entire string.
Try letter = strText[i] so you isolate the single letter.
What #Rob said.
Try something like this:
int gCount = 0;
string s = "Debugging";
for ( int i = 0; i <strText.Length; i++)
{
if ( s[i] == 'g' ) ++gCount ;
}
textBox1.Text = "g appears " + gCount+ " times";
namespace runtime
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int lettercount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i < strText.Length; i++)
{
letter = strText.Substring(i,1);
if (letter == "g")
{
lettercount++;
}
}
textBox1.Text = "g appear " + lettercount + " times";
}
}
}
I'm a little surprised that there isn't some information on this on the web, and I keep finding that the problem is a little stickier than I thought.
Here's the rules:
You are starting with delimited/escaped data to split into an array.
The delimiter is one arbitrary character
The escape character is one arbitrary character
Both the delimiter and the escape character could occur in data
Regex is fine, but a good-performance solution is best
Edit: Empty elements (including leading or ending delimiters) can be ignored
The code signature (in C# would be, basically)
public static string[] smartSplit(
string delimitedData,
char delimiter,
char escape) {}
The stickiest part of the problem is the escaped consecutive escape character case, of course, since (calling / the escape character and , the delimiter): ////////, = ////,
Am I missing somewhere this is handled on the web or in another SO question? If not, put your big brains to work... I think this problem is something that would be nice to have on SO for the public good. I'm working on it myself, but don't have a good solution yet.
A simple state machine is usually the easiest and fastest way. Example in Python:
def extract(input, delim, escape):
# states
parsing = 0
escaped = 1
state = parsing
found = []
parsed = ""
for c in input:
if state == parsing:
if c == delim:
found.append(parsed)
parsed = ""
elif c == escape:
state = escaped
else:
parsed += c
else: # state == escaped
parsed += c
state = parsing
if parsed:
found.append(parsed)
return found
void smartSplit(string const& text, char delim, char esc, vector<string>& tokens)
{
enum State { NORMAL, IN_ESC };
State state = NORMAL;
string frag;
for (size_t i = 0; i<text.length(); ++i)
{
char c = text[i];
switch (state)
{
case NORMAL:
if (c == delim)
{
if (!frag.empty())
tokens.push_back(frag);
frag.clear();
}
else if (c == esc)
state = IN_ESC;
else
frag.append(1, c);
break;
case IN_ESC:
frag.append(1, c);
state = NORMAL;
break;
}
}
if (!frag.empty())
tokens.push_back(frag);
}
private static string[] Split(string input, char delimiter, char escapeChar, bool removeEmpty)
{
if (input == null)
{
return new string[0];
}
char[] specialChars = new char[]{delimiter, escapeChar};
var tokens = new List<string>();
var token = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
var c = input[i];
if (c.Equals(escapeChar))
{
if (i >= input.Length - 1)
{
throw new ArgumentException("Uncompleted escape sequence has been encountered at the end of the input");
}
var nextChar = input[i + 1];
if (nextChar != escapeChar && nextChar != delimiter)
{
throw new ArgumentException("Unknown escape sequence has been encountered: " + c + nextChar);
}
token.Append(nextChar);
i++;
}
else if (c.Equals(delimiter))
{
if (!removeEmpty || token.Length > 0)
{
tokens.Add(token.ToString());
token.Length = 0;
}
}
else
{
var index = input.IndexOfAny(specialChars, i);
if (index < 0)
{
token.Append(c);
}
else
{
token.Append(input.Substring(i, index - i));
i = index - 1;
}
}
}
if (!removeEmpty || token.Length > 0)
{
tokens.Add(token.ToString());
}
return tokens.ToArray();
}
The implementation of this kind of tokenizer in terms of a FSM is fairly straight forward.
You do have a few decisions to make (like, what do I do with leading delimiters? strip or emit NULL tokens).
Here is an abstract version which ignores leading and multiple delimiters, and doesn't allow escaping the newline:
state(input) action
========================
BEGIN(*): token.clear(); state=START;
END(*): return;
*(\n\0): token.emit(); state=END;
START(DELIMITER): ; // NB: the input is *not* added to the token!
START(ESCAPE): state=ESC; // NB: the input is *not* added to the token!
START(*): token.append(input); state=NORM;
NORM(DELIMITER): token.emit(); token.clear(); state=START;
NORM(ESCAPE): state=ESC; // NB: the input is *not* added to the token!
NORM(*): token.append(input);
ESC(*): token.append(input); state=NORM;
This kind of implementation has the advantage of dealing with consecutive excapes naturally, and can be easily extended to give special meaning to more escape sequences (i.e. add a rule like ESC(t) token.appeand(TAB)).
Here's my ported function in C#
public static void smartSplit(string text, char delim, char esc, ref List<string> listToBuild)
{
bool currentlyEscaped = false;
StringBuilder fragment = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (currentlyEscaped)
{
fragment.Append(c);
currentlyEscaped = false;
}
else
{
if (c == delim)
{
if (fragment.Length > 0)
{
listToBuild.Add(fragment.ToString());
fragment.Remove(0, fragment.Length);
}
}
else if (c == esc)
currentlyEscaped = true;
else
fragment.Append(c);
}
}
if (fragment.Length > 0)
{
listToBuild.Add(fragment.ToString());
}
}
Hope this helps someone in the future. Thanks to KenE for pointing me in the right direction.
Here's a more idiomatic and readable way to do it:
public IEnumerable<string> SplitAndUnescape(
string encodedString,
char separator,
char escape)
{
var inEscapeSequence = false;
var currentToken = new StringBuilder();
foreach (var currentCharacter in encodedString)
if (inEscapeSequence)
{
currentToken.Append(currentCharacter);
inEscapeSequence = false;
}
else
if (currentCharacter == escape)
inEscapeSequence = true;
else
if (currentCharacter == separator)
{
yield return currentToken.ToString();
currentToken.Clear();
}
else
currentToken.Append(currentCharacter);
yield return currentToken.ToString();
}
Note that this doesn't remove empty elements. I don't think that should be the responsibility of the parser. If you want to remove them, just call Where(item => item.Any()) on the result.
I think this is too much logic for a single method; it gets hard to follow. If someone has time, I think it would be better to break it up into multiple methods and maybe its own class.
You'ew looking for something like a "string tokenizer". There's a version I found quickly that's similar. Or look at getopt.