Working with mathematical operations received as input - c

Let's say I'd like to receive two mathematical operations from a user (e.g. + - %) and calculate numbers accordingly. Let's also say I can use one if/else statement to determine precedence (and that all operations have different precedences).
I have several ideas in mind for implementation, and would like feedback regarding which is considered "better" coding (clearer, more efficient, etc.).
I could do something like this:
if (firstOperator >= secondOperator){
switch (firstOperator){
case '+':
switch (secondOperator)
// insert all 6 possible cases
case '-':
switch (secondOperator)
// insert all 5 possible cases
...
...
}
else{
// same idea as above
}
Or I could simply hard-code all options by creating one switch for every option of firstOperation, and nest a second switch in each of those cases for all possible secondOperation.
The two approaches are different, and I have one or two more. I would have thought that the first is more "correct" and elegant, but it actually results in more lines of code than the "brute-force" all-out second option.
I would love to hear any input regarding this kind of coding.
Note: I'm talking about only very basic C programming (i.e. without using other data structures like stacks, etc. Just the basic if/else, switch, loops, etc.

Here's how I would have done it, but it depends on your first and second operations being independently handled (which I think should be possible if what you are doing is an expression evaluator). In my example, I assume there is a queue holding the arguments that were parsed in the order they were parsed.
if (firstOperator >= secondOperator) {
handle(firstOperator);
handle(secondOperator);
} else {
// Assuming something like 1 + 2 * 3, with 1 2 3 in the queue:
//
// tmp = dequeueArg() makes the queue: 2 3
// handle('*') makes the queue: 6
// pushFront(tmp) makes the queue: 1 6
// handle('+') makes the queue: 7
//
int tmp = dequeueArg();
handle(secondOperator);
pushFront(tmp);
handle(firstOperator);
}
void handle(Op operator)
{
int x = dequeueArg();
int y = dequeueArg();
switch (operator) {
case '+': pushFront(x+y); break;
case '-': pushFront(x-y); break;
case '*': pushFront(x*y); break;
case '/': pushFront(x/y); break; // Maybe check for 0
case '%': pushFront(x%y); break; // Maybe check for 0
case '&': pushFront(x&y); break;
etc...
}
}
What I wrote here probably will not work as a general infix parser with precedence. It's more an example of how to not use O(N^2) nested case statements.

Related

Last break in switch unnecessary?

I was musing over a switch statement I had written for 4 mutually exclusive cases. I inserted a break statement at the end of each case, because I didn't want to do the test again after one case or another had been successful.
Here's the question, though. What, if anything, does the last break do? If the test case 43 succeeds, the break terminates the case, but if there's no break, the default shouldn't run, and so there's no wasted test anyway.
Here's the code:
switch(telemetry) {
case(40):
printf("\nHouse Telemetry #%i \n", psc);
break;
case(41):
printf("\nNav Telemetry #%i \n", psc);
break;
case(42):
printf("\nDownhill Telemetry #%i \n", psc);
break;
case(43):
printf("\nRealTime Telemetry #%i \n", psc);
break; // what do I do?
default:
printf("\nCommand ID not recognized\n");
}
Perhaps one of you compiler gurus can advise me.
If you did not have the break; in case 43, it would fall through to the default case, and also execute the printf("\nCommand ID not recognized\n");.
Why do you think the default would not run? switch-case will continue execution until it encounters a break statement, and this includes the default section.
The break therefore is required for the desired behavior.
Putting a break; on the very last element of a switch-case (whether it is default or case) is optional, as it would stop execution that is coming to an end anyway.
I've encountered programmers who feel both ways about it: That there should not be an extra break at the very end of the block because it is not necessary, or that there should be one for consistency, and on the possibility that the sections get re-arranged in the future.
A switch statement is not a language construction that divides codes into separate cases. It is a computed “go to” statement: Based on the switch expression, it causes program control to jump to one of the labels.
Once that jump is completed, the switch does not exercise any further control over execution. It does not separate cases from one another or insert jumps or returns at the end of each case. Therefore, if you want control to leave the code for one case and not flow into the following code for another case, you must insert a break or other instruction that affects program control (such as return).
This characteristic of switch statements makes possible uses such as:
switch (letter)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf("Vowel.\n");
break;
default:
printf("Consonant.\n");
break;
}
Observe there are five case labels using one section of code. If the switch automatically separated them, the first four would be empty; nothing would be done for them when letter was a, e, i, or o.
Another example is where one case does some preparation work and then falls into another case, such as:
switch (operation)
{
case Subtract:
b = -b;
case Add:
result = a+b;
break;
case Multiply:
result = a*b;
break;
}
Here the Add case adds two numbers, and the Subtract case works by negating b and then continuing into the code for the Add case. This could not work if the switch automatically separated cases. (This is a simplified example, of course.)
The break keyword in each case indicates the end of a particular case. If we do not put the break in each case then even though the specific case is executed, the switch in C will continue to execute all the cases until the end is reached. This should not happen; hence we always have to put break keyword in each case. Break will terminate the case once it is executed and the control will fall out of the switch.

Is there any better implementation for this switch case construct?

