I am working on C# windows form. I want to make a comparison as below scenario.
I have two textbox. The first text box (textbox1) is readonly and contain text: "This is my first Windows Application using C#." The second textbox (textbox2) is for user typing the text the same as text in textbox1. If user typed wrong characters I would display the number of characters errors in a label (lblError).
Example: If user type "the" then lblError should display "1"
Thanks,
Man
Code example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void CompareWords(string a, string b)
{
List<string> diff;
IEnumerable<string> set1 = a.Split(' ').Distinct();
IEnumerable<string> set2 = b.Split(' ').Distinct();
if (set2.Count() > set1.Count())
{
diff = set2.Except(set1).ToList();
}
else
{
diff = set1.Except(set2).ToList();
}
labelWrong.Text = ("Wrong words: " + diff.Count());
}
private void CompareChars(string a, string b)
{
List<string> diff = new List<string>();
if (a == b) //Same string, no iteration needed.
lblWrongChars.Text = ("Wrong chars: " + 0);
if ((a.Length == 0) || (b.Length == 0)) //One is empty
{
lblWrongChars.Text = ("Wrong chars: " + (a.Length == 0 ? b.Length : a.Length));
}
double maxLen = a.Length > b.Length ? a.Length : b.Length;
int minLen = a.Length < b.Length ? a.Length : b.Length;
int sameCharAtIndex = 0;
for (int i = 0; i < minLen; i++) //Compare char by char
{
if (a[i] == b[i])
{
diff.Add(b[i].ToString() + ",");
sameCharAtIndex++;
}
}
lblWrongChars.Text = ("Wrong chars: " + (a.Length - diff.Count()));
}
private void txtReadOnly_KeyDown(object sender, KeyEventArgs e)
{
string lastchar_inserted = e.KeyValue.ToString();
if (lastchar_inserted == "32")
{
CompareWords(txtReadOnly.Text, txtUserType.Text);
}
CompareChars(txtReadOnly.Text, txtUserType.Text);
}
}
Related
I'm working on a program that encodes and decodes letters to numbers. I have the Encoding properly built but the decoding is giving me problems. I'm using int to char conversions with the ASCII table as the key. It doesn't seem like the conversion logic for the decoding is right but I really have no idea how to fix it. This is my first time using this conversion method so I still don't fully understand it.
*edit This is on a windows form app that has three buttons and two text boxes. Encode is one button, and you type in a sentence and it outputs in in numbers for each letter. Decode is another but it does the opposite type in numbers and get words. the third button is clear so thats not important. Sorry I left this out of the initial question.
class LetterCodeLogic
{
public static string Encode(string msg)
{
string result = "";
string m = msg.ToUpper();
char c;
int x;
for(int i = 0; i < m.Length; i++)
{
c = Convert.ToChar(m[i]);
x = c;
if (x == 32)
{
x = 0;
}
else
{
x -= 64;
if (x < 1 || x > 26)
{
x = 99;
}
}
result += x.ToString() + " ";
}
return result;
}
public static string Decode(string msg)
{
string result = "";
string[] nums = msg.Split(',');
char c;
int x;
for (int i = 0; i < msg.Length; i++)
{
x = Convert.ToChar(msg[i]);
c = (char)x;
if (c == 0)
{
c = (char)32;
}
else
{
c -= (char)64;
if (c < 65 || c > 90)
{
c = (char)35;
}
}
result += c.ToString() + " ";
}
return result;
}
}
I find problems like this are far easier when you break them into parts. First, write functions that convert a single character to a number or vice versa.
static public byte Encode(char c)
{
if (c == ' ') return 0;
if (c >= 'A' && c <= 'Z') return (byte)(c - 'A' + 1);
return 99;
}
static public char Decode(byte n)
{
if (n == 0) return ' ';
if (n >= 1 && n <= 27) return (char)(n + 'A' - 1);
return '#';
}
Now the functions you need are very easy to write:
static public string Encode(string stringInput)
{
return string.Join(" ", stringInput.Select(Encode).Select( b => b.ToString() ));
}
static public string Decode(string numericInput)
{
return new string(numericInput.Split(' ').Select( n => byte.Parse(n)).Select(Decode).ToArray());
}
What I want to do is to split an array and then put the character which i split at into another element
i.e. string text = "1*5+89-43&99" should become string[] textsplit = ["1","*","5","+","89","-","43","&","99"] (it must be a string)
and I will supply the characters to be left in seperate elements
You can do this using string.IndexOfAny.
Simply keep looking for the next index of any of the separators. When you find a separator, add the text between it and the last separator to your results, then look for the next separator.
string input = "1*1*5+89-43&33";
var separators = new[] { '+', '-', '*', '/', '&' };
var result = new List<string>();
int index;
int lastIndex = 0;
while ((index = input.IndexOfAny(separators, lastIndex)) != -1)
{
// Add the text before the separator, if there is any
if (index - lastIndex > 0)
{
result.Add(input.Substring(lastIndex, index - lastIndex));
}
// Add the separator itself
result.Add(input[index].ToString());
lastIndex = index + 1;
}
// Add any text after the last separator
if (lastIndex < input.Length)
{
result.Add(input.Substring(lastIndex));
}
Try with the following code snippet:
string text = "1*1*5+89-43&33";
List<string> textsplit = new List<string>();
foreach(var match in Regex.Matches(text, #"([*+/\-)(])|([0-9]+)"))
{
textsplit.Add(match.ToString());
}
Result added as an image.
Here's a basic and naive implementation that I beliewe will do what you want:
public static List<string> SplitExpression(string expression)
{
var parts = new List<string>();
bool isNumber(char c) => c == '.' || (c >= '0' && c <= '9');
bool isOperator(char c) => !isNumber(c);
int index = 0;
while (index < expression.Length)
{
char c = expression[index];
index++;
if (isNumber(c))
{
int numberIndex = index - 1;
while (index < expression.Length && isNumber(expression[index]))
index++;
parts.Add(expression.Substring(numberIndex, index - numberIndex));
}
else
parts.Add(c.ToString());
}
// move unary signs into following number
index = 0;
while (index < parts.Count - 1)
{
bool isSign = parts[index] == "-" || parts[index] == "+";
bool isFirstOrFollowingOperator = index == 0 || isOperator(parts[index - 1][0]);
bool isPriorToNumber = isNumber(parts[index + 1][0]);
if (isSign && isFirstOrFollowingOperator && isPriorToNumber)
{
parts[index + 1] = parts[index] + parts[index + 1];
parts.RemoveAt(index);
}
else
index++;
}
return parts;
}
Example input: "-1+-2*-10.1*.1", and output:
-1
+
-2
*
-10.1
*
.1
I am trying to write a code that lists roots of given number.
This is what I did so far. The result I get is 2*2*5*5 which is true but I want to get this instead: 2^2*5^2.
public partial class Form1 : Form
{
List<int> divisor;
public Form1()
{
InitializeComponent();
}
private void list_Click(object sender, EventArgs e)
{
int number;
divisor = new List<int>();
showroot.Text = "";
number = Int32.Parse(usernum.Text);
for (int i = 2; i <= number; i++)
{
if (number % i == 0)
{
divisor.Add(i);
number = number / i;
i = 1;
}
}
for (int i = 0; i < divisor.Count; i++)
{
print(""+ divisor[i]);
}
}
private void print(String text)
{
if (showroot.Text != "")
{
showroot.Text = showroot.Text + "*" + text;
}
else
{
showroot.Text = text;
}
}
}
I tried to check how much same root and count them by two for statements nested but that brings another errors within.
for (int i = 0; i < divisor.Count; i++) {
for (int a = 0; i < divisor.Count; a++) {
if (i == a) {
base[i]++;
}
}
}
What to do?
Split the task into easy to implement portions, extract methods:
First of all, let's collect all prime divisors (divisors can repeat):
private static IEnumerable<int> AllPrimeDivisors(int value) {
if (value <= 1)
yield break;
for (; value % 2 == 0; value /= 2)
yield return 2;
int n = (int)(Math.Sqrt(value) + 0.5);
for (int d = 3; d <= n; d += 2) {
while (value % d == 0) {
yield return d;
value /= d;
n = (int)(Math.Sqrt(value) + 0.5);
}
}
if (value > 1)
yield return value;
}
Then combine them in required format (we should GroupBy the same - repeating - divisors and represent them either in divisor or in divisor^power format)
private static string Solve(int value) {
var terms = AllPrimeDivisors(value)
.GroupBy(divisor => divisor)
.Select(group => group.Count() == 1
? $"{group.Key}"
: $"{group.Key}^{group.Count()}");
return string.Join("*", terms);
}
Finally add UI:
private void list_Click(object sender, EventArgs e) {
if (int.TryParse(usernum.Text, out var number))
showroot.Text = Solve(number);
else
showroot.Text = "Incorrect Input, Syntax Error";
}
Tests:
int[] tests = new int[] {
3, 5, 9, 12, 16, 41, 81, 100,
};
var result = tests
.Select(item => $"{item,3} == {Solve(item)}");
Console.Write(string.Join(Environment.NewLine, result));
Outcome:
3 == 3
5 == 5
9 == 3^2
12 == 2^2*3
16 == 2^4
41 == 41
81 == 3^4
100 == 2^2*5^2
A naive implementation would be by changing your for to this:
for (int i = 2; i <= number; i++)
{
count = 0;
while (number % i == 0)
{
number = number / i;
count++;
}
if (count > 0)
{
divisor.Add(i);
powers.Add(count);
}
}
However a lot of optimizations can be done.
My initial code is 'A0AA' and I need a code/function in C# that will increment it until it goes to 'Z9ZZ'.
for example.
first code is 'D9ZZ'
the next code should be 'E0AA'
sorry maybe my example is quite confusing.. here's another example.. thanks.
first code is 'D9AZ'
the next code should be 'D9BA'
string start = "A9ZZ";
int add = 1;
string next = String.Concat(start.Reverse().Select((x,i) =>
{
char first = i == 2 ? '0' : 'A';
char last = i == 2 ? '9' : 'Z';
if ((x += (char)add) > last)
{
return first;
}
else
{
add = 0;
return x;
}
})
.Reverse());
This should fix it.
private static IEnumerable<string> Increment(string value)
{
if (value.Length != 4)
throw new ArgumentException();
char[] next = value.ToCharArray();
while (new string(next) != "Z9ZZ")
{
next[3]++;
if (next[3] > 'Z')
{
next[3] = 'A';
next[2]++;
}
if (next[2] > 'Z')
{
next[2] = 'A';
next[1]++;
}
if (next[1] > '9')
{
next[1] = '0';
next[0]++;
}
yield return new string(next);
}
}
Example of calling this code:
IList<string> values = Increment("A0AA").Take(100).ToList();
foreach (var value in values)
{
Console.Write(value + " ");
}
Here's a pretty clean solution that checks every character starting at the end:
public SomeMethod()
{
var next = Increment("A2CZ"); // A2DZ
}
public string Increment(string code)
{
var arr = code.ToCharArray();
for (var i = arr.Length - 1; i >= 0; i--)
{
var c = arr[i];
if (c == 90 || c == 57)
continue;
arr[i]++;
return new string(arr);
}
return code;
}
I was working on C++ with Juce Library for few months. I had written a code in my project where the formatting of textbox was modified to only hexadecimal values with few features:
Demonstratation:
12 ab 32 a5 64
Now if my cursor is at the end and i go on pressing backspace, it shud remove the values as it happens in a general text box.
Now If my cursor is at the beginning of a5, and i press "delete key", the value should become like:
12 ab 32 56 4
If my cursor is at the end of a5 and i press the 'delete key" nothing should happen. while entering the values space bar should not let spacing bw two values. Only a-f and 0-9 should be allowed to enter.
Code in C++ here:
void CMSP430CommPanel::textEditorTextChanged (TextEditor& editor)
{
if(&editor == m_texti2cWrite)
{
int count = 0;
int location;
String text1 = m_texti2cWrite->getText();
String text = m_texti2cWrite->getText().removeCharacters(" ");
String hexString = String::empty;
int countCaret = m_texti2cWrite->getCaretPosition();
for(int i=0; i < text.length(); i++)
{
hexString = hexString + String (&text[i], 1);
if((i+1) % 2 == 0)
{
if(i != text.length()-1)
{
hexString = hexString + T(" ");
count ++;
}
}
count ++;
}
m_texti2cWrite->setText(hexString,false);
if(text1.length() == m_texti2cWrite->getCaretPosition())
{
m_texti2cWrite->setCaretPosition(count);
}
else
{
m_texti2cWrite->setCaretPosition(countCaret);
}
}
}
I want the same thing to work in my WPF application. Lets say the general implementation of the same code in C#.
please help!!!
Try this (TextChanged-Event of your TextBox):
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox m_texti2cWrite = (TextBox)sender;
int count = 0;
string text1 = m_texti2cWrite.Text;
string text = m_texti2cWrite.Text.Replace(" ", string.Empty);
string hexString = string.Empty;
int countCaret = e.Changes.ToList()[0].Offset;
for (int i = 0; i < text.Length; i++)
{
hexString += text[i];
if ((i + 1) % 2 == 0)
{
if (i != text.Length - 1)
{
hexString = hexString + " ";
count++;
}
}
count++;
}
m_texti2cWrite.Text = hexString;
if (text1.Length == countCaret)
{
m_texti2cWrite.Select(count, 0);
}
else
{
if (e.Changes.ToList()[0].RemovedLength == 0)
{
m_texti2cWrite.Select(countCaret + 1, 0);
if (string.IsNullOrWhiteSpace(hexString.Substring(countCaret, 1)))
m_texti2cWrite.Select(countCaret + 2, 0);
}
else
{
m_texti2cWrite.Select(countCaret, 0);
if (string.IsNullOrWhiteSpace(hexString.Substring(countCaret, 1)))
m_texti2cWrite.Select(countCaret + 1, 0);
}
}
}
}
EDIT (only accept Digits, ControlKeys or a-f):
Add this method:
private Boolean IsTextAllowed(String text)
{
string acceptedChars = "ABCDEFabcdef";
foreach (Char c in text.ToCharArray())
{
if (Char.IsDigit(c) || Char.IsControl(c) || acceptedChars.Contains(c)) continue;
else return false;
}
return true;
}
Add the TextBox_PreviewTextInput-Event to your TextBox
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !IsTextAllowed(e.Text);
}
public class CMSP430CommPanel
{
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
public void textEditorTextChanged(TextEditor editor)
{
if (editor == m_texti2cWrite)
{
int count = 0;
int location;
string text1 = m_texti2cWrite.getText();
string text = m_texti2cWrite.getText().removeCharacters(" ");
string hexString = string.empty;
int countCaret = m_texti2cWrite.getCaretPosition();
for (int i = 0; i < text.Length; i++)
{
hexString = hexString + (string)(text[i], 1);
if ((i + 1) % 2 == 0)
{
if (i != text.Length - 1)
{
hexString = hexString + T(" ");
count++;
}
}
count++;
}
m_texti2cWrite.setText(hexString,false);
if (text1.Length == m_texti2cWrite.getCaretPosition())
{
m_texti2cWrite.setCaretPosition(count);
}
else
{
m_texti2cWrite.setCaretPosition(countCaret);
}
}
}
}