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.
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;
|
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm modifying some existing code written in C++ that uses string pointers, but struggling to understand why I'm having so much difficulty using the toupper() function, or reducing the ASCII value by 32 to perform a case conversion. I have successfully achieved what I want, with minimal C++ knowledge, but I'd like to improve on the present code which — in order to simply prove a technical point — contains an if condition for every letter of the alphabet.
Other than my difficulties getting to grips with C++ syntax and rules, my attempt is working fine as I want.
The existing code defines 'buf' as follows:
static void c_write(Ldisc ldisc, const char *buf, int len)
{
from_backend(ldisc->frontend, 0, buf, len);
}
I then added the following, for each of 26 letters of the alphabet, in order to prove my point.
if (buf[0] == 97) buf="A";
if (buf[0] == 98) buf="B";
if (buf[0] == 99) buf="C";
if (buf[0] == 100) buf="D";
...and so on etc.
If I replace my 26 conditions with the following, then compilation fails.
if (buf[0]>=97 && buf[0]<=122)
{
buf[0]=buf[0]-32;
}
The message was "(376) : error C2166: l-value specifies const object"
I also tried using the toupper() function, but obtained unsatisfactory results there, either crashing the routine or returning a spurious value.
To the extent that it might help to understand the context in which buf[] is being used, the existing code contains the following working section.
switch (buf[0]) {
case CTRL('M'):
if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL);
else
ldisc->back->send(ldisc->backhandle, "\r", 1);
break;
case CTRL('?'):
case CTRL('H'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_EC);
break;
}
case CTRL('C'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_IP);
break;
}
case CTRL('Z'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_SUSP);
break;
}
default:
ldisc->back->send(ldisc->backhandle, buf, len);
break;
The problem is very simple, in this
static void c_write(Ldisc ldisc, const char *buf, int len)
const is a promise not to modify the string pointed at by buf. So obviously trying to convert it to upper case is not allowed. That's what your error "(376) : error C2166: l-value specifies const object" is trying to tell you.
It seems reasonable that a function whose (apparent) purpose is to write a string would not modify that string. So if you need to convert to upper case I would say that the correct place to do that is before you call c_write, not as part of c_write.
currently I am doing the following:
enum TC_ID {
CMD01 = 'C'*'M'*'D'*'0'*'1',
CMD02 = 'C'*'M'*'D'*'0'*'2',
..
};
Which works, but is going to be quite effortfull for a whole lot of commands :D
So, I am looking for a Macro, or inline function or something else which multiplies all the chars of a char array/string with a fixed size, so that I don't have to type them in manually in my code.
Is something like this possible?
Some unnecessary but maybe interesting information:
Well, this looks kinda stupid, why am I doing this you might ask ;)
My goal is to use this enum in a switch statement, which in the end is used to execute telecommands for my project.
The size of my telecommands is always 5.
So I am calculating some kind of very simple hash value which will be used inside the switch statement:
char *id // contains the Telecommand as a string
TC_ID hash = static_cast<TC_ID>(id[0]*id[1]*id[2]*id[3]*id[4]);
switch (hash) {
case (CMD01):
// execute funtion..
break;
case (CMD02):
// do something else
break;
default:
// unknown command
}
I know that instead of a switch I could just use a lot of if else statements and strcmp, but I don't want to because it's ugly :D
EDIT: Also, using an appropriate hash function would be much better.
However, how can this be implemented in an enumeration, so that I can still use my switch statement for the commands?
I think what I want is basically some kind of hash table which I can generate at the start for all command words and then make a switch over all of them.. but just how?
EDIT2: My compiler version is C++98
EDIT3: Workaround solution in comment in answer post
This works (C++11):
constexpr int multChars(const char* s /*string*/, int t = 1 /*tally*/){
return *s ? multChars(s+1, t*(*s)) : t;
};
//--------------------------------------------------------
//test it on a template (won't compile unless N is evaluated at compile time)
#include <iostream>
template<int N>
void printN() { std::cout<<N<<'\n'; }
int main(){
printN<multChars("ab")>();
return 0;
}
The ascii code of 'a' is 97 and the ascii code of 'b' is 98.
This returns 9506 as expected.
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.
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.