multiple string comparing in switch - c#

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.

Related

How can i use a static method in in a non-static class

I want to use this method in an non-static class:
public class LogicalExpressionCalculator : MeasurementInterpreter
{
private static Boolean Operator(this string logic, string x, string y)
{
switch (logic)
{
case "==": return x == y;
case "!=": return x != y;
case ">": return Int32.Parse(x) > Int32.Parse(y);
case ">=": return Int32.Parse(x) >= Int32.Parse(y);
case "<": return Int32.Parse(x) < Int32.Parse(y);
case "<=": return Int32.Parse(x) <= Int32.Parse(y);
case "&&": return bool.Parse(x) && bool.Parse(y);
case "||": return bool.Parse(x) || bool.Parse(y);
default: throw new Exception("invalid logic");
}
}
}
How can I change this method to works in a non static class?
The method i want to used inside the class in this method:
protected void CalculateExpression()
{
Stack variableStack = new Stack();
Stack operatorStack = new Stack();
foreach (string field in contextString)
{
switch (field)
{
case "(":
case "<":
case ">":
case "==":
operatorStack.Push(field);
break;
case ")":
string operatorPop = null;
while (operatorPop == "(")
{
operatorPop = operatorStack.Pop().ToString();
resultStack = Operator(operatorPop, variableStack.Pop().ToString(), variableStack.Pop().ToString());
variableStack.Push(resultStack);
}
break;
case "UserInput":
case "EngineRpm":
case "VehicleSpeed":
variableStack.Push((string)hashtable[field]);
break;
default:
int integer;
if(Int32.TryParse(field, out integer)) variableStack.Push(integer);
if (bool.Parse(field)) variableStack.Push(field);
break;
}
}
Result = resultStack;
if (Result)
{
}
}
i get an error
Extension method must be static
Remove this doesn't seem to be necessary.
private static Boolean Operator(string logic, string x, string y)
{
switch (logic)
{
case "==": return x == y;
case "!=": return x != y;
case ">": return Int32.Parse(x) > Int32.Parse(y);
case ">=": return Int32.Parse(x) >= Int32.Parse(y);
case "<": return Int32.Parse(x) < Int32.Parse(y);
case "<=": return Int32.Parse(x) <= Int32.Parse(y);
case "&&": return bool.Parse(x) && bool.Parse(y);
case "||": return bool.Parse(x) || bool.Parse(y);
default: throw new Exception("invalid logic");
}
}

Looping through string keeping only digits and decimal points

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

Convert If Statement into Switch

I have this If statement and I would like to move them into Case-Switch
Here is my if Stataments:
if (rResponse.ErrorCode[0] == 0x20 && rResponse.ErrorCode[1] == 0x03)
ErrorMsg = "COMM_FRAME_ERROR";
if (rResponse.ErrorCode[0] == 0x20 && rResponse.ErrorCode[1] == 0x04)
ErrorMsg = "JAM";
if (rResponse.ErrorCode[0] == 0x20 && rResponse.ErrorCode[1] == 0x05)
ErrorMsg = "NO_CARD";
How can I do that?
if (rResponse.ErrorCode[0] == 0x20) {
switch(rResponse.ErrorCode[1]) {
case 0x03:
ErrorMsg = "COMM_FRAME_ERROR";
break;
case 0x04:
ErrorMsg = "JAM";
break;
case 0x05:
ErrorMsg = "NO_CARD";
break;
}
}
If u want both in switch case:
switch(rResponse.Errorcode[0])
case 0x20:
switch(rResponse.ErrorCode[1]) {
case 0x03:
ErrorMsg = "COMM_FRAME_ERROR";
break;
case 0x04:
ErrorMsg = "JAM";
break;
case 0x05:
ErrorMsg = "NO_CARD";
break;
}
break;
Can omit or change the exception,
if (rResponse.ErrorCode[0] == 0x20)
{
switch (rResponse.ErrorCode[1])
{
case 0x03:
ErrorMsg = "COMM_FRAME_ERROR";
break;
case 0x04:
ErrorMsg = "JAM";
break;
case 0x05:
ErrorMsg = "NO_CARD";
break;
default:
throw new InvalidOperationException();
break;
}
}
switch(rResponse.Errorcode[0])
{
case 0x20:
switch(rResponse.ErrorCode[1])
{
case 0x03:
ErrorMsg = "COMM_FRAME_ERROR";
break;
case 0x04:
ErrorMsg = "JAM";
break;
case 0x05:
ErrorMsg = "NO_CARD";
break;
}
break;
}
You can try something like this..
switch (rResponse.ErrorCode[0] + rResponse.ErrorCode[1])
{
case (0x20 + 0x03):
ErrorMsg = "COMM_FRAME_ERROR";
break;
case (0x20 + 0x04):
....
}
though this may not suite all the situations,
Although with the information provided Itay's response might be best. But if this error portion is on a larger scale then maybe something as follows might be worth a go. (Similar approach, just makes it easy to add on.
private string GetError(byte response1, byte response2)
{
var ErrorMessage = "";
switch (response1)
{
case 0x20:
ErrorMessage = ParseCardErrors(response2);
break;
case 0x21:
ErrorMessage = ParseDeviceErrors(response2);
break;
default:
ErrorMessage = "Unknown Error";
}
return ErrorMessage;
}
private string ParseCardErrors(byte response)
{
switch(response)
{
case 0x03:
return "COMM_FRAME_ERROR";
case 0x04:
return "JAM";
case 0x05:
return "NO_CARD";
default:
return "Unknown card Error";
}
}
private string ParseDeviceErrors(byte response)
{
switch(response)
{
case 0x03:
return "COMM_FRAME_ERROR";
case 0x04:
return "Unplugged";
case 0x05:
return "No device";
default:
return "Unknown device Error";
}
}
I might be posting a very diffrent solution this question but it can answer #Robert question:
class Program
{
//This can be included in Seprate class also
public enum ErrorMessages
{
//Store any Values as Key and Pair
// Provide and easy way to update answers
Error1 = 1,
Error2 = 2,
Error3 = 3,
Error4 = 4
}
public static void Main()
{
ICollection<EnumValueDto> list = EnumValueDto.ConvertEnumToList<ErrorMessages>();
foreach (var element in list)
{
Console.WriteLine(string.Format("Key: {0}; Value: {1}", element.Key, element.Value));
}
Console.Read();
/* OUTPUT:
Key: 1; Value: Error1
Key: 2; Value: Error2
Key: 3; Value: Error3
Key: 4; Value: Error4
*/
}
public class EnumValueDto
{
public int Key { get; set; }
public string Value { get; set; }
public static ICollection<EnumValueDto> ConvertEnumToList<T>() where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new Exception("Type given T must be an Enum");
}
var result = Enum.GetValues(typeof(T))
.Cast<T>()
.Select(x => new EnumValueDto
{
Key = Convert.ToInt32(x),//values are arbitary here any datatype will work
Value = x.ToString(new CultureInfo("en"))
})
.Where(err => err.Key==3) //Instead of 3 as key here use Response variable instead
.ToList()
.AsReadOnly();
return result;
}
}
}

