![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Banned
![]() ![]() |
Reducing Repetitive Code
I'm trying to figure out a way to reduce the repetitiveness of this code. I see a couple options: load an array of all the cases from a simplified data file, or declare an array of all the cases.
I could change it to a switch, but I don't feel like having 50 break statements clogging up my source. The code converts an integer that represents the event of an asynchronous key's state, to a string representing the event's signal in human-readable form. Only the relevant signals are being handled, nothing like mouse clicks, F keys, arrows, etc... There is no coreleation between the number and the ASCII value for those characters, only to the extent of how it is defined by the Windows operating system. If only there was a function that could do this conversion for me. Any ideas? c Syntax (Toggle Plain Text)
|
|
|
|
|
|
#2 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,261
Rep Power: 5
![]() |
I haven't tested this with a compiler, but this should be enough to get you started.
Basic notion is that you have some ranges that you are mapping, and finding a technique to map anything in that range. boolean getShift () {
return (GetAsyncKeyState (160) || GetAsyncKeyState (161));
}
boolean getCase () {
return (GetKeyState (20) & 1 ? !getShift () : getShift ());
}
char ExtractChar(unsigned char key, int lower, int upper, const char *data)
{
/* return mapped result, or zero if we can't do the mapping */
return (key >= lower && key <= upper) ? data[key - lower]: '\0';
}
void keyToString (unsigned char key, char *result) {
boolean isUpper = getCase ();
if (key >= 96 && key <= 105) {
result[0] = key-48;
result[1] = 0;
}
else if (key == 8) {
strcpy (result, "^backspace^");
}
else if (key == 9) {
strcpy (result, "^tab^");
}
else if (key == 13) {
strcpy (result, "\n");
}
else if (key == 17) {
strcpy (result, "^ctrl^");
}
else if (key == 18) {
strcpy (result, "^alt^");
}
else if (key == 32) {
strcpy (result, " ");
}
else if (key == 46) {
strcpy (result, "^delete^");
}
else {
result[1] = 0;
if (!isUpper) {
if (key >= 'A' && key <= 'Z')
result[0] = key + 32;
else
result[0] = ExtractChar(key, 48, 57, "0123456789") ||
ExtractChar(key, 186, 192, ";=,-./`") ||
ExtractChar(key, 219, 222, "[\\]'");
}
else if (isUpper) {
if (key >= 'A' && key <= 'Z')
result[0] = key;
else
result[0] = ExtractChar(key, 48, 57, ")!@#$%^&*(") ||
ExtractCha(key, 186, 192, ":+<_>?~") ||
Extract(key, 219, 222, "{|}\"");
}
}
} |
|
|
|
|
|
#3 |
|
Banned
![]() ![]() |
Ahh, yes. That's a good idea! I was trying to think of someway to use strings of data. This way looks perfect. I'll take your idea and come up with my own code. Thanks.
|
|
|
|
|
|
#4 | |
|
Programmer
Join Date: Aug 2005
Location: 0x0010 * 0x0091 + 0x0004
Posts: 65
Rep Power: 4
![]() |
Quote:
__________________
#if 0 /* in case someone actually tries to compile this */ <Jim_McNeat> Is there like a way to put a compiler in "Just trust me on that one" mode? |
|
|
|
|
|
|
#5 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,261
Rep Power: 5
![]() |
Depends on your definition of "neat", I guess. Given that some of the conditions involve the value of "key" being in a range, that means a switch/case approach must list all the cases in that range. That can easily become unwieldy and difficult to maintain (eg it is easy to leave out one of the cases and that is hard to pick up without quite comprehensive testing).
|
|
|
|
|
|
#6 | |
|
Expert Programmer
Join Date: Aug 2005
Location: Rotterdam, the Netherlands
Posts: 942
Rep Power: 4
![]() |
Quote:
|
|
|
|
|
|
|
#7 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,261
Rep Power: 5
![]() |
2Roll4Life7 and Polyphemus_, if you want to play with getting it "neater"
1) Define what you mean by "neatness", and provide some measure by which you determine how neat some code is; 2) Try different approaches. In keeping on topic with this thread, one measure might be related to the amount of repetitive code ...... In practice, I don't tend to like nesting switch/case blocks in if/else blocks (or vice versa) because it takes more time/effort to read and understand, which means it takes more time/effort to maintain. |
|
|
|
|
|
#8 |
|
Professional Programmer
|
There is actually a term for the act of cleaning these kind of things up, it's called "Refactoring. As previously stated, a lot of it is just identifying what code could go into a function. Don't be afraid of having functions with long signatures. A common refactoring process is also creating large arrays with all the necessary information, sometimes even including function names and parameters.
example: if your program looks like this function bla
{
if a then 1
if b then 2
if c then 3
if d then 4
}{
( a, 1 )
( b, 2 )
( b, 3 )
( c, 4)
}foreach $i in $array {
if $i[0] then $i[1]
}the string "subrouting:a:b:c" could be parsed with /^subroutine:(.*):(.*):(.*)/ subroutine(a, b, c) now in some languages this is not as easy as in others (PERL is very good at things like this for example). Excuse me for my rant on Refactoring, but it's a good skill to have, and I use it everyday for my job and on my personal projects. Eventually one can get good at it that the code written on the first try does not have to be refactored anymore, but don't be afraid to write it out the long way and look back afterwards. Good Luck, -Dizz |
|
|
|
|
|
#9 |
|
Expert Programmer
Join Date: Aug 2005
Location: Rotterdam, the Netherlands
Posts: 942
Rep Power: 4
![]() |
Dizz! You're back!
|
|
|
|
|
|
#10 |
|
Programmer
Join Date: Aug 2005
Location: 0x0010 * 0x0091 + 0x0004
Posts: 65
Rep Power: 4
![]() |
Well, what I meant was by putting all the numbers into a switch statement and then in the default you can have just a couple of if statments for the ranges. Or alternatively you could have listed all the numbers you wanted for a range with no break statements between them and have your code for that range after that. I'm not too crazy about either of those though. As Grumpy said, it depends on your definition of neat.
Those were just my observations from glancing at the code... If I were faced with this problem myself, I'd probably just do a lookup in a hard coded hash table (this doesn't reduce repetitive code, but I just think it's a better approach [assuming you only want a few selected key codes and not all]). Then again if we are stuck stictly with C, that would require writing your own hash table implementation or finding a decent one by somebody else. Perl could probably do this in 2 lines, lol, and even C++ would give you the option of the STL hash_set. If you wanted to just map all the key codes with characters, you could do it with a large array of strings eg: char *keycodes[] = {"VK_LBUTTON", "VK_RBUTTON ", "VK_CANCEL", "VK_MBUTTON ", "VK_XBUTTON1", "VK_XBUTTON2", NULL, "VK_BACK", "VK_TAB", "...etc..."};So both solutions I described don't actually reduce the code, but that doesn't mean they aren't good solutions. Infact, a hardcoded lookup table or an index into an array are both faster than branching into a function that performs calculations. Also, if you plan on maintaining this code, I'd go with whatever way you're more comfortable with. If you'd like me to elaborate more, I won't mind, just ask. * My example line from above was using the keycodes from this list: http://msdn.microsoft.com/library/de...alKeyCodes.asp
__________________
#if 0 /* in case someone actually tries to compile this */ <Jim_McNeat> Is there like a way to put a compiler in "Just trust me on that one" mode? |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| EXECryptor software protection | Jean5 | C++ | 35 | Oct 10th, 2006 8:10 PM |
| Little help | whoawhoayoyo | Assembly | 8 | Apr 18th, 2006 8:10 PM |
| How to post a question | nnxion | C++ | 10 | Jun 3rd, 2005 12:53 PM |
| How to post a question | nnxion | C++ | 0 | Jun 3rd, 2005 9:55 AM |
| How to post a question | nnxion | C | 0 | Jun 3rd, 2005 9:55 AM |