csharp string separetion for math operation - c#

I'm doing a calculator with HTML CSS and JQuery with ajax call to a c# code (it's for an exercises given to me to learn a bit ajax and csharp).
I was able to do everything i needed to do, I'm just missing one thing.
The c# code, receive from a file named "Handler.ashx" a string, this string conteins the displalyed operation of the calculator, example: "321/34". now, I should, with c#, find a way to separate the 2 number inside the string and make the operation using the / used as separation. this for every single operation (+, -, /, *)
(I'm not english, so if somethings is not clear please tell me and I'll try to explaine myself better)

I'd use the built-in methods int IndexOf(char)
I am using C# 10 (or .Net 6.0), so depending on your version some features might not be available yet, but the logic should be the same
string test = "147+548";
int plusIndex = test.IndexOf('+');
int minusIndex = test.IndexOf('-');
int mulIndex = test.IndexOf('*');
int divIndex = test.IndexOf('/');
string operation;
float a = 0;
float b = 0;
if (plusIndex != -1)
{
operation = "PLUS";
a = float.Parse(test[..plusIndex]);
b = float.Parse(test[(plusIndex+1)..]);
}
else if (minusIndex != -1)
{
operation = "MINUS";
a = float.Parse(test[..minusIndex]);
b = float.Parse(test[(minusIndex + 1)..]);
}
else if (mulIndex != -1)
{
operation = "MULTIPLY";
a = float.Parse(test[..mulIndex]);
b = float.Parse(test[(mulIndex + 1)..]);
}
else/* if (divIndex == -1)*/
{
operation = "DIVIDE";
a = float.Parse(test[..divIndex]);
b = float.Parse(test[(divIndex + 1)..]);
}
Console.WriteLine($"{a} {operation} {b}");
The string[...] I put down are the same as SubString. [..5] means from start to index 5 and [6..] means from index 6 to the end

Related

Is there a way to convert a whole condition in string to boolean

I need a way to check conditions set up in runtime.
I have classes that provide conditions created by themselves.
But I don't know how to do that.
At least I want something like that:
int x = 1;
int y = 2;
int z = 3;
string s = "(x == 1 && y == 3) || z == 3";
bool b = bool.Parse(s);
I already tried stating the conditions in a string and then convert them to a bool.
Mainly I tried using this
string s = "true || false";
and then
bool b = false;
bool.TryParse(s, out b);
or
bool b = Convert.ToBoolean(s);
The "true" or "false" statements in the string are put in later.
The individual conditions are checked and being replaced with true or false.
Didn't work until now.
Edit:
I am working on a Game and there are multiple objects that act according to their individual conditions. But these conditions are set up on runtime and their length and complexity is unknown before runtime. Using strings was my first attempt because i don't know how to do this.
Also I know only a bit more than the basics so I don't know many methods and libraries.
You can try exploiting an old trick with DataTable:
using System.Data;
...
private static bool Compute(string formula, int x, int y, int z) {
using (var table = new DataTable()) {
// variables of type int
table.Columns.Add("x").DataType = typeof(int);
table.Columns.Add("y").DataType = typeof(int);
table.Columns.Add("z").DataType = typeof(int);
table.Columns.Add("result").Expression = formula;
table.Rows.Add(x, y, z);
return Convert.ToBoolean(table.Rows[0]["result"]);
}
}
...
// Please, not the syntax difference
Console.Write(Compute("(x = 1 and y = 3) or z = 3", 1, 2, 3));
You can use a C# script system like CS-Script; this allow you to execute C# as script (essentially strings). There is also the open source C# compiler Roslyn, but this may be too advanced for your needs.

Use null-conditional operator to set value to 0 if null

