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);
}
Related
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);
}
}
Currently I'm working on an web-API dependent application. I have made a class with a lot of API strings like: /api/lol/static-data/{region}/v1/champion/{id}. Also I made a method:
public static String request(String type, Object[] param)
{
return "";
}
This is going to do the requesting stuff. Because it's very different with each request type how many parameters are being used, I'm using an array for this. Now the question is, is it posssible to String.Format using an array for the paramaters while the keys in the strings are not numbers? Or does anyone know how to do this in a different way?
No, string.Format only supports index-based parameter specifications.
This:
"/api/lol/static-data/{region}/v1/champion/{id}"
^^^^^^^^ ^^^^
will have to be handled using a different method, like string.Replace or a Regex.
You will need to:
Decide on the appropriate method for doing the replacements
Decide how an array with index-based values should map to the parameters, are they positional? ie. {region} is the first element of the array, {id} is the second, etc.?
Here is a simple LINQPad program that demonstrates how I would do it (though I would add a bit more error handling, maybe caching of the reflection info if this is executed a lot, some unit-tests, etc.):
void Main()
{
string input = "/api/lol/static-data/{region}/v1/champion/{id}";
string output = ReplaceArguments(input, new
{
region = "Europe",
id = 42
});
output.Dump();
}
public static string ReplaceArguments(string input, object arguments)
{
if (arguments == null || input == null)
return input;
var argumentsType = arguments.GetType();
var re = new Regex(#"\{(?<name>[^}]+)\}");
return re.Replace(input, match =>
{
var pi = argumentsType.GetProperty(match.Groups["name"].Value);
if (pi == null)
return match.Value;
return (pi.GetValue(arguments) ?? string.Empty).ToString();
});
}
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("-----"));
How to find whether a string array contains some part of string?
I have array like this
String[] stringArray = new [] { "abc#gmail.com", "cde#yahoo.com", "#gmail.com" };
string str = "coure06#gmail.com"
if (stringArray.Any(x => x.Contains(str)))
{
//this if condition is never true
}
i want to run this if block when str contains a string thats completely or part of any of array's Item.
Assuming you've got LINQ available:
bool partialMatch = stringArray.Any(x => str.Contains(x));
Even without LINQ it's easy:
bool partialMatch = Array.Exists(stringArray, x => str.Contains(x));
or using C# 2:
bool partialMatch = Array.Exists(stringArray,
delegate(string x) { return str.Contains(x)); });
If you're using C# 1 then you probably have to do it the hard way :)
If you're looking for if a particular string in your array contains just "#gmail.com" instead of "abc#gmail.com" you have a couple of options.
On the input side, there are a variety of questions here on SO which will point you in the direction you need to go to validate that your input is a valid email address.
If you can only check on the back end, I'd do something like:
emailStr = "#gmail.com";
if(str.Contains(emailStr) && str.length == emailStr.length)
{
//your processing here
}
You can also use Regex matching, but I'm not nearly familiar enough with that to tell you what pattern you'd need.
If you're looking for just anything containing "#gmail.com", Jon's answer is your best bets.
What is the most efficient way to parse a C# string in the form of
"(params (abc 1.3)(sdc 2.0)(www 3.05)....)"
into a struct in the form
struct Params
{
double abc,sdc,www....;
}
Thanks
EDIT
The structure always have the same parameters (same names,only doubles, known at compile time).. but the order is not granted.. only one struct at a time..
using System;
namespace ConsoleApplication1
{
class Program
{
struct Params
{
public double abc, sdc;
};
static void Main(string[] args)
{
string s = "(params (abc 1.3)(sdc 2.0))";
Params p = new Params();
object pbox = (object)p; // structs must be boxed for SetValue() to work
string[] arr = s.Substring(8).Replace(")", "").Split(new char[] { ' ', '(', }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arr.Length; i+=2)
typeof(Params).GetField(arr[i]).SetValue(pbox, double.Parse(arr[i + 1]));
p = (Params)pbox;
Console.WriteLine("p.abc={0} p.sdc={1}", p.abc, p.sdc);
}
}
}
Note: if you used a class instead of a struct the boxing/unboxing would not be necessary.
Depending on your complete grammar you have a few options:
if it's a very simple grammar and you don't have to test for errors in it you could simply go with the below (which will be fast)
var input = "(params (abc 1.3)(sdc 2.0)(www 3.05)....)";
var tokens = input.Split('(');
var typeName = tokens[0];
//you'll need more than the type name (assembly/namespace) so I'll leave that to you
Type t = getStructFromType(typeName);
var obj = TypeDescriptor.CreateInstance(null, t, null, null);
for(var i = 1;i<tokens.Length;i++)
{
var innerTokens = tokens[i].Trim(' ', ')').Split(' ');
var fieldName = innerTokens[0];
var value = Convert.ToDouble(innerTokens[1]);
var field = t.GetField(fieldName);
field.SetValue(obj, value);
}
that simple approach however requires a well conforming string or it will misbehave.
If the grammar is a bit more complicated e.g. nested ( ) then that simple approach won't work.
you could try to use a regEx but that still requires a rather simple grammar so if you end up having a complex grammar your best choice is a real parser. Irony is easy to use since you can write it all in simple c# (some knowledge of BNF is a plus though).
Do you need to support multiple structs ? In other words, does this need to be dynamic; or do you know the struct definition at compile time ?
Parsing the string with a regex would be the obvious choice.
Here is a regex, that will parse your string format:
private static readonly Regex regParser = new Regex(#"^\(params\s(\((?<name>[a-zA-Z]+)\s(?<value>[\d\.]+)\))+\)$", RegexOptions.Compiled);
Running that regex on a string will give you two groups named "name" and "value". The Captures property of each group will contain the names and values.
If the struct type is unknown at compile time, then you will need to use reflection to fill in the fields.
If you mean to generate the struct definition at runtime, you will need to use Reflection to emit the type; or you will need to generate the source code.
Which part are you having trouble with ?
A regex can do the job for you:
public Dictionary<string, double> ParseString(string input){
var dict = new Dictionary<string, double>();
try
{
var re = new Regex(#"(?:\(params\s)?(?:\((?<n>[^\s]+)\s(?<v>[^\)]+)\))");
foreach (Match m in re.Matches(input))
dict.Add(m.Groups["n"].Value, double.Parse(m.Groups["v"].Value));
}
catch
{
throw new Exception("Invalid format!");
}
return dict;
}
use it like:
string str = "(params (abc 1.3)(sdc 2.0)(www 3.05))";
var parsed = ParseString(str);
// parsed["abc"] would now return 1.3
That might fit better than creating a lot of different structs for every possible input string, and using reflection for filling them. I dont think that is worth the effort.
Furthermore I assumed the input string is always in exactly the format you posted.
You might consider performing just enough string manipulation to make the input look like standard command line arguments then use an off-the-shelf command line argument parser like NDesk.Options to populate the Params object. You give up some efficiency but you make it up in maintainability.
public Params Parse(string input)
{
var #params = new Params();
var argv = ConvertToArgv(input);
new NDesk.Options.OptionSet
{
{"abc=", v => Double.TryParse(v, out #params.abc)},
{"sdc=", v => Double.TryParse(v, out #params.sdc)},
{"www=", v => Double.TryParse(v, out #params.www)}
}
.Parse(argv);
return #params;
}
private string[] ConvertToArgv(string input)
{
return input
.Replace('(', '-')
.Split(new[] {')', ' '});
}
Do you want to build a data representation of your defined syntax?
If you are looking for easily maintainability, without having to write long RegEx statements you could build your own Lexer parser. here is a prior discussion on SO with good links in the answers as well to help you
Poor man's "lexer" for C#
I would just do a basic recursive-descent parser. It may be more general than you want, but nothing else will be much faster.
Here's an out-of-the-box approach:
convert () to {} and [SPACE] to ":", then use System.Web.Script.Serialization.JavaScriptSerializer.Deserialize
string s = "(params (abc 1.3)(sdc 2.0))"
.Replace(" ", ":")
.Replace("(", "{")
.Replace(")","}");
return new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(s);