I'm working on an embedded system where a register hast to be accessed and after that to be incremented to achieve the result I'm looking for, since the machine is notifying and configured to react on my access and changing or not changing the flag. So the switch's argument has to be kept as it is, since it would otherwise change the behaving of the embedded system.
But there may occur a situation where I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch.
(More indepth I'm converting a sequence of analog values to digital values conversions step by step. The index is used to stay synchronized with the current conversion and relating it with the corresponding case to handle the figure correct. There may occur a state in which the index desynchronisizes to the current conversion so the sequence of conversions must be run through without any of the cases getting invoked (to prevent setting wrong data) untill the sequence is finished and the resynchroinisation can get performed)
The way I'm currently doing this is this:
switch (RunIndex++)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
if (RunIndexSyncedWithADCensured == false)
{
break;
}
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
This construct does the job but it looks like it is a bit controversial and I don't feel well by considering about committing this into productinal code.
So is there a better looking way to achieve the same, without the need of additional variables or assignements?
note:
Also it may be relevant, that this is in the first part of a interupt function consisting of 2 parts.
The first part handles what has to happen if() a conversion is finished. The second part, what has additional to be done if() this conversion also ended the sequence. So it is no option to simply return from the function without getting into the second part. and there is currently no loop structure where an if(...)break; may break out. (What is also the reason why I'm putting the if inside the switch scope, as it is at least by standard a valid way to break out.)
Firstly, the if() inside switch() will never be executed.
Consider the below code snippet:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 2;
switch(i) {
if (i == 2) {
printf("I M HERE\n");
}
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}
return 0;
}
For your code: you expect the string I M HERE to be printed. But that is not the case.
The output for the above code snippet is:
2
No statements before case/default(switch constructs): is executed inside switch
Now to answer for
I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch
Just move the if() outside to the switch().
if (RunIndexSyncedWithADCensured) {
switch (RunIndex++) {
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
/* Other cases here */
default:
RunIndex = 0;
break;
}
} else
RunIndex++;
Why not save the value first and then increment it and use the saved value in the switch? By the way this also includes two accesses, first to read the value from RunIndex and the second to increment it.
int runIndex = (RunIndex++);
if (RunIndexSyncedWithADCensured )
{
switch (runIndex)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
}
Since you are using adjacent index numbers, you could make an array of function pointers to replace the switch. That's what the optimizer will turn the switch into anyhow. So instead of your obscure switch, you get this:
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[RunIndex](RawData);
}
RunIndex++;
if (RunIndex > MAX)
{
RunIndex = 0;
}
Completely unrelated to the switch statement design: in case RunIndex is a sensitive volatile variable such as some hardware register, then you shouldn't use it directly in any form of computations. Make a copy of it:
volatile int RunIndex;
...
int index = RunIndex; // read from RunIndex
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[index](RawData);
}
index++;
if (index > MAX)
{
index = 0;
}
RunIndex = index; // write to RunIndex
This is standard practice for all such volatile variables.

optimizing switch case code

I have below switch case in my code.
switch(condition)
case 'A' :
//Code part A
break;
case 'B' :
//Code part A
//Code part B
break;
case 'C' : //Some code
break;
code Part A is repeated in both case 'A' and case 'B'. I want to avoid duplication of code.
If we use fall though then we need to add an if condition for case B. Is this the only way for avoiding repetition of code?
If the order is not important, you can simply do:
switch (condition)
{
case 'B':
// Code part B
// no break
case 'A':
// Code part A
break;
...
}
A case 'B' will continue to execute through the case 'A' code because you didn't call a break.
Manipulating a switch statement to reduce duplication of code may work at first, but then you may add additional cases to the switch later, which may break that cleanness of that optimization. For example:
switch(condition)
case 'A' :
// Code part A
break;
case 'B' :
// Code part A
// Code part B
break;
case 'C' :
// Code part C
break;
case 'D' :
// Code part A
// Code part D
break;
Suddenly an optimization which seemed nice at the time, starts to become difficult to maintain, difficult to read and error prone.
Having already determined that there is common code, the cleanest response in my view is to write functions to perform the common code and call from each case. Going forward, this will continue to be maintainable.
Unfortunately, that's the only way, short of defining a function for partA.
You can reduce nesting by exiting the switch from inside the combined case label to make the code look a little more uniform:
switch (someValue) {
case 'A':
case 'B':
// Code part A
if (someValue == 'A') break;
// Code part B
break;
case 'C':
break;
}
This lets your part A and part B code have the same level of nesting.
Can "//Code part B" be executed before "//Code part A"? If so, you could just reorder them and let it fall through without an if condition.
I don't think there's much else to do, otherwise. One of the reasons for the creation of object-oriented languages was avoiding the duplication of code you have in imperative languages.

is it possible to do an OR in a case statement?