c# web service not returning results

I recently "finished" a new project except there is a small problem. Im not getting my results back.
This project utilizes c# web services via a SOAP client along with Request and Response Classes. The project is designed to reserve something, in this demo, it reserves a seat in a cinema. However when the data is passed from the windows form client to the web service, nothing comes back. I recently stopped the project from freezing upon execution of the web method.
This is the method that calls the web service (The method signature is only temporary)
public void derp()
{
var client = new SampleServiceSoapClient();
var req = new GetReservationRequest();
req.row = row;
req.seat = seat;
req.name = textNameRequest.Text;
try
{
client.GetReservation(req);
}
catch (Exception err)
{
MessageBox.Show("Server Unavailable");
}
}
I am running this method on a seperate thread to stop crashing. The output of this method is supposed to come back through a response object and then i assign the values of said object to text boxes on the form. However, the data is lost before it returns.
The web method is as follows
[WebMethod]
public GetReservationResponse GetReservation(GetReservationRequest req)
{
object o = HttpContext.Current.Cache["Reservation"];
if(o == null)
{
o = reservedSeat;
}
else
{
reservedSeat = (bool[,])o;
}
GetReservationResponse resp = new GetReservationResponse();
string rowHolder = "A";
int rowRequest = req.row;
int seatCopy = 0;
bool emptySeat = false;
while (rowRequest < 12)
{
for (int seat = req.seat; seat < 16; seat++)
{
if (reservedSeat[req.row, seat])
{
//Loop back
}
else
{
emptySeat = true;
seatCopy = seat;
break;
}
}
if (reservedSeat[req.row, 15])
{
seatCopy = 0;
break;
}
}
switch (rowRequest)
{
case 1: rowHolder = "A";
break;
case 2: rowHolder = "B";
break;
case 3: rowHolder = "C";
break;
case 4: rowHolder = "D";
break;
case 5: rowHolder = "E";
break;
case 6: rowHolder = "F";
break;
case 7: rowHolder = "G";
break;
case 8: rowHolder = "H";
break;
case 9: rowHolder = "I";
break;
case 10: rowHolder = "J";
break;
case 11: rowHolder = "K";
break;
case 12: rowHolder = "L";
break;
default: rowHolder = "None Specified";
break;
}
int x = 0;
if (!reservedSeat[rowRequest, seatCopy])
{
reservedSeat[rowRequest, seatCopy] = true;
seatCopy++;
//resp.row = rowRequest;
x = seatCopy;
seatCopy--;
if (seatCopy.Equals(15))
{
rowRequest++;
}
}
resp.row = rowHolder;
resp.seat = x;
//row++
return resp;
}
I have no clue why the data is being lost before it comes back but some information would be amazing...
Where in this code rowrequest is incremented? It seems to me, that you have infinite loop here:
while (rowRequest < 12)
{
for (int seat = req.seat; seat < 16; seat++)
{
if (reservedSeat[req.row, seat])
{
//Loop back
}
else
{
emptySeat = true;
seatCopy = seat;
break;
}
}
if (reservedSeat[req.row, 15])
{
seatCopy = 0;
break;
}
}

