My professor commonly asks my class how many statements there are in a given program, but I can't determine what he defines as a statement. It seems as though an if/else is one statement, and a for loop is one statement regardless of if there are other supposed statements within it. Are there any governing rules for this matter or is his definition of his own invention?
Thanks
For a precise definition of a statement:
Definition: A statement is a block of code that does something. An assignment statement assigns a value to a variable. A for statement performs a loop.
In C, C++ and C# Statements can be grouped together as one statement using curly brackets
{
statement1;
statement2;
}
As far as counting statements, I agree with the others, there's not much point. Counting Lines of Code (LOC) though, actually has some value and there's a lot of research that tries to relate the number of LOC to the workload of developers. It's possible that your instructor is having you count statements and thinking of statements as nothing more than a single LOC, which isn't quite the case.
Statements nest, i.e. smaller statements can be joined into larger statements, like compound statements. For this reason, the question about "how many statements are there in this program" are ambiguous. One has to define the counting method first. Without it the question of "how many" makes little sense.
Here is the function that handles statements parsing in JS alike language:
static void do_statement(CsCompiler *c )
{
int tkn;
switch (tkn = CsToken(c)) {
case T_IF: do_if(c); break;
case T_WHILE: do_while(c); break;
case T_WITH: do_with(c); break;
case T_DO: do_dowhile(c); break;
case T_FOR: do_for(c); break;
case T_BREAK: do_break(c); CsSaveToken(c,CsToken(c)); break;
case T_CONTINUE: do_continue(c); CsSaveToken(c,CsToken(c)); break;
case T_SWITCH: do_switch(c); break;
case T_CASE: /*do_case(c);*/ CsParseError(c,"'case' outside of switch"); break;
case T_DEFAULT: /*do_default(c);*/ CsParseError(c,"'default' outside of switch"); break;
case T_RETURN: do_return(c); break;
case T_DELETE: do_delete(c); break;
case T_TRY: do_try(c); break;
case T_THROW: do_throw(c); break;
case '{': do_block(c, 0); break;
case ';': ; break;
default:
{
CsSaveToken(c,tkn);
do_expr(c);
break;
}
}
}
As you see it includes things like for, while and also expressions (separated by ;)
In computer programming a statement
can be thought of as the smallest
standalone element of an imperative
programming language. A program is
formed by a sequence of one or more
statements. A statement will have
internal components (e.g.,
expressions).
More at Statement (Computer Science) at Wikipedia.
Related
Please note that this is a question about C++ language, not about how real or useful is the example I'm giving to illustrate it.
Imagine we have an enum in a namespace (or namespaces):
namespace SomeVeryLargeNamespaceExample {
enum class E {
One,
Two,
};
}
Now, we want to use it in the expression of a switch statement. Today I found that it is possible to add the using SomeVeryLargeNamespaceExample::E inside the switch statement, before the first case, reducing the code cluttering in the cases:
switch (e) {
using SomeVeryLargeNamespaceExample::E;
case E::One:
std::cout << "One\n";
break;
case E::Two:
std::cout << "Two\n";
break;
}
At first glance I thought it was some kind of "do this before any case statement" feature that I never learned about, but some expressions, such as a function call, are not executed (actually, gcc generates a warning statement will never be executed [-Wswitch-unreachable]). On the other hand, a variable declaration is possible (but not initialization).
My question is, what other statements are possible? Is this a feature or just a consequence of how switch is designed?
Note: I found this other question, but it is specific for C (so it doesn't mention the namespaces case, for example), and I'm curious about C++.
Any valid C++ statement is possible:
int a;
void foo(int x)
{
switch (x) {
a=4;
case 0:
a=1;
break;
case 1:
a=2;
break;
}
}
This is syntactically valid C++, and gcc has no issues compiling it and producing an executable. However the initial statement can never be reached, of course. Therefore every modern C++ compiler will give you a warning message:
t.C: In function ‘void foo(int)’:
t.C:8:18: warning: statement will
never be executed [-Wswitch-unreachable]
8 | a=4;
|
This question already has answers here:
Changing switch variable inside a case
(4 answers)
Closed 9 years ago.
Will it work/is it allowed to have a switch-case statement and change the key in a statement?
For example:
temp = 1
switch(temp)
{
case 1:
temp = 2;
//Do something with temp..
break;
}
The point of doing this is just that I don't have to create another variable, and it also makes sense to do so in my program. I am not asking about changing to another case in the switch-case statement, just if it's allowed to reuse the variable used as the key without any side effects.
This is perfectly fine. Virtually every state machine on the planet does something equivalent to what you do here.
Yes, you may do that. In fact, the following is common practice for writing lexers:
int c = getc(file);
switch(c)
{
case '+':
c = getc(file); // < `c` modified here!
switch(c)
{
case '+': return OP_INC;
default: ungetc(c, file); return OP_ADD;
}
...
}
Though it is not a good idea to use the same variable however the code will work because the branch is determined in the moment when the expression in the switch statement is evaluated.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
How could I explain how and when to use an if-statement vs. a switch statement in a "Choose Your Own Adventure" game?
The game is basically structured that if you put in a certain answer, it changes the flow or direction of the game. I've usually used if-statements with functions, but is that the most efficient and simple way to teach?
Thanks!
Edit: Wow, thank you SO much for so many great answers!! Just one last note: if you were a 13-year-old trying to grasp this concept without any previous knowledge of programming, how would you try to go about to understand it? Seriously, thanks so much for the help!!
There are (give or take) five different solutions to "I've received this input, what do I do now".
If/else if/else ... chain. Advantage is that you can use any expression that can be made into true or false. Disadvantage is that it can get pretty messy when you have a long chain of them.
Switch - great for "there are lots of almost similar things to do". Drawback is that the case labels have to be integer values (or char values, but not strings, floating point values, etc).
A table which makes the long if/else into a much simpler if(table[index].something) ...
Function pointers - sort of a table pointer variant - store a pointer to the function that does whatever you want to do if you move in that direction.
Objects using virtual functions. Again, a variant on the table solution, but instead of storing function pointers, we store objects with some member function that we can use to "do whatever you need to do".
The correct solution in this case is perhaps a combination/variation on one of the latter 3 - in my opinion, at least.
In this very scenario you've described an if statement is pretty much your best option since the code needs to compare an answer provided by the user with some pre-defined options.
Those options will most likely be strings. switch statements in C++ cannot work on strings. Thus a series of if statements will probably be simpler.
A switch statement can be used when the answer only consists of a number or a single character.
For example, the code piece for the game's main menu could look like this:
Console output:
Please select an action:
1) Start a new game.
2) Go to options screen.
3) Quit game.
code:
int userChoice = getUserInput();
switch(userChoice){
case START_NEW_GAME: //1
startGame(); break;
case OPTIONS: //2
showOptions(); break;
case QUIT: //3
exit(); break;
}
Use a switch statement when you're identifying cases of numeric or ordinal values.
switch (number)
{
case 1: DoSomething();
break;
case 2: DoSomethingElse();
break;
}
Use if, elseif and else for more complex conditions, like numeric ranges.
if (number > 0 && number <= 100)
{
DoSomething();
}
else if (number > 100 && number <= 1000)
{
DoSomethingElse()
}
else
{
NotifyOutOfRange();
}
switch statements are for speed. That's why they are only numeric. The compiler will attempt to make a lookup table for non-sparse (i.e. contiguous) value ranges which can improve performance significantly when the code is constantly being executed. This is because it only needs to do 1 comparison for a contiguous range to determine what piece of code to execute.
switch statements potentially can cause hard to find bugs since at the end of each case you need to specify a break or the execution will fall through to the next case.
if/else if/else statements are for more general use. They are in general, slower than an equivalent switch statement if there are many comparisons against the same value. However if that if chain of statements is not executed a lot and the chain is not that long, the performance improvement is negligible.
For more general usage, if is the way to go. In a CYOAG, you will not be needing speed. The slowest part of the game is the user.
To explain this to a 13 year old:
If you think that you will be executing a comparison on a single
integer (whole number) value over 1,000,000 or more times all at once and you need
it to be done as quickly as possible, use a switch statement.
Otherwise, doesn't matter. Just be careful when using a switch, because if you
don't have a break at the end of each case you will be scratching you head
trying to figure out what just happend? when two or more cases are executed.
You can use switch statements if you have too many "else if" statements :)
More seriously, if a player has many different choices (like picking from 26 different options (a-z), then switch is the way to go).
Well, you can't really put strings into switch/case. That leaves you with if. or you'll need to implement parser that reads strings, maps them to some enum type, and then uses said enum within switch/case.
However a better (more extensible) way would be to use map of function callbacks.
Something like this:
#include <map>
#include <string>
#include <iostream>
typedef void(*ActionCallback)();
typedef std::map<std::string, ActionCallback> ActionMap;
static bool running = true;
void leftAction(){
std::cout << "\"left\" entered" << std::endl;
}
void rightAction(){
std::cout << "\"right\" entered" << std::endl;
}
void quitAction(){
std::cout << "game terminated" << std::endl;
running = false;
}
int main(int argc, char** argv){
ActionMap actionMap;
actionMap["left"] = leftAction;
actionMap["right"] = leftAction;
actionMap["quit"] = quitAction;
while(running){
std::string command;
std::cout << "enter command. Enter \"quit\" to close" << std::endl;
std::cin >> command;
ActionMap::iterator found = actionMap.find(command);
if (found == actionMap.end())
std::cout << "unknown command " << command << std::endl;
else
(*found->second)();
}
return 0;
}
The big advantage of this approach is that you can change commands at runtime. Add new commands, remove them, etc. You could even go a bit further and add lisp/python/lua binding and make it even more extensible.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Debugging a switch statement in a C-based programming puzzle
I found the below C question on web:
#include<stdio.h>
int main()
{
int a=10;
switch(a)
{
case '1':
printf("ONE\n");
break;
case '2':
printf("TWO\n");
break;
defa1ut:
printf("NONE\n");
}
return 0;
}
Although I never used 'switch' of int '10' with char '1', I assume the worst would be a non-compile, or 'default' get executed. But no, on my VStudio, it goes directly to 'return 0'. Why is this?
By the way, although I had a few years of experience in C programming, my previous motto was to stick to MSDN or available code samples. Now with the interviews and questions, the solidness of my skill is definitely being challenged.
defa1ut is not the same as default.
That's an unused and unreachable label.
As SLaks pointed out, defa1ut is a user defined label (e.g. for a goto), not the switch keyword default. This is why you aren't seeing the expected output.
But to answer your other question, in C you can compare char literals with integers. In this case '1' has a numerical value of 49, assuming you are using the ASCII character set.
Assuming you meant default, and you are using ASCII, your code sample is equivalent to this:
int a=10;
switch(a)
{
case 49: // ASCII value of '1'
printf("ONE\n");
break;
case 50: // ASCII value of '2'
printf("TWO\n");
break;
default:
printf("NONE\n");
}
You are reading defa1ut as default; default is C language's keyword but defau1t is not. If you want the output to be simply "NONE" use default instead of defau1t.
Example:
switch( x )
{
case y:
if ( true )
{
break;
}
cout << "Oops";
break;
}
If the switch statement selects y, will Oops be written to the standard output?
- Is break in switch statements a dynamic keyword like continue which can be called under conditions or static like a closing bracket }?
break breaks out of an enclosing switch, while, for, or do ... while. It doesn't break out of an enclosing if or bare block. Pretty much exactly like continue.
It's certainly not part of the required syntax of a switch statement (like a close-brace is part of the syntax of blocks). break is a statement, essentially meaning "transfer execution to the point after the end of the innermost breakable construct".
No, Oops will not written out, the break jumps behind this statement.
You can use break statements conditionally just fine, you only have to watch out when you create nested statements that also support break (i.e. loops).
break is absolutely dynamic. So, if you write if (false) break; your Oops would be written out.
Think of break in this case as a goto end_of_switch.
No, it will not be printed in your case. break only breaks from switches and loops, not conditionals or functions or arbitrary enclosing scopes. Therefore, a more relevant question would be whether Oops is printed in this case:
switch( x )
{
case y:
for ( int i = 0; i < 10; ++i )
{
break;
}
cout << "Oops";
break;
}
And the answer here is yes, it will. The break will break out of the for, not the switch.
No. It would break out of the switch construct. "break" is used to come out of the innermost loop construct or switch construct. So, in your case the "oops" is not printed out on the screen. If you want that to happen, in your code, you could use if(false) instead of if(true).