I really hate to join a forum and start asking questions, but I'm developing a program which contains a command line where you can enter commands in one window, and get the output from another (see attachment if you will). It accepts commands which I've created, and instructions from the assembly language. In total, I would expect to have somewhere around 300 commands and instructions.
The current system I have setup is something like so:
Code:
public string Input = "";
// Converts code into something readable to the interpret function.
public void ParseInput()
{
// Code here would read the input offered by the text box and convert it.
interpret();
}
// Reads code and decides what to do with it.
public void Interpret();
{
if (input == proper_syntax)
commandA_do();
elseif(input == proper_syntaxB)
commandB_do();
// 300 elseif's later...
else
{ // say nothing happened }
}
Proper syntax notwithstanding, of course. Now I would assume this is very bad to have 300 'if' long if statement (hogging resources, and clogging pipes, and whatnot). Even with the 15 or so commands I had declared using that format, it did crash the program at some times. So, what would be an effective way to condense down those if statements?
Welcome to the forum! Thanks for being so polite; we're happy to help, if we can. :-)
A branch table comes to mind. Instead of linearly going through a long string of if's, the idea is to store the location of the handling code in hash table and then jump to the code. This way you get time complexity O(1) instead of O(n) where n is the number of types of instructions. In assembly, this was realized by storing memory address to jump to, but in C# we can do it with delegates. Declaring a delegate allows us to store references to functions that have a specific functional signature. (Sorry, they're a little complicated and I can't think of how to explain better; best to just read the MSDN article: http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx
For example, suppose we had three instructions that take arguments like assembly code does (e.g.):
use System.Collections.Generic;
//Declare the StatementHandler type to point at methods which contain a
// functional signature wherein they return void and take only one string as input
private delegate void StatementHandler(string);
//Declare some handlers routines that will do whatever the MOV, JMP and CMP statements do
// Notice that they all match the functional signature of a StatementHandler
private static void movHandler(string input) { ... }
private static void jmpHandler(string input) { ... }
private static void cmpHandler(string input) { ... }
//Declare a hash table (a type safe hash table is called a dictionary in C#
private static Dictionary<string, StatementHandler> branchTable;
//Initialize the branch table; call once at the very start of the program
private static void initBranchTable()
{
//Allocate memory
branchTable = new Dictionary<string, StatementHandler>();
//Add each of the handlers to the dictionary
branchTable.Add("mov", movHandler);
branchTable.Add("jmp", jmpHandler);
branchTable.Add("cmp", cmpHandler);
}
public static void interpret(string input)
{
//Get the part of the input before the first space (telling us what type of instruction it is;
// the parsing may be slightly different based on your syntax)
string instructionType = input.Split(' ')[0];
//Check to see if we know about this type of instruction
if( branchTable.ContainsKey(instructionType) )
{
//If we know this instruction, call the appropriate handler
StatementHandler handler = branchTable[instructionType];
//Call the appropriate handler routine (e.g. movHandler if it was a mov statement)
handler(input);
//N.B.: this could be more compactly written as one statement (uh, I think...):
// branchTable[instructionType](input);
}
else
{
//This isn't an instruction
complainToUser();
}
}
Does that help? You might also want to do some benchmarking; it may or may not be faster to just use a long list of if's depending on how many branches you have exactly. (There is some small amount overhead in using delegates).
Also, none of my code is debugged, so sorry if there are syntax errors anywhere. I just wrote it in the window...
Hope that helps; let me know if further problems.
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
switch might be a simpler solution that my more complicated one... not sure if there is some optimization trade off between using switch and doing it manually.
EDIT: Eh, I thought about it some more (read the thread I linked you too) and am going to come out in favor of doing it yourself with my more complex methods. The compiled behavior of switch does not guarantee constant-time lookup (and - I am guessing - for your inputs will generate a binary search tree giving you something like O(log n) lookup time). At least if you do it yourself you know what you're getting. Use of switch still may or may not be faster depending on how many instructions you have exactly... Benchmark it, I guess, if performance is an issue.
Last edited by BioPhysEngr; July 28th, 2011 at 01:34 AM.
Reason: updated some thoughts
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
Eh, I can't edit my posts for whatever reason. At the current moment, I'd prefer reliability, consistency and organization versus performance. Would you know how a list of 300 functions would perform with if, switch, or a table?
if: Good for only a few cases (< 10?)
switch: probably reasonable performance (possibly optimal); easy to read the code
table: most scalable, you know exactly what the code is doing
I don't know where the regime change between when you should use if, switch and table occurs though. Probably the best advice is to rapidly prototype and get something working using switch and then if you are having performance problems implement table. Agreed, other forum members?
I try not to get too caught up in Agile programming dogma, but rapid prototyping followed by refinement usually serves me well. I recommend it to you too.
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.