I would like to pass some operators through as querystring parameters so that I can convert them, along with a value into an SQL query. The idea would be to let the querystring parameters dictate wether the page returns search results where prices are equal to, greater than or equal to, greater than, less than or less than or equal to as follows:
=, >=, >, < and <=
I'm not sure what the best practise is for passing these operators through is, could anybody help me out? Would you pass through ascii codes or simply text like e, gte, gt, lt, lte and then convert them on results page that builds the query?
Thanks guys!
As user Kon said, use HttpServerUtility.UrlEncode. I've once written a tiny little class to simplify working with query strings so that I do not have to call Server.UrlEncode.
As a side note, keep an eye on SQL injection aka Little Bobby Tables:
(Source)
Server.UrlEncode
You can use eq, ne, gt, lt, ge, le, sa, eb, ap like in the examples below
ge means >=
GET [base]/subjects?grade=ge90
le means <=
GET [base]/encounter?length=le20
More information you can find on those websites:
https://www.hl7.org/fhir/stu3/search.html#number
https://www.hl7.org/fhir/stu3/search.html#prefix
URL encoding is definitely what you're looking for. Take a look at the Web.Utils namespace. http://msdn.microsoft.com/en-us/library/system.web.util.httpencoder.aspx
Related
I want to evaluate a math expression which the user enters in a textbox. I have done this so far
string equation, finalString;
equation = textBox1.Text;
StringBuilder stringEvaluate = new StringBuilder(equation);
stringEvaluate.Replace("sin", "math.sin");
stringEvaluate.Replace("cos", "math.cos");
stringEvaluate.Replace("tan", "math.tan");
stringEvaluate.Replace("log", "math.log10");
stringEvaluate.Replace("e^", "math.exp");
finalString = stringEvaluate.ToString();
StringBuilder replaceI = new StringBuilder(finalString);
replaceI.Replace("x", "i");
double a;
for (int i = 0; i<5 ; i++)
{
a = double.Parse(finalStringI);
if(a<0)
break;
}
when I run this program it gives an error "Input string was not in a correct format." and highlights a=double.Parse(finalStringI);
I used a pre defined expression a=i*math.log10(i)-1.2 and it works, but when I enter the same thing in the textbox it doesn't.
I did some search and it came up with something to do with compiling the code at runtime.
any ideas how to do this?
i'm an absolute beginner.
thanks :)
The issue is within your stringEvaluate StringBuilder. When you're replacing "sin" with "math.sin", the content within stringEvaluate is still a string. You've got the right idea, but the error you're getting is because of that fact.
Math.sin is a method inside the Math class, thus it cannot be operated on as you are in your a = double.Parse(finalStringI); call.
It would be a pretty big undertaking to accomplish your goal, but I would go about it this way:
Create a class (perhaps call it Expression).
Members of the Expression class could include Lists of operators and operands, and perhaps a double called solution.
Pass this class the string at instantiation, and tear it apart using the StringBuilder class. For example, if you encounter a "sin", add Math.sin to the operator collection (of which I'd use type object).
Each operator and operand within said string should be placed within the two collections.
Create a method that evaluates the elements within the operator and operand collection accordingly. This could get sticky for complex calculations with more than 2 operators, as you would have to implement a PEMDAS-esque algorithm to re-order the collections to obey the order of operations (and thus achieve correct solutions).
Hope this helps :)
The .Parse methods (Int.Parse, double.Parse, etc) will only take a string such as "25" or "3.141" and convert it to the matching value type (int 25, or double 3.141). They will not evaluate math expressions!
You'll pretty much have to write your own text-parser and parse-tree evaluator, or explore run-time code-generation, or MSIL code-emission.
Neither topic can really be covered in the Q&A format of StackOverflow answers.
Take a look at this blog post:
http://www.c-sharpcorner.com/UploadFile/mgold/CodeDomCalculator08082005003253AM/CodeDomCalculator.aspx
It sounds like it does pretty much what you're trying to do. Evaluating math expressions is not as simple as just parsing a double (which is really only going to work for strings like "1.234", not "1 + 2.34"), but apparently it is possible.
You can use the eval function that the framework includes for JScript.NET code.
More details: http://odetocode.com/code/80.aspx
Or, if you're not scared to use classes marked "deprecated", it's really easy:
static string EvalExpression(string s)
{
return Microsoft.JScript.Eval.JScriptEvaluate(s, null, Microsoft.JScript.Vsa.VsaEngine.CreateEngine()).ToString();
}
For example, input "Math.cos(Math.PI / 3)" and the result is "0.5" (which is the correct cosine of 60 degrees)
I'm trying to read-in a bunch of unsigned integers from a configuration file into a class. These numbers may be specified in either base-10 (eg: 1234) or in base-16 (eg: 0xAB31). Therefore looking for the strtoul equivalent in C# 2.0.
More specifically, I'm interested in a C# function which mimics the behaviour of the this function when the argument indicating the base or radix is passed in as zero. (Under C++, strtoul will attempt to 'guess' the base or radix based on the first couple of characters in the string and then proceed to convert the number suitably)
Currently I'm manually checking the first two characters (using string.Substring() method) of the string and then calling Convert.ToUInt32(hex, 10) or Convert.ToUInt32(hex, 16) as needed.
I'm sure that there has to be a better way to deal with this problem and hence this post. More elegant ideas/solutions or work-arounds would be great help.
Well, you don't need to use Substring unless it's in hex, but it sounds like you're basically doing it the right way:
return text.StartsWith("0x") ? Convert.ToUInt32(text.Substring(2), 16)
: Convert.ToUInt32(text, 10);
Obviously this will create an extra object for the Substring call, and you could write your own hex parsing code to cope with this - but unless you've actually run into performance problems with this approach, I'd keep it simple.
In a nutshell, I programmed myself into a corner by creating a CLR aggregate that performs row id concatenation, so I say:
select SumKeys(id), name from SomeTable where name='multiple rows named this'
and I get something like:
SumKeys name
-------- ---------
1,4,495 multiple rows named this
But it dies when SumKeys gets > 8000 chars and I don't think I can do anything about it.
As a quick fix (it's only failing 1% of the time for my application) I thought I might compress the string down and I thought some of you bright people out there might know a slick way to do this.
Something like base64 made for 0-9 and a comma?
You'd be much better of if you figure out more reasonable storage for your data (maybe HashSet)...
But for compression try regular System.IO.Compression.GZipStream ( http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx ) and convert resulting byte array to base64 string if needed... or store as byte array.
How about a hexadecimal representation, where every digit represents a 4-bit half of a character byte (a nibble), with 0xa used as the comma? You will only get a 50% compression, but it is fast and simple.
Not sure how "fancy" you'd consider it, but zip/gzip compression is highly effective for any text (sometimes to the tune of 90% reduction or better). Since you're already working with C# and CLR integration, it hopefully wouldn't be too hard to setup/deploy. I haven't tinkered with any C# libraries for compression yet, but it's easy to find them. For example: http://sharpdevelop.net/OpenSource/SharpZipLib/ or http://dotnetzip.codeplex.com/ or even http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx
Or an easier option might be to switch your field to text or varchar/nvarchar(max), if that's feasible.
You can use a Huffman tree. This is basically an algorithm to compress ascii into binary. I was told that it is basically what WinZIP uses, but I'm not sure if that is really true or not. I did a quick search for huffman coding c# and there seems to be at least one decent implementation out there, though I haven't used any of them.
If your "vocabulary" is just digits and commas, a Hoffman tree will get you very good compression.
http://www.enusbaum.com/blog/2009/05/22/example-huffman-compression-routine-in-c/
try:
SELECT name, GROUP_CONCAT(id) FROM SomeTable GROUP BY name WHERE name = 'multiple rows named this'
I came across a method that will work with SQL Server:
SELECT
STUFF((
SELECT ','+id FROM SomeTable a WHERE a.name = b.name FOR XML PATH('')
),1,1,'') AS SumKeys, name
FROM SomeTable b
GROUP BY name
WHERE name = 'multiple rows named this'
The WHERE clause is optional
Using a string.CompareTo(string) i can get around this slightly but is not easy to read and i have read on that locallity settings might influence the result.
Is there a way to just simply use < or > on 2 Strings in a more straightforward way?
You can overload operators but you seldom should. To me "stringA" > "stringB" wouldn't mean a damn thing, it's not helping readability IMO. That's why operator overloading guidelines advise not to overload operators if the meaning is not obvious.
EDIT: Operator Overloading Usage Guidelines
Also, in case of String I'm afraid you can't do it seeing as you can put operator-overloading methods only in the class in which the methods are defined.
If the syntax of CompareTo bothers you, maybe wrapping it in extension method will solve your problem?
Like that:
public static bool IsLessThan(this string str, string str2) {
return str.Compare(str2) < 0;
}
I still find it confusing for reader though.
The bottom line is, you can't overload operators for String. Usually you can do something like declaring a partial and stuffing your overloads there, but String is a sealed class, so not this time. I think that the extension method with reasonable name is your best bet. You can put CompareTo or some custom logic inside it.
CompareTo is the proper way in my opinion, you can use the overloads to specify culture specific parameters...
You mention in a comment that you're comparing two strings with values of the form "A100" and "B001". This works in your legacy VB 6 code with the < and > operators because of the way that VB 6 implements string comparison.
The algorithm is quite simple. It walks through the string, one character at a time, and compares the ASCII values of each character. As soon as a character from one string is found to have a lower ASCII code than the corresponding character in the other string, the comparison stops and the first string is declared to be "less than" the second. (VB 6 can be forced to perform a case-insensitive comparison based on the system's current locale by placing the Option Compare Text statement at the top of
the relevant code module, but this is not the default setting.)
Simple, of course, but not entirely logical. Comparing ASCII values skips over all sorts of interesting things you might find in strings nowadays; namely non-ASCII characters. Since you appear to be dealing with strings whose contents have pre-defined limits, this may not be a problem in your particular case. But more generally, writing code like strA < strB is going to look like complete nonsense to anyone else who has to maintain your code (it seems like you're already having this experience), and I encourage you to do the "right thing" even when you're dealing with a fixed set of possible inputs.
There is nothing "straightforward" about using < or > on string values. If you need to implement this functionality, you're going to have to do it yourself. Following the algorithm that I described VB 6 as using above, you could write your own comparison function and call that in your code, instead. Walk through each character in the string, determine if it is a character or a number, and convert it to the appropriate data type. From there, you can compare the two parsed values, and either move on to the next index in the string or return an "equality" value.
There is another problem with that, I think:
Assert.IsFalse(10 < 2);
Assert.IsTrue("10" < "2");
(The second Assert assumes you did an overload for the < operator on the string class.)
But the operator suggests otherwise!!
I agree with Dyppl: you shouldn't do it!
I am working on the front end of an application. I have to introduce one more filter criteria LoanNumber. Now loan number is E-100. Business layer and domain object is not in my control. So i cannot change it. Domain object which holds loannumber is integer, I have to do
ingeoFilterData.intLoanNumber="E-100"
ingeoFilterData is the domain object. intLoanNumber is declared as Nullable Int32 Now this domainobject is very critical and it goes to some external engine,so i cannot change it.
Please suggest some workaround.
Edit-
I am copying down loannumber from database table.
RT1
RT2
PT1
pt10
PT11
PT12
PT13
PT14
PT15
pt16
pt17
pt8
pt9
MDR1
MDR2
MDR3
If you have only one character, you can do this:
multiply your int by 100. (for example E-51 -> 5100)
Then keep the char as int in the rest of the number (for example 5106).
Do the reverse when you need to show the UI id (E-51).
If you have no limitations (as you mentioned) then you can have your int as a protocol (according to me that is even harder because you are limited by Int32 - 4,294,967,296).
You can set your number to something like
<meaning><number><meaning><number>
and meaning is - 1 - number, 2 - letter, 3 - hyphon.
then 11 will mean 1; 201 will mean A, 3 will mean hyphon, and 113201 will mean 1-A;
It's complicated and not very likely to be usable...
This solution limits your id to length of 5 numbers or 3 letters and 1 number. You can squeez some more by using your int bit-wize and optimize your "protocol" as much as possible.
I hope this helps,
Danail
Is "E-100" a string. ie. E is not a variable?
No, you can't set an int to a string value.
No, an int type cannot store a string. But you can parse your value to an int, before passing this to your domain object for filtering.
If the "prefix" of the loan number is always "E-" you could just exclude it.
Otherwise maybe you could add a property "LoanNumberPrefix" and store the "E-" in it.
Unfortunately at some point, bad design will give you unsolvable problems.
I don't know if this is one of them, but if the domain model has specified that loan numbers are integers, then either you, or the people that made that model clearly hasn't done their job.
Why the E in there? What does it signify? Is it just a prefix, can you remove it when storing it and put it back before displaying it?
Unfortunately, if the prefix can change, so that at some point you will have F-100 and so on, then you need to find a way to encode that into the integer you send to the domain model and business logic.
If you can't do that, you need to find a different place to store that prefix, or possibly the entire code.
If you can't do that, well, then you're screwed.
But to be blunt, this smells badly of someone who has been asleep while designing.
"Yeah, that's a good idea, we'll make the loan identification number an integer. I know somewhere, someplace, that someone has an example of what those loan identification numbers look like, but it's just numbers right? I mean, what could go wrong...?"
i think thats possible if you can convert the char into ASCII code.
string --- ASCII
0-10---48-57
A-Z----65-90
a-z----97-122
check out the ASCII table for more info..
Conversion:
so you can convert
RT1 to 082084049
RT2 to 082084050 and
MDR3 to 077068082051
i just prepend 0's to each character if the value is not 3 digit one(because max possible ASCII (z) value is in 3 digits ). R is actually 82, it becomes 082. And the final integer (no of digits) would be in multiples of 3.
Extraction:
This helps to extract the info in the other end. just split this into seperate 3 digit values and convert them to char and append them. you wil get the final string.
082,084,049 - R,T,1. thats all.
p.s: this method may end up in arithmetic overflow problem for large strings
I suggest that you talk to someone in the business/domain layer, or who is responsible for the design of the system, and point out to them that loannumber need to be changed to a string. No one will thank you for bodging your code to get around what is a design flaw--it can only lead to trouble and confusion later.