C# First Special Char - c#

I'm trying to write a calculator just for the fun of it, the first bit is quite easy.
Making it do the calculations, even with more of the same type calculations, ex 10+10+10
My problem comes when I try to figuer out how to do this when it comes in a long string with diffrendt calculations methods..
Ex 10+15-5, and 10-15+5 gives to very diffrendt ressults. But at the moment I cant archive this since my code dosent support diffrendt calculation methods in the same string, so I need a way to look at what calculation methods was posted in the string.
I'm using a .split('-','+') on the string, but that leaves me in a porblem, I have no way to look for what char was the first I split the string on, so I dont know what method to call..
I'm figureing that the final thing would be something like this.
If(stringSplitChar == +)
{
int tempRes;
tempRes = Convert.ToInt32(SplitVal[0]);
for (i = 1; i < SplitVal.Count(); i++)
{
tempRes = addVal(tempRes, Convert.ToInt32(SplitVal[i]));
}
endRes = tempRes.ToString(););
}
endRes = temp;
return endRes;

You should learn parsing, syntax tree, ...
You can take a look at existing project to understand how it works. ncalc for instance.

To be Fair You need get Nos. Separately, If you want to do this without...
using System;
using System.Data;
class Program {
static void Main(string[] args) {
string s ="10+20+30"
var dt = new DataTable();
var result = dt.Compute(s, null);
}
}

Related

Call random method directly instead of using a lot of if-statements, C#