I'm new to C# but not to programming in general.
I am trying to set add some error checking to my program. There are 3 textboxes and I am trying to make it so that if the text box is left blank, it assumes a value of 0. Here is my code so far:
private void btnCalculate_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtNumberOfClassATix.Text)) // Assumes 0 if no number entered for txtNumberOfClassATix.Text.
{
txtNumberOfClassATix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassBTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassBTix.Text.
{
txtNumberOfClassBTix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassCTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassCTix.Text.
{
txtNumberOfClassCTix.Text = "0";
}
int classANum = int.Parse(txtNumberOfClassATix.Text);
int classBNum = int.Parse(txtNumberOfClassBTix.Text);
int classCNum = int.Parse(txtNumberOfClassCTix.Text);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
This code works but I'm sure I could replace those if statements with something simpler. I've seen how to set a variable to null if another is null using the null-conditional operator but I don't really grasp it enough to adapt it to my scenario.
So far maccettura's answer is the best, but can we do better? Sure we can. Let's make a general-purpose extension method:
internal static class Extensions
{
public static int? AsInt(this string s)
{
int result;
if (s == null)
return null;
else if (int.TryParse(s, out result))
return result;
else
return null;
}
}
And now:
int classANum = txtNumberOfClassATix.Text.AsInt() ?? 0;
If it's an int, you get the int. If it's not, you get zero. Easy peasy.
Or, you might want this extension method:
internal static class Extensions
{
public static int AsInt(this string s, int default = 0)
{
int result;
if (s == null)
return default;
else if (int.TryParse(s, out result))
return result;
else
return default;
}
}
And now you can say what you want the default to be without using ??.
This style of programming is called "fluent programming"; it can make code that is very easy to read and understand.
Notice that this solution does not update the UI with zeros; if you wanted to do that then I would recommend splitting that into two steps: one which causes the mutation, and then a separate step which computes the value. Operations which are useful for both their effects and their values can be confusing.
This is a perfect time to use a method so you arent repeating yourself:
private static int GetInputAsInt(TextBox textbox)
{
int outputValue = 0;
if(textbox?.Text != null && int.TryParse(textbox.Text, out outputValue))
{
return outputValue;
}
return 0;
}
Now you are checking if the textbox itself is not null, and that the value contained therein is a int, if anything fails it returns a 0;
Call it in your other method like this:
int classANum = GetInputAsInt(txtNumberOfClassATix);
Which means your button click event would be a bit simpler:
private void btnCalculate_Click(object sender, EventArgs e)
{
int classANum = GetInputAsInt(txtNumberOfClassATix);
int classBNum = GetInputAsInt(txtNumberOfClassBTix);
int classCNum = GetInputAsInt(txtNumberOfClassCTix);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
To keep it simple, a good approach is to use the conditional operator. The full example is below (broken across two lines for readability):
txtNumberOfClassATix.Text =
String.IsNullOrEmpty(txtNumberOfClassATix.Text) ? "0" : txtNumberOfClassATix.Text;
This is a nice, readable, assignment for the first part:
myString = ...
The conditional operator breaks down by providing a boolean expression (true/ false) on the left side of the ?. So, for example:
myString = anotherString == "" ? ... // checking if another string is empty
The final part is the :. To the left is the assignment if the expression is true, and to the right goes the assignment if the expression is false. To finish the example:
myString = anotherString == "" ? "anotherString is empty" : "anotherString is not empty";
The above example can be written out in full to clear up any misunderstanding as:
if (anotherString == "")
{
myString = "anotherString is empty";
}
else
{
myString = "anotherString is not empty";
}
This can apply to all the statements. The documentation is found here.
The best way to reduce the line of code is use the function for your common operation(s). In your case, you can create function which checks whether or not the object is NULL or empty. Based on the return value of that function you can proceed ahead. On the other hand, you can handle it on front-end by using different validators such as RequiredFieldValidator, CustomValidator, etc.

Can I put multiple statements in a interpolated string in C# 6?

In Ruby, I can put multiple statements in a interpolated string, eg.
puts "#{a = 1; b = 2; a + b;}"
Or I can put them in multiple lines like this:
puts "#{a = 1;
b = 2;
a + b;}"
Can I do the same thing in C# 6? I've tried but failed. Below is my C# code.
Console.WriteLine($#"haha
{int a = 1;
int b = 2;
a+b;}
heihei");
When I try to run the C# program, I got:
CS1525 Invalid expression term 'int'
CS1073 Unexpected token 'a'
I hope someone can help.
You can't have full code blocks in your string interpolation statements. You can only do evaluations inside.
So this works (pulled the variables outside):
int a = 1;
int b = 2;
Console.WriteLine($#"haha
{a+b}
heihei");
And this too (do evaluation only):
Console.WriteLine($#"haha
{1+2}
heihei");
Ruby is different then C# in your case you write full code in your string interpolation so it's not working.
Console.WriteLine($"Name = {name}, hours = {hours:hh}")
or
Console.WriteLine($#"haha {1+2} heihei");
For Ref: Microsoft C#

Bitwise operations on strings - 1440 characters length

How can i make bitwise operations on strings at c#
example
string sr1="0101110";
string sr2="1101110";
sr1 & sr2="0101110";
or
sr1 | sr2="1101110";
How can i make such comparison ?
Notice string lengths are fixed 1440 characters
Here my dirty solution
private string compareBitWiseAnd(string sr1, string sr2)
{
char[] crArray1 = sr1.ToCharArray();
char[] crArray2 = sr2.ToCharArray();
StringBuilder srResult = new StringBuilder();
for (int i = 0; i < crArray1.Length; i++)
{
if (crArray1[i] == crArray2[i])
{
srResult.Append(crArray1[i]);
}
else
{
srResult.Append('0');
}
}
return srResult.ToString();
}
private string compareBitWiseOr(string sr1, string sr2)
{
char[] crArray1 = sr1.ToCharArray();
char[] crArray2 = sr2.ToCharArray();
StringBuilder srResult = new StringBuilder();
for (int i = 0; i < crArray1.Length; i++)
{
if (crArray1[i] == '1' || crArray2[i] == '1')
{
srResult.Append("1");
}
else
{
srResult.Append('0');
}
}
return srResult.ToString();
}
Convert to actual bits first, and then do the bitwise comparison.
int num1 = Convert.ToInt32(sr1, 2);
int num2 = Convert.ToInt32(sr2, 2);
int result = num1 & num2;
Use this if you want to get a binary string from the result.
BigInteger is the type you are looking for. It also have BitwiseOr.
If you really need to stick with strings it is not very hard to compute bitwise operations on character-by-character basis... but I'd avoid doing it if possible.
And here is a question on how to construct BigInteger from string of any base - BigInteger Parse Octal String?
var bitString = "10101";
BigInteger value = bitString.Aggregate(new BigInteger(), (b, c) => b * 2 + c - '0');
You have to convert the string to numbers first, you can use "Convert.ToInt32(String, Int32)", the second parameter lets you specify the base:
string sr1 = "0101110";
string sr2 = "1101110";
int one = Convert.ToInt32(sr1, 2);
int two = Convert.ToInt32(sr2, 2);
int result = one & two;
hope it helps.
You can't do bitwise operations on a string in the way you intend. There are interesting things you can do with bitwise operations on strings with other goals, like changing their case, but I think this is what you want:
// Convert the string to an integer
int foo = Convert.ToInt32(sr1, 2);
int bar = Convert.ToInt32(sr2, 2);
// Perform binary styff
int result = foo & bar;
// Convert back to a string, if you want
string resultStr = result.ToString();
I like Alexei's BigInteger solution, but it does require .NET 4.0 minimum. If for some reason you can't use that, then another option is to use the BitArray class, which has been available since .NET 1.1. Unfortunately, there is no method built-in to BitArray to parse a binary string, so you have to do that manually, similar to Alexei's solution.
Another option is a class I wrote called BoolArray which does a lot of the same things as BitArray, but does have a method to parse binary strings - use the static BoolArray.FromBinaryString method:
BoolArray bin = BoolArray.FromBinaryString("1001011000111010101"); // etc
Here is the BoolArray source code. Note, however, that it isn't quite complete, and isn't fully tested either, but I'm not immediately aware of any bugs.
EDIT: I noticed after pasting the original link that the code used a function provided in a different class of my "Utils" library, and wouldn't have compiled directly. I've updated the link to provide this class in the code as well... hopefully that was the only case, but if not let me know and I can fix.

Best solution for an StringToInt function in C#

I were asked to do an StringToInt / Int.parse function on the white board in an job interview last week and did not perform very good but I came up with some sort of solution. Later when back home I made one in Visual Studion and I wonder if there are any better solution than mine below.
Have not bothred with any more error handling except checking that the string only contains digits.
private int StrToInt(string tmpString)
{
int tmpResult = 0;
System.Text.Encoding ascii = System.Text.Encoding.ASCII;
byte[] tmpByte = ascii.GetBytes(tmpString);
for (int i = 0; i <= tmpString.Length-1; i++)
{
// Check whatever the Character is an valid digit
if (tmpByte[i] > 47 && tmpByte[i] <= 58)
// Here I'm using the lenght-1 of the string to set the power and multiply this to the value
tmpResult += (tmpByte[i] - 48) * ((int)Math.Pow(10, (tmpString.Length-i)-1));
else
throw new Exception("Non valid character in string");
}
return tmpResult;
}
I'll take a contrarian approach.
public int? ToInt(this string mightBeInt)
{
int convertedInt;
if (int.TryParse(mightBeInt, out convertedInt))
{
return convertedInt;
}
return null;
}
After being told that this wasn't the point of the question, I'd argue that the question tests C coding skills, not C#. I'd further argue that treating strings as arrays of characters is a very bad habit in .NET, because strings are unicode, and in any application that might be globalized, making any assumption at all about character representations will get you in trouble, sooner or later. Further, the framework already provides a conversion method, and it will be more efficient and reliable than anything a developer would toss off in such a hurry. It's always a bad idea to re-invent framework functionality.
Then I would point out that by writing an extension method, I've created a very useful extension to the string class, something that I would actually use in production code.
If that argument loses me the job, I probably wouldn't want to work there anyway.
EDIT: As a couple of people have pointed out, I missed the "out" keyword in TryParse. Fixed.
Converting to a byte array is unnecessary, because a string is already an array of chars. Also, magic numbers such as 48 should be avoided in favor of readable constants such as '0'. Here's how I'd do it:
int result = 0;
for (int i = str.Length - 1, factor = 1; i >= 0; i--, factor *= 10)
result += (str[i] - '0') * factor;
For each character (starting from the end), add its numeric value times the correct power of 10 to the result. The power of 10 is calculated by multiplying it with 10 repeatedly, instead of unnecessarily using Math.Pow.
I think your solution is reasonably ok, but instead of doing math.pow, I would do:
tmpResult = 10 * tmpResult + (tmpByte[i] - 48);
Also, check the length against the length of tmpByte rather than tmpString. Not that it normally should matter, but it is rather odd to loop over one array while checking the length of another.
And, you could replace the for loop with a foreach statement.
If you want a simple non-framework using implementation, how 'bout this:
"1234".Aggregate(0, (s,c)=> c-'0'+10*s)
...and a note that you'd better be sure that the string consists solely of decimal digits before using this method.
Alternately, use an int? as the aggregate value to deal with error handling:
"12x34".Aggregate((int?)0, (s,c)=> c>='0'&&c<='9' ? c-'0'+10*s : null)
...this time with the note that empty strings evaluate to 0, which may not be most appropriate behavior - and no range checking or negative numbers are supported; both of which aren't hard to add but require unpretty looking wordy code :-).
Obviously, in practice you'd just use the built-in parsing methods. I actually use the following extension method and a bunch of nearly identical siblings in real projects:
public static int? ParseAsInt32(this string s, NumberStyles style, IFormatProvider provider) {
int val;
if (int.TryParse(s, style, provider, out val)) return val;
else return null;
}
Though this could be expressed slightly shorter using the ternary ? : operator doing so would mean relying on side-effects within an expression, which isn't a boon to readability in my experience.
Just because i like Linq:
string t = "1234";
var result = t.Select((c, i) => (c - '0') * Math.Pow(10, t.Length - i - 1)).Sum();
I agree with Cyclon Cat, they probably want someone who will utilize existing functionality.
But I would write the method a little bit different.
public int? ToInt(this string mightBeInt)
{
int number = 0;
if (Int32.TryParse(mightBeInt, out number))
return number;
return null;
}
Int32.TryParse does not allow properties to be given as out parameter.
I was asked this question over 9000 times on interviews :) This version is capable of handling negative numbers and handles other conditions very well:
public static int ToInt(string s)
{
bool isNegative = false, gotAnyDigit = false;
int result = 0;
foreach (var ch in s ?? "")
{
if(ch == '-' && !(gotAnyDigit || isNegative))
{
isNegative = true;
}
else if(char.IsDigit(ch))
{
result = result*10 + (ch - '0');
gotAnyDigit = true;
}
else
{
throw new ArgumentException("Not a number");
}
}
if (!gotAnyDigit)
throw new ArgumentException("Not a number");
return isNegative ? -result : result;
}
and a couple of lazy tests:
[TestFixture]
public class Tests
{
[Test]
public void CommonCases()
{
foreach (var sample in new[]
{
new {e = 123, s = "123"},
new {e = 110, s = "000110"},
new {e = -011000, s = "-011000"},
new {e = 0, s = "0"},
new {e = 1, s = "1"},
new {e = -2, s = "-2"},
new {e = -12223, s = "-12223"},
new {e = int.MaxValue, s = int.MaxValue.ToString()},
new {e = int.MinValue, s = int.MinValue.ToString()}
})
{
Assert.AreEqual(sample.e, Impl.ToInt(sample.s));
}
}
[Test]
public void BadCases()
{
var samples = new[] { "1231a", null, "", "a", "-a", "-", "12-23", "--1" };
var errCount = 0;
foreach (var sample in samples)
{
try
{
Impl.ToInt(sample);
}
catch(ArgumentException)
{
errCount++;
}
}
Assert.AreEqual(samples.Length, errCount);
}
}

Categories