Looping through string keeping only digits and decimal points - c#

After reading answers to similar questions I came up with the following approach to my problem of testing the contents of a text box for a number.
My question now is: Is my solution as simple as it can be?
internal static string testStringForNumber(string v)
{
// example: string strToTest = Data.CommonMethods.testStringForNumber(this.amountTextBox.Text.Trim());
string returnValue = "";
string chr = "";
int nLen = v.Length;
int i = 0; // this is my counter
while (i < nLen)
{
chr = v.Substring(i, 1);
switch (chr)
{
case ".":
returnValue = returnValue + chr;
break;
case "0":
returnValue = returnValue + chr;
break;
case "9":
returnValue = returnValue + chr;
break;
case "8":
returnValue = returnValue + chr;
break;
case "7":
returnValue = returnValue + chr;
break;
case "6":
returnValue = returnValue + chr;
break;
case "5":
returnValue = returnValue + chr;
break;
case "4":
returnValue = returnValue + chr;
break;
case "3":
returnValue = returnValue + chr;
break;
case "2":
returnValue = returnValue + chr;
break;
case "1":
returnValue = returnValue + chr;
break;
}
i = i + 1;
}
return returnValue;
}

I'd use a regex instead personally.
string newString = Regex.Replace(strToTest,#"[^\d.]","");
Of course, I don't know WHY you would do this. Something like "Test 23. Test 42." Will return the string 23.42.

It is not, I'll give a one-liner here, but I'd recommend StringBuilder for code maintainance.
public string NumbersAndDecimalPoints(string input)
{
return new string(input.ToCharArray().Where(t => char.IsDigit(t) || t == '.').ToArray());
}
If a string is what you want. Else you can parse it to a number as well.
return decimal.Parse(NumbersAndDecimalsPoints(v));
If on the other hand the task is finding out if the string is a valid number, I'd either go with #Steve and use Any() or just try to parse it.
Using Any() (which won't catch multiple separators):
var isNumber = !input.ToCharArray().Any(c => "1234567890.".IndexOf(c) < 0);
Using TryParse() (really the best method):
var number = 0m;
var isNumber = decimal.TryParse(input, out number); // is number true = is valid number

Related

multiple string comparing in switch

have a requirement in C# switch in string compare.
string result = getResponse();
switch (result)
{
case "S0": ret = "true";
break;
case "S1": ret = "fail";
break;
// ? can be any digit number, ex, M:0, M:100, M:1000
case "M:?": ret = result;
break;
default: ret = "wrong";
break;
}
how to make the switch statement in "M:?" case?
If you are using C# 7, you can use switch pattern matching.
string ret = string.Empty;
string result = getResponse();
switch (result)
{
case "S0":
ret = "true";
break;
case "S1":
ret = "fail";
break;
case var val when new Regex(#"^M:\d+").IsMatch(val):
ret = val;
break;
default:
ret = "wrong";
break;
}
As #KingKing commented in the question that many devs does not have luxury of using C# 7, at that time you can use following code :
string result = getResponse();
switch (Regex.IsMatch(result, #"^M:\d+") ? "M:XXX" : result)
{
case "S0":
ret = "true";
break;
case "S1":
ret = "fail";
break;
case "M:XXX": // make it unique so that it will not collide with other case statement and update this value in ternary condition accordingly
ret = result;
break;
default:
ret = "wrong";
break;
}
Another option instead of using switch pattern matching is to handle more complex case in the default bloc with if statements like so
string ret = string.Empty;
string result = getResponse();
switch (result)
{
case "S0":
ret = "true";
break;
case "S1":
ret = "fail";
break;
default:
Regex rgx = new Regex(#"^M:\d+");
if (rgx.IsMatch(result))
{
ret = result;
}
else {
ret = "wrong";
}
break;
}
try with pattern matching :-
public string Convert(string result)
{
switch (result)
{
case "S0": return "true";
case "S1": return "fail";
case var m when Regex.IsMatch(m, #"^M:\d+$"): return m;
default: return "wrong";
}
}
if you are using an older C# without pattern matching, move your clause to before the switch
public string Convert(string result)
{
if(Regex.IsMatch(result, #"^M:\d+$")) return result;
switch (result)
{
case "S0": return "true";
case "S1": return "fail";
default: return "wrong";
}
How about using LINQ:
var switches = new Func<string, string>[]
{
x => x == "S0" ? "true" : null,
x => x == "S1" ? "fail" : null,
x =>
{
var match = Regex.Match(x, #"^M:(\d+)");
if (match.Success)
return match.Groups[1].Captures[0].Value;
return null;
},
x => "wrong",
};
string result = "M:47";
string ret = switches.Select(s => s(result)).Where(r => r != null).First();
That gives me "47" for ret.

i want make math operation with one button C#

i want make math operation with one button and textbox , when type on textbox operation like 25+5+-10+7 and press on button show me result
i am trying do this but i can not.
in this code i make for each char in textbox and i want store 25 in firstvalue parameter and + in op parameter and 5 in secondvalue parameter
and make operation 25+5=30 and store it in firstvalue parameter and store +- in op , 10 in secondvalue and make operation ,store it in firstvalue ....and so on until length of string .
but i do not know where and how store second value
private void button1_Click(object sender, EventArgs e)
{
string allValue = textBox1.Text;
int firstValue=0;
int secondValue=0;
string first = string.Empty;
string op = string.Empty;
foreach (char item in allValue)
{
if (char.IsNumber(item))
{
first += item;
}
else if(item=='+' || item=='-' || item=='*' || item=='/')
{
firstValue = Int32.Parse(first);
op += item;
first = "";
switch (op)
{
case "+":
firstValue = firstValue + secondValue;
break;
case "-":
firstValue = firstValue - secondValue;
break;
case "+-":
firstValue = firstValue +- secondValue;
break;
case "*":
firstValue = firstValue * secondValue;
break;
case "/":
firstValue = firstValue / secondValue;
break;
}
}
}
MessageBox.Show(firstValue.ToString());
}
If you want to parse the string from beginning to end and do the calculations during the parsing, then you can't do the calculation between two values until you have both operands. That means that you have to wait until you find the second operator (or the end of the string) until you can do the calculation for the first operator.
When you parse the number, put that in the secondValue variable. If it's the first value then just move it to firstValue and continue to get another value, otherwise do the calculation with the two values that you have according to the previous operator.
To include the last calculation you can loop one step more than the last character in the string. That allows your loop to run one more time after the last value, and you can do that last calculation. It requires a few more checks though, so that you don't actually try to read from that position outside the string.
To handle negative values you should include that in the value, not using a +- operator. Otherwise you would also need --, *- and /- operators.
Example (not tested):
private void button1_Click(object sender, EventArgs e) {
string allValue = textBox1.Text;
int firstValue = 0;
int secondValue = 0;
string second = string.Empty;
string op = string.Empty;
for (int i = 0; i <= allValue.Length; i++) {
if (i < allValue.Length && (Char.IsNumber(allValue[i]) || (char == '-' && second.Length == 0))) {
second += allValue[i];
} else if (i == allValue.Length || "+-*/".indexOf(allValue[i]) != -1) {
secondValue = Int32.Parse(second);
if (op.Length > 0) {
switch (op) {
case "+": firstValue += secondValue; break;
case "-": firstValue -= secondValue; break;
case "*": firstValue *= secondValue; break;
case "/": firstValue /= secondValue; break;
}
} else {
firstValue = secondValue;
}
if (i < allValue.Length) {
op = allValue[i].ToString();
}
second = "";
} else {
// illegal formula
}
}
MessageBox.Show(firstValue.ToString());
}
Note: This calculates strictly from left to right and does not handle priority, e.g. 1+2*3 is evaluated as (1+2)*3, not the 1+(2*3) that is normally used.
You can use the NCalc library. You would use it like this:
NCalc.Expression e = new NCalc.Expression(textBox1.Text);
double value = e.Evaluate();
// Next, do something with your evaluated value.
Would this work for you? As mentioned in earlier answers this does not pay regard to the order of operations and there is a lot of other error checking that should likely be done.
using System.Text.RegularExpressions;
private void button1_Click(object sender, EventArgs e)
{
MatchCollection values = Regex.Matches(textBox1.Text, "[0-9]+");
MatchCollection operations = Regex.Matches(textBox1.Text, #"[\/\*\+-]");
if (values.Count == operations.Count + 1)
{
int total = int.Parse(values[0].Value);
if (operations.Count > 0)
{
for (int index = 1; index < values.Count; index++)
{
int value = int.Parse(values[index].Value);
switch (operations[index - 1].Value)
{
case "+":
total += value;
break;
case "-":
total -= value;
break;
case "/":
total /= value;
break;
case "*":
total *= value;
break;
}
}
}
MessageBox.Show(total.ToString());
}
}
Doing all the things from scratch is not easy. In my simplified answer I'll presume your operators are only +-*/ (including their precedence).
Reference: How to evaluate an infix expression in just one scan using stacks?
First you should parse the input string... My way would be
public enum TokenType
{
Operator,
Operand
}
public class Token
{
public string Value { get; set; }
public TokenType Type { get; set; }
public override string ToString()
{
return Type + " " + Value;
}
}
IEnumerable<Token> Parse(string input)
{
return Regex.Matches(input, #"(?<value>\d+)|(?<type>[\+\-\*\/\(\)])").Cast<Match>()
.Select(m => m.Groups["value"].Success
? new Token() { Value = m.Groups["value"].Value, Type = TokenType.Operand }
: new Token() { Value = m.Groups["type"].Value, Type = TokenType.Operator });
}
This Parse method will return all the operators and operands in your expression.
The next step would be to evaluate the expression using a stack
Token Exec(Stack<Token> operatorStack, Stack<Token> operandStack)
{
var op = operatorStack.Pop();
var t1 = operandStack.Pop();
var t2 = operandStack.Pop();
switch (op.Value)
{
case "+": return new Token() { Value = (int.Parse(t1.Value) + int.Parse(t2.Value)).ToString(), Type = TokenType.Operand };
case "-": return new Token() { Value = (int.Parse(t2.Value) - int.Parse(t1.Value)).ToString(), Type = TokenType.Operand };
case "*": return new Token() { Value = (int.Parse(t1.Value) * int.Parse(t2.Value)).ToString(), Type = TokenType.Operand };
case "/": return new Token() { Value = (int.Parse(t2.Value) / int.Parse(t1.Value)).ToString(), Type = TokenType.Operand };
}
return null;
}
int Eval(string input)
{
var tokens = Parse(input);
var operatorStack = new Stack<Token>();
var operandStack = new Stack<Token>();
var precedence = new Dictionary<string, int>() { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 } };
foreach (var token in tokens)
{
if (token.Type == TokenType.Operand) operandStack.Push(token);
if (token.Type == TokenType.Operator)
{
while (operatorStack.Count > 0 && precedence[operatorStack.Peek().Value] >= precedence[token.Value])
{
operandStack.Push(Exec(operatorStack, operandStack));
}
operatorStack.Push(token);
}
}
while(operatorStack.Count>0)
{
operandStack.Push(Exec(operatorStack, operandStack));
}
return int.Parse(operandStack.Pop().Value);
}
You can test your code now.
int r1 = Eval("25 - 5");
int r2 = Eval("25 - 5*2");
int r3 = Eval("25 - 5 + 3*2");
int r4 = Eval("25/5 + 7*3");
int r5 = Eval("25/5 + 7*3 + 2");
int r6 = Eval("25/5 + 7*3 * 2");

Escape quotes for interpolated string

I have a program that generates C# from bits of C# stored in an XML file. If I have a snippet like:
foo {bar}
I need to transform that into an interpolated string, like this:
$#"foo {bar}"
The problem is that, if I have quotes outside a placeholder, e.g.:
"foo" {bar}
I need to double those:
$#"""foo"" {bar}"
but ignore quotes inside placeholders:
foo {"bar"}
should produce:
$#"foo {"bar"}"
Also, need to look out for doubled braces:
foo {{"bar"}}
should produce:
$#"foo {{""bar""}}"
And perhaps the trickiest of all, if the placeholder is preceded and/or followed by an even number of braces:
foo {{{"bar"}}}
should produce:
$#"foo {{{"bar"}}}"
In short, if there's a placeholder then ignore everything inside. For the rest of the text, double quotes.
Can this be accomplished using regular expressions? If not, what alternatives do I have?
You will need at least 2 steps:
Add quotes inside the expression:
"(?=[^}]*(?:}})*[^}]*$)|(?<=^[^{]*(?:{{)*)" =>
replace with ""
See demo
Enclose in $#"..." with string.Format("$#\"{0}\"", str);
Here is an IDEONE demo
var s = "\"foo\" {bar}";
var rx = new Regex(#"(?<!(?<!{){[^{}]*)""(?![^{}]*}(?!}))");
Console.WriteLine(string.Format("$#\"{0}\"",rx.Replace(s,"\"\"")));
And another demo here
This cannot be done with regular expressions. Knowing when a placeholder starts is easy, knowing when it ends is the hard part, since a placeholder can hold almost any C# expression, so you have to keep track of blocks ({}) and literals (strings, chars, comments) because any brace in a literal is not significant.
This is the code I came up with:
enum ParsingMode {
Text,
Code,
InterpolatedString,
InterpolatedVerbatimString,
String,
VerbatimString,
Char,
MultilineComment
}
public static string EscapeValueTemplate(string valueTemplate) {
if (valueTemplate == null) throw new ArgumentNullException(nameof(valueTemplate));
var quoteIndexes = new List<int>();
var modeStack = new Stack<ParsingMode>();
modeStack.Push(ParsingMode.Text);
Func<ParsingMode> currentMode = () => modeStack.Peek();
for (int i = 0; i < valueTemplate.Length; i++) {
char c = valueTemplate[i];
Func<char?> nextChar = () =>
i + 1 < valueTemplate.Length ? valueTemplate[i + 1]
: default(char?);
switch (currentMode()) {
case ParsingMode.Code:
switch (c) {
case '{':
modeStack.Push(ParsingMode.Code);
break;
case '}':
modeStack.Pop();
break;
case '\'':
modeStack.Push(ParsingMode.Char);
break;
case '"':
ParsingMode stringMode = ParsingMode.String;
switch (valueTemplate[i - 1]) {
case '#':
if (i - 2 >= 0 && valueTemplate[i - 2] == '$') {
stringMode = ParsingMode.InterpolatedVerbatimString;
} else {
stringMode = ParsingMode.VerbatimString;
}
break;
case '$':
stringMode = ParsingMode.InterpolatedString;
break;
}
modeStack.Push(stringMode);
break;
case '/':
if (nextChar() == '*') {
modeStack.Push(ParsingMode.MultilineComment);
i++;
}
break;
}
break;
case ParsingMode.Text:
case ParsingMode.InterpolatedString:
case ParsingMode.InterpolatedVerbatimString:
switch (c) {
case '{':
if (nextChar() == '{') {
i++;
} else {
modeStack.Push(ParsingMode.Code);
}
break;
case '"':
switch (currentMode()) {
case ParsingMode.Text:
quoteIndexes.Add(i);
break;
case ParsingMode.InterpolatedString:
modeStack.Pop();
break;
case ParsingMode.InterpolatedVerbatimString:
if (nextChar() == '"') {
i++;
} else {
modeStack.Pop();
}
break;
}
break;
case '\\':
if (currentMode() == ParsingMode.InterpolatedString) {
i++;
}
break;
}
break;
case ParsingMode.String:
switch (c) {
case '\\':
i++;
break;
case '"':
modeStack.Pop();
break;
}
break;
case ParsingMode.VerbatimString:
if (c == '"') {
if (nextChar() == '"') {
i++;
} else {
modeStack.Pop();
}
}
break;
case ParsingMode.Char:
switch (c) {
case '\\':
i++;
break;
case '\'':
modeStack.Pop();
break;
}
break;
case ParsingMode.MultilineComment:
if (c == '*') {
if (nextChar() == '/') {
modeStack.Pop();
i++;
}
}
break;
}
}
var sb = new StringBuilder(valueTemplate, valueTemplate.Length + quoteIndexes.Count);
for (int i = 0; i < quoteIndexes.Count; i++) {
sb.Insert(quoteIndexes[i] + i, '"');
}
return sb.ToString();
}

Replace int numbers with the corresponding months(strings) without using If-else

What is the best way to do this task without using the if-else clause 12 times. The task is this:
if(mon=="1")
{
month="JAN";
}
else if(mon=="2")
{
month="FEB";
}
and so on..
Try using this code
using System.Globalization;
var month = 7;
var dtf = CultureInfo.CurrentCulture.DateTimeFormat;
string monthName = dtf.GetMonthName(month);
string abbreviatedMonthName = dtf.GetAbbreviatedMonthName(month);
using System.Globalization;
CultureInfo.CurrentCulture.DateTimeFormat.AbbreviatedMonthNames[int.Parse(mon)-1];
Alternative for this is to use array.
string[] months = new string[]{"JAN", "FEB", "MAR",..., "DEC"};
string month = months[value - 1];
-1 because the index starts at zero.
or
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(1)
Use Switch-Case:
switch(mon)
{
case "1":
month = "JAN";
break;
case "2":
month = "FEB";
break;
default:
month = string.Empty; // OR throw exception
break;
}
Another option:
switch (int.parse(mon))
{
case 1: return "JAN";
case 2: return "FEB";
//...
case 12: return "DEC";
default: return "???";
}
// Azodious notes that switches work on strings too, so you can also do:
switch (mon)
{
case "1": return "JAN";
case "2": return "FEB";
//...
case "12": return "DEC";
default: return "???";
}
or as an index into an array, similar to what John Woo showed, (but you'd have to parse mon as an int first).

casting data split to integer

i realize that it does not read inside if (berjaya[23].Equals(70)) as if it was not equal to 70. but when i tried to show berjaya[23] using MessageBox, it do appear 70.
my first guess is casting. i tried int value = (int)(berjaya[23]); and my next plan is try do if(value == 70) but it says string cannot be convert to int.
is there any other way for the (berjaya[23].Equals(70)) be read?
===EDIT===
i should casting the data split by this way:
int.TryParse(berjaya[23], out value1);
then to change the picture, i used this:
if (value1 == 301)
{
Bitmap abc = (Bitmap)System.Drawing.Bitmap.FromFile("C:\\Users\\HDAdmin\\Pictures\\HospitalIcon\\web\\web2\\images\\a3_01.gif");
pictureBox1.Image = abc;
}
Try this, but set the image names
Bitmap abc = (Bitmap)System.Drawing.Bitmap.FromFile("C:\\Users\\HDAdmin\\Pictures\\HospitalIcon\\fafa\\images\\a3_00.gif");
if (berjaya[23].Equals(70))
{
abc = (Bitmap)System.Drawing.Bitmap.FromFile("C:\\Users\\HDAdmin\\Pictures\\HospitalIcon\\fafa\\images\\a3_01.gif");
}
myPicturebox.Image = abc;
You must add first a Empty bitmap.
like:
Bitmap abc;
Or you can assign value for that. Then in if/else you change into:
abc = (Bitmap)System.Drawing.Bitmap.FromFile("C:\\Users\\HDAdmin\\Pictures\\HospitalIcon\\fafa\\images\\a3_01.gif");
Additonal:
Ops, sorry Miss/Mr/Ms (What must I say?) Sara Brown, That will be a much complicated. add this function
public int value(string num){
string a = num.split("");//If this function true?
int res = 0;
for(var b = 0; b<a.Length; b++){
res = res*10;
switch(a[b]){
case "0":
break;
case "1":
res += 1;
break;
case "2":
res += 2;
break;
case "3":
res += 3;
break;
case "4":
res += 4;
break;
case "5":
res += 5;
break;
case "6":
res += 6;
break;
case "7":
res += 7;
break;
case "8":
res += 8;
break;
case "9":
res += 9;
break;
}
}
return res;
}
the add this code
Bitmap abc;
if(value(Berjaya[23])==70){
abc = (Bitmap)System.Drawing.Bitmap.FromFile("C:\\Users\\HDAdmin\\Pictures\\HospitalIcon\\fafa\\images\\a3_01.gif");
}

Categories

Resources