Relative newcomer to c# here.
Let’s say I have 50 different methods a1(), a2(), … a50() and I want to call a random one. One way to do it is of course to generate a random int, nr, between 1 and 50 and then use a lot of if statements like if(nr == 1){
a1()
} and so on. Quite cumbersome - can I do something smarter?
Is it for example possible to do something along the lines of creating a string which is initially only “a” and then adding nr as a string and then calling that string as method? Like this:
Public void RandomMethod()
{
nr = Random.Range(1,51);
string = ‘a’ + nr.tostring();
string();
}
I know this doesn’t work, but something like this instead of my first idea would save me hundreds of lines of code
Any response is appreciated 😊
One option would be to put your functions into a collection, say a List for example. Then you could randomly index into that collection to get a random function to call. You would generate a random index between 0 and the length of the List minus 1. This could apply generally to any number of functions then (50 or otherwise).
To do exactly what you asked (and, I have no clue why you'd want to), consider something like this:
Create a delegate that matches the call signature of all of your methods (they all have to have the same call signature or ... I really can't imagine what you'd want to do if they didn't). You could use an Action or Func declaration, but I'm going to make it clear here:
public delegate void SomeMethod(int i);
Then write your 50 methods. All their call signatures will match the delegate:
public static void Method1(int i) { System.Console.WriteLine($"{nameof(Method1)}: {i}"); }
public static void Method2(int i) { System.Console.WriteLine($"{nameof(Method2)}: {i}"); }
public static void Method3(int i) { System.Console.WriteLine($"{nameof(Method3)}: {i}"); }
public static void Method4(int i) { System.Console.WriteLine($"{nameof(Method4)}: {i}"); }
// ...
public static void Method50(int i) { System.Console.WriteLine($"{nameof(Method50)}: {i}"); }
Then create an array of delegates:
public static SomeMethod[] Methods = new SomeMethod[]
{
Method1,
Method2,
Method3,
Method4,
//...
Method50,
};
And then a method that picks 1 or more from the list at random and runs them:
public void Run5RandomMethods()
{
Random random = new Random();
for(int i = 0; i < 5; i++)
{
var randNumber = random.Next(50);
var method = Methods[randNumber];
method.Invoke(i);
}
}
Note: this is untested, I'm not going to create 50 dummy methods for you. If you find an issue, comment below and I'll fix the code
By the way, what you show in your question (composing the name of the method by concatenating a string and the string representation of a number) is doable using a technology known as Reflection. Let me know if you really want to do that.
So, assuming we have fifty methods that all have a signature like
void SomeMethod()
{
...
}
You could declare an array like below, this is an array of Action delegates
var methods = new Action[]
{
SomeMethod,
SomeOtherMethod,
() => _ = SomeFunctionWithAHardcodedParameter("Wibble"),
...
}
Then you could call a random method by doing,
method[Random.Next(methods.Length)]();
First off, I just want to say something similar to what others have already said: you should readdress whether you need 50 methods named a1(), a2(), ..., a50(), and rethink what the problem you're trying to solve is (which you haven't provided enough information for us to help you with).
If that was hyperbole, try to avoid doing that; it may muddy the responses to solve a perceived problem ("why do you have 50 poorly-named methods?") instead of your actual problem ("can I execute a randomly selected method?" <- still a weird question, but who am I to judge...).
That out of the way, you can use something like Reflection. This can be "dangerous" and expensive when executing, so use with caution... or better yet don't use it, but be aware of it, because it can lead you to think Reflection is the answer to problems you don't actually have.
Anyway, you can:
// have an instance of an object
var obj = new ClassName();
// get all the methods of the object
var methodInfos = typeof(ClassName).GetMethods();
// filter them somehow
var filteredMethodInfos = methodInfos.Where(m => Regex.IsMatch(m.Name, #"\a[\d]{1,2}")).ToArray();
// get a random one and invoke it
var rnd = new Random();
filteredMethodInfos[rnd.Next(filteredMethodInfos.Length)].Invoke(obj, null);
I haven't tested this, but it should in theory work.
But again: don't use reflection if you don't have to. There's probably an issue with your root question (as Tim Schmelter said, this is an "XY-problem") if your answer is "randomly execute 1 of 50 methods".

How to get value of escape characters in c#?

I want to know the ASCII value of an escape sequence in runtime. for example:
string x = "\\b";
char res = someFunctionCall(x);
//res = '\b' = 0x08
The difference here that I only know x at runtime.
I know that this can be made with simple switch (already doing that), but I was wondering if it can be made using some existing c# call. I tried Char.Parse(x), but it didn't work.
Edit: I'm not talking here about converting '\b' to its corresponding ASCII value, rather, I'd like to parse "\\b" as what you write in c# to get '\b'.
There is slow but rather easy way to do this. compile your code at runtime and let c# compiler take care of that! I know its overkill for what you want. but it works.
Anyway as #JonSkeet noted you can use a dictionary for simple escape sequences. take your list from here https://msdn.microsoft.com/en-us/library/h21280bw.aspx
Here is solution by compiling code at runtime, Note that its VERY SLOW, so I suggest you to replace and map multiple characters at once so compiler only runs and evaluate all of that for you only once.
using System;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
//...
private static void Main()
{
string x = "\\b";
string res = Evaluate(x);
Console.WriteLine(res);
}
public static string Evaluate(string input)
{
// code to compile.
const string format = "namespace EscapeSequenceMapper {{public class Program{{public static string Main(){{ return \"{0}\";}}}}}}";
// compile code.
var cr = new CSharpCodeProvider().CompileAssemblyFromSource(
new CompilerParameters { GenerateInMemory = true }, string.Format(format, input));
if (cr.Errors.HasErrors) return null;
// get main method and invoke.
var method = cr.CompiledAssembly.GetType("EscapeSequenceMapper.Program").GetMethod("Main");
return (string)method.Invoke(null, null);
}

How do I get the number of listitems that meet certain criteria?

I need for example the number of list-items, that are NOT "".
ATM, I solve it like this:
public int getRealCount()
{
List<string> all = new List<string>(originList);
int maxall = all.Count;
try
{
for (int i = 0; i < maxall; i++)
{
all.Remove("");
}
}
catch { }
return all.Count;
}
No question, performance is pretty bad. I'm lucky it's just a 10-items-list, but on a phone you should avoid such code.
So my question is, how can I improve this code?
One idea was: there could already be a method for that. The econd method would be: that all could be filled with only the items that are not "".
How should I solve this?
Thanks
Sounds like you want:
return originList.Count(x => x != "");
There's no need to create a copy of the collection at all. Note that you'll need using System.Linq; in your using directives at the start of your source code.
(Note that you should not have empty catch blocks like that - it's a terrible idea to suppress exceptions in that way. Only catch exceptions when you either want to really handle them or when you want to rethrow them wrapped as another type. If you must ignore an exception, you should at least log it somewhere.)
If performance is your concern, then you should keep a collection that is only for these items.
If performance is not a big deal, I would suggest you use a Linq query on your collection. The cool thing about Linq is that the search is delayed until you need it.
int nonEmptyItemCount = originList.Count(str => !string.IsNullOrEmpty(str));
You could also do
int nonEmptyItemCount = originList.Count(str => str != "");
You should use LINQ. Install ReSharper, it'll generate it for you.
Also, don't create an int maxall = all.Count and then use it in your for loop.
For mobile apps you shouldn't use unnecessary memory so just use all.Count in the for loop.
You're calling all.remove("") for every item in the list all. Why not just call it once? You're not using i at all in your code...
Why not:
public int getRealCount()
{
List<string> all = new List<string>(originList);
int erased =all.RemoveAll(delegate(string s)
{
return s == "";
});
return all.Count - erased;
}
Update:
Fixed the issue I had. This is without lambda's.

send a String array as parameter to a function

I have a function in a class called Function, like below:
public int SearchedRecords(String [] recs)
{
int counter = 0;
String pat = "-----";
String[] records = recs;
foreach (String line in records)
{
if (line.Contains(pat) == true)
{
counter++;
}
}
return counter;
}
And I am calling this method from my main class this way:
String [] file = File.ReadAllLines("C:/Users.../results.txt");
int counter = Function.SearchedRecords( []file);
But I get an error saying:
;expected
What is wrong?
Another question: The function above is counting from a file all the lines with the pattern ----- in them (even if with more dashes, or if the line has some chars before or after the dashes). Am I right?
It's something like the patterns in Java so maybe there is an other way.
Can you enlighten me?
Remove the [] from your parameter.
e.g.
int counter = Function.SearchedRecords(file);
And yes, your assumption about the behavior of the Contains method is correct - you'll match any line containing five consecutive dashes, regardless of what characters are before or after them.
If you want to parse for exactly five dashes, with nothing before or after them I suggest looking into the RegEx class (regular expressions).
Change
int counter = Function.SearchedRecords( []file);
to
int counter = Function.SearchedRecords(file);
and yes, this will work, for that string.
However Contains is case sensitive, if you were matching on a name, or another string with alphabetic characters, the case would have to be identical to match e.g. line.Contains("Binary Worrier") will not match a string "Hello binary worrier".
Also, reading the entire file into memory is fine if you know that the file will always be small, this method gets less efficient the larger the file.
Better to always use something like System.IO.StreamReader or System.IO.File.ReadLines (available in .Net 4 and later), these allow you to consume the file one line at a time. e.g.
using (var reader = new System.IO.StreamReader("MyFile.txt"))
{
while(!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line.Contains(pattern))
counter++;
}
}
Change it to
int counter = Function.SearchedRecords(file);
Remove '[]' from a method call. Yes, your function seems to count what you want.
First of all you need to create an instance of function class and then run the function. Hope following code helps
Function fb = new Function();
int counter = fb.SearchedRecords(file);
Right now, you are using SearchRecords as an static function of a static class which doesn't require instantiation.
You can do this in a shorter way using LINQ:
int counter = file.Count(line => line.Contains("-----"));

Please help me understand anonymous delegates?

I've downloaded the VCSharpSample pack from Microsoft and started reading on Anonymous Delegates. I can more or less understand what the code is doing, but I don't understand the reason behind it. Maybe if you gave me some examples where it would result in cleaner code and easier maintainability then I could wrap my head around it. :)
Can you help?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
delegate decimal CalculateBonus(decimal sales);
class Player
{
public string Name;
public decimal Score;
public decimal Bonus;
public CalculateBonus calculation_algorithm;
}
class Program
{
static decimal calculateStandardBonus(decimal sales)
{
return sales / 10;
}
static void Main(string[] args)
{
decimal multiplier = 2;
CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus);
CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
Player[] players = new Player[5];
for (int i = 0; i < 5; i++)
{
players[i] = new Player();
}
players[0].Name = "Sergio";
players[0].Score = 240;
players[0].calculation_algorithm = standard_bonus;
players[1].Name = "Sergio";
players[1].Score = 240;
players[1].calculation_algorithm = enhanced_bonus;
players[2].Name = "Caro";
players[2].Score = 89;
players[2].calculation_algorithm = standard_bonus;
players[3].Name = "Andy";
players[3].Score = 38;
players[3].calculation_algorithm = enhanced_bonus;
players[4].Name = "Hugo";
players[4].Score = 600;
players[4].calculation_algorithm = enhanced_bonus;
foreach (Player player in players)
{
PerformCalculationBonus(player);
}
foreach (Player player in players)
{
DisplayPersonalDetails(player);
}
Console.ReadLine();
}
public static void PerformCalculationBonus(Player player)
{
player.Bonus = player.calculation_algorithm(player.Score);
}
public static void DisplayPersonalDetails(Player player)
{
Console.WriteLine(player.Name);
Console.WriteLine(player.Score);
Console.WriteLine(player.Bonus);
Console.WriteLine("---------------");
}
}
}
Anonymous delegates are designed to help you make code more readable by being able to define the behavior of a simple delegate inline in another method. This means that if you're dealing with something that requires a delegate (an event handler, for example), you can define the behavior right in the code rather than creating a dedicated function for it.
In addition, they're the precursor for lambda expressions. Things like LINQ to Objects (any of the methods that operate on IEnumerable<T>) use delegates to perform queries on objects. For example, if you have a collection of strings and you want a query that finds all of them that are five characters long, you can do that with a lambda:
List<string> strings = ...
var query = strings.Where(s => s.Length == 5);
Or you could do it with an anonymous delegate:
var query = strings.Where(delegate(string s) { return s.Length == 5; });
If you didn't have these, your code would look something like this:
var query = strings.Where(IsFiveCharacters);
...
private bool IsFiveCharacters(string input)
{
return input.Length == 5;
}
It's important to realize, though, that lambdas and anonymous delegates are just compiler features. When your code is compiled, it does actually create regular functions like in the last example, but they're hidden and named using characters that are illegal in the language being used. There's a lot of logic that goes around them when doing things like closures (where you access a variable that exists outside of the lambda/anonymous delegate declaration), as well.
The benefit is that you don't have to look somewhere else for the code to do a one-time lookup/change/calculation/whatever. It's a bit annoying to have to add a function (or a whole other class for a function!) you'll only ever use in one place, and then you have to look back later and see what that bit of code was and why it's needed and whether it still is.
With an anonymous delegate, the code is right there in the code that uses it.

Categories

Resources