I want to do something like:
case someenumvalue || someotherenumvalue:
// do some stuff
break;
Is this legal in C?
The variable that I am doing a switch on is an enumerated list data struct.
You can rely on the fact that case statements will fall-through without a break:
case SOME_ENUM_VALUE: // fall-through
case SOME_OTHER_ENUM_VALUE:
doSomeStuff();
break;
You can also use this in a more complicated case, where both values require shared work, but one (or more) of them additionally requires specific work:
case SOME_ENUM_VALUE:
doSpecificStuff();
// fall-through to shared code
case SOME_OTHER_ENUM_VALUE:
doStuffForBothValues();
break;
Yes, you can simply skip the break in the first case to achieve the fall-through effect:
switch (expr) {
case someenumvalue: // no "break" here means fall-through semantic
case someotherenumvalue:
// do some stuff
break;
default:
// do some other stuff
break;
}
Many programmers get into the trap of fall-through inadvertently by forgetting to insert the break. This caused me some headaches in the past, especially in situations when I did not have access to a debugger.
you need:
case someenumvalue:
case someotherenumvalue :
do some stuff
break;
You can use fallthrough to get that effect:
case someenumvalue:
case someotherenumvalue :
do some stuff
break;
A case statement like a goto -- your program will execute everything after it (including other case statements) until you get to the end of the switch block or a break.
As others have specificied, yes you can logically OR things together by using a fall through:
case someenumvalue: //case somenumvalue
case someotherenumvalue : //or case someothernumvalue
do some stuff
break;
But to directly answer your question, yes you can do a logical, or bit-wise or on them as well (it's just a case for the result of the operation), just be careful that you're getting what you'd expect:
enum
{
somenumvalue1 = 0,
somenumvalue2 = 1,
somenumvalue3 = 2
};
int main()
{
int val = somenumvalue2; //this is 1
switch(val) {
case somenumvalue1: //the case for 0
printf("1 %d\n", mval);
break;
case somenumvalue2 || somenumvalue3: //the case for (1||2) == (1), NOT the
printf("2 %d\n", mval); //case for "1" or "2"
break;
case somenumvalue3: //the case for 2
printf("3 %d\n", mval);
break;
}
return 0;
}
If you choose to do the second implementation keep in mind that since you're ||'ing things, you'll either get a 1 or 0, and that's it, as the case.

For larger switch case statements, is it better to separate them?

Quick question. For example, working with a some-what larger case of ~1000 options: which is the 'best' method? I'm not specifically wanting straight up faster results.
switch (foo) {
case 0:
// code ...
break;
// One, two, skip a few...
case 1000:
// code ...
}
or something that splits possible results so it can quickly find the proper case statement. Similar too:
if (foo < 101) {
if (foo < 51)
switch (foo) {}
else
switch (foo) {}
} else if (foo > 100 && foo < 201) {
// skipped for convenience
} else if (foo > 900) {
if (foo < 951)
switch (foo) {}
else
switch (foo) {}
}
I imagine the second method is much faster for the larger numbers, but the first method also seems it may be able to breeze through it since it's not constantly checking statements. Is one of these methods frowned upon or is there a better method? This is for C, but I am interested in knowing its consistency with other languages. Thanks!
switch statements can be incredibly fast if the compiler implements them using jump tables, but this is only possible on special sequence of cases, and may not be practical it really depends on the possible cases. The compiler may or may not use jump tables, I did find this http://blog.jauu.net/2010/06/15/GCC-generated-Switch-Jump-Tables/ which was kind of interesting.
JUMP tables can be incredibly fast, since it just calculates the offset and jumps to the appropriate address.
GCC does have -fno-jump-tables which does disable it completely.
Sometimes you can build your own jump table, using arrays of function pointers, and special indices, this can make your code incredibly fast but its not practical in all cases, imagine you had a switch and in every case you would call a function, you could build an array of function pointers, set a default function just to be safe, then instead of a switch you would simply do fun_table[indice](); I did this once for my own virtual machine.
I think switch statements are often interpreted as goto's in the underlying assembly language, which would make the first method significantly faster.
This seems to support that, although it isn't exactly proof: http://en.wikibooks.org/wiki/Optimizing_C%2B%2B/Writing_efficient_code/Performance_improving_features#Case_values_of_switch_statements
I believe that the switch statement is better, at least from a code readability standpoint (and maybe from a speed standpoint since it's only picking out one block to run as apposed to have to evaluate multiple conditions, as in the second example.)
Is it not recommended that any function should fit onto about 1.5 screens, so such a huge switch statement will not fit this bill. To overcome this have a dispatch table.All you have to do is index into the array to find the appropriate function to call.
I'm posting this just for information purpose, since samy.vilar already gave the most elegant solution with the function array. If you use GCC, it understands case range. This code would eventually behave in quite similar way as your second solution, resulting in some binary-tree code path (assuming there is no compiler optimization).
int nested_switch(int i)
{
switch (i) {
/* i is in the 1..10 range */
case 1 .. 10:
switch (i) {
/* i is in the 0..5 range */
case 1 .. 5:
switch (i) {
case 1:
break;
case 2:
break;
...
case 5:
break;
}
case 5 .. 10:
switch (i) {
case 6:
break;
case 7:
break;
...
case 10:
break;
}
}
/* i is in the 11..20 range */
case 11 .. 20:
switch (i) {
...
}
}
return 0;
}

Resources