How could I refactor this into more manageable code?

Is this code even complex enough to deserve a higher level of abstraction?
public static JsonStructure Parse(string jsonText)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
var key = default(string);
var value = default(object);
foreach (var token in Lexer.Tokenize(jsonText))
{
switch (currentState)
{
case ParserState.Begin:
switch (token.Type)
{
case TokenType.BeginObject:
currentState = ParserState.Name;
current = result = new JsonObject();
break;
case TokenType.BeginArray:
currentState = ParserState.Value;
current = result = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Name:
switch (token.Type)
{
case TokenType.String:
currentState = ParserState.NameSeparator;
key = (string)token.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.NameSeparator:
switch (token.Type)
{
case TokenType.NameSeparator:
currentState = ParserState.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Value:
switch (token.Type)
{
case TokenType.Number:
case TokenType.String:
case TokenType.True:
case TokenType.False:
case TokenType.Null:
currentState = ParserState.ValueSeparator;
value = token.Value;
break;
case TokenType.BeginObject:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.Name;
current = new JsonObject();
break;
case TokenType.BeginArray:
structureStack.Push(current);
currentState = ParserState.Value;
current = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.ValueSeparator:
var jsonObject = (current as JsonObject);
var jsonArray = (current as JsonArray);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.Name;
}
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.Value;
}
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
currentState = ParserState.End;
break;
case TokenType.ValueSeparator:
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
case TokenType.ValueSeparator:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
var previousJsonArray = (previous as JsonArray);
if (previousJsonObject != null)
{
previousJsonObject.Add(keyStack.Pop(), current);
currentState = ParserState.Name;
}
if (previousJsonArray != null)
{
previousJsonArray.Add(current);
currentState = ParserState.Value;
}
if (token.Type != TokenType.ValueSeparator)
{
currentState = ParserState.End;
}
current = previous;
break;
default:
throw new JsonException(token, currentState);
}
break;
default:
break;
}
}
return result;
}
Without looking at it in detail, as you are parsing based on state, could you use the state pattern to break it up and parse each bit in a separate class based on the state?
something like this might be a start, although this is just pseudo code...
public interface IParserState
{
IParserState ParseToken (IToken token);
}
public class BeginState : IParserState
{
private readonly Stack<JsonStructure> m_structureStack;
private readonly Stack<String> m_keyStack;
public BeginState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
{
m_structureStack = structureStack;
m_keyStack = keyStack;
}
public IParserState ParseToken(IToken token)
{
switch (token.Type)
{
case TokenType.OpenBrace:
return new ObjectKeyParserState(m_structureStack,m_keyStack);
case TokenType.OpenBracket:
return new ArrayValueParserState(m_structureStack, m_keyStack);
default:
throw new JsonException (token);
}
}
}
public class ObjectKeyParserState : IParserState
{
private readonly Stack<JsonStructure> m_structureStack;
private readonly Stack<String> m_keyStack;
private readonly JsonObject m_current;
public ObjectKeyParserState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
{
m_current = new JsonObject();
}
public IParserState ParseToken (IToken token)
{
switch (token.Type)
{
case TokenType.StringLiteral:
key = (string)token.Value;
return new ColonSeperatorParserState(m_structureStack, m_keyStack, m_current,key);
default:
throw new JsonException(token);
}
}
The 'conceptual design' in this case is production rules. If you were to design json yourself, would you think in terms of "A pair is a key followed by a colon followed by a value" or would you think in terms like "Colons will do 'a' in this case 'A' and do 'b' in case 'B' and do 'c' in case 'C'"? Look at http://www.json.org/. You'll see the 'conceptual design' stated in terms of production rules.
Since the 'structural design' of your code does not have the form of the 'conceptual design', no amount of refactoring will help. Changing the 'conceptual design' a small amount, would lead a code change that is hard to code and hard to test. You need a rewrite the code in terms of the 'conceptual design'.
// object
// "{" "}"
// "{" members "}"
private static JsonObject ProduceJsonObject(Tokens tokens)
{
var result = new JsonObject();
tokens.Accept( TokenType.OpenBrace );
result.members = ProduceJsonMembers(tokens);
tokens.Accept( TokenType.CloseBrace );
return result;
}
// members
// pair
// pair { "," pair }
private static JsonMembers ProduceJsonMembers(Tokens tokens)
{
var result = new JsonMembers();
result.Add( ProduceJsonPair(tokens) );
while (tokens.LookAhead == TokenTag.Comma)
{
tokens.Accept( TokenType.Comma );
result.Add( ProduceJsonPair(tokens) );
}
return result;
}
//pair
// string ":" value
private static JsonPair ProduceJsonPair(Tokens tokens)
{
var result = new JsonPair();
result.String = tokens.Accept( TokenType.ID );
tokens.Accept( TokenType.Colon );
result.Value = ProduceJsonValue( tokens );
return result;
}
// and so forth

Categories

Resources