c++ switch case - c++

whenever I try to use switch with
case myvar:
where myvar is a char I get an error. Is it possible to make it work? Thanks

The expressions used in cases must be constant integral expressions that can be evaluated at compile time. So no. Unless myvar is a static const int of some sort, you can't make this work using case.
But what you can do is just use chained if statements.

In general, no. Cases must be compile-time constants.

It seems you want your switch cases to work based on char. As others said, your switch cases should be integral compile-time constants. And the below example works because, the corresponding ASCII values are retrieved for each case of char.
#include <iostream>
int main( void )
{
char myvar = 'a' ;
switch( myvar )
{
case 'a':
std::cout << "\n This Works !" << std::endl ;
break ;
default:
break ;
}
return 0 ;
}
Hope this helps !

Related

Constexpr is this correct behaviour?

I'm not sure this is correct behaviour. So I hadn't messed with constexpr before and want to make sure I'm not misunderstanding something about the spec. Testing in the way MSDN mentions to test it. If I put a breakpoint in the function and it gets skipped then it was evaluated at compile time. Is the behaviour below normal?
https://msdn.microsoft.com/en-us/library/dn956974.aspx
It only seems to work with optimization on period.
It only works if I set the value to a constexpr variable or in specific use cases that have NOTHING to do with the input variable.
So for some reason this works
constexpr unsigned int factorial(unsigned int n)
{
return n <= 1 ? 1 : n*factorial(n - 1);
}
constexpr unsigned int value = factorial(5);
std::cout << value << std::endl;
but this gets ran at run time
constexpr unsigned int factorial(unsigned int n)
{
return n <= 1 ? 1 : n*factorial(n - 1);
}
std::cout << factorial(5) << std::endl;
Seems kinda inconvenient to have to make a constexpr variable. It seems to work in some other specialized cases.
switch (fnv1a("Hello"))
{
case fnv1a("GoodBye"):
std::cout << "GoodBye" << std::endl;
break;
case fnv1a("Hello"):
std::cout << "Hello" << std::endl;
break;
default:
break;
}
This case initialized the case values to constants but the call in the switch statement doesn't evaluate to a constexpr and gets ran at run time.
Also equality operators seem to work for some reason so. This example only calls fnv1a once for the dynamic value.
void isValue(const char* str)
{
if (fnv1a(str) == fnv1a("Hello"));
std::cout << "Found it!" << std::endl;
}
I know MSVC has had some issues with compliance, but the behaviour not evaluating to a constant based on the use case rather then if the input is constant just seems odd to me.
The behavior you observe is correct. A constexpr function is required to be called at compile-time on constant expressions only. This includes the cases where the return value of a constexpr function is used as an initializer for constexpr variables, or as the value for a non-type template parameter.
In all other cases, the compiler is not required to evaluate the function at compile-time.

C++ Switch Statement

Recently (yesterday hah) I started learning C++. I am trying to make a simple calculator to practice. I used a switch statement in order to call upon the correct method(or is it function.. don't know the nuances of c++...) within the class; However, the code will not compile because I am using a string to define which case to use and also defining multiple classes to have the same result.
Here is the switch statement (I've only done addition to squash any bugs before I add the others):
switch(input){
case 'A': case 'a': case 'add': case 'Add':
cout << bo.addNum();
break;
default:
cout << "Not addition";
break;
}
The error I'm getting is the following:
basic.cpp:41:2: error: statement requires expression of integer type ('string'
(aka 'basic_string<char, char_traits<char>, allocator<char> >') invalid)
switch(input){
^ ~~~~~
basic.cpp:42:28: warning: multi-character character constant [-Wmultichar]
case 'A': case 'a': case 'add': case 'Add':
^
basic.cpp:42:40: warning: multi-character character constant [-Wmultichar]
case 'A': case 'a': case 'add': case 'Add':
^
Here is the code in its totality:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class beckahClass{
public:
void setNum(int num1, int num2){
a = num1;
b = num2;
}
int addNum(){
return a + b;
}
int subNum(){
return a - b;
}
int divNum(){
return a / b;
}
int multNum(){
return a * b;
}
private:
int a, b;
};
int main (void){
beckahClass bo;
string input;
int a, b;
cout << "Please specify the operation to preform by the following:\n A: add\nS: subtract\nM: Multiple\nD: divide\nEnter operation: ";
cin >> input;
cout << "Enter the two nums you want to preform your operation on: ";
cin >> a >> b;
bo.setNum(a, b);
switch(input){
case 'A': case 'a': case 'add': case 'Add':
cout << bo.addNum();
break;
default:
cout << "Not addition";
break;
}
return 0;
}
I also realize there are probably more efficient ways to use logic; because I'm just starting C++, I would greatly appreciate any critique. I had been looking up 'maps' before briefly and was wondering if this might be a good instance to use it in?
Thanks.
The reason is that C/C++ switch statement takes an int argument and do not support string as a type. Although it supports the notion of constant array. Also to mention that C/C++ switch statements are typically generated as branch tables. and it is not easy to generate a branch table using a string style switch.
In C++ the switch statement takes int as the argument.
Why you cannot string in switch and getting the below error?
basic.cpp:42:28: warning: multi-character character constant [-Wmultichar]
case 'A': case 'a': case 'add': case 'Add':
^
basic.cpp:42:40: warning: multi-character character constant [-Wmultichar]
case 'A': case 'a': case 'add': case 'Add':
The reason is because to generate the code for switch the compiler must understand what it means for two values to be equal. For int and enum, it is trivial and easy as they are constant values. But when it comes to string then it is difficult resulting in error.
In C++, the switch statement takes an int argument, and you are trying to use it with a string, which you can not do in C++.
In this specific case, I'd argue that what you're trying to do with your switch is far to simple and an if else block would be better (plus it'd actually work with string).
For example:
if(input == "A" || input == "a" || input == "add" || input == "Add") {
cout << bo.addNum();
} else {
cout << "Not addition";
}
Alternatively, as others have explained, you can switch on a char. As it turns out, you can access the individual characters of a string quite nicely. This method will have your switch statement work on the first character of the string you took as input.
switch(input[0]) {
case 'A': case 'a':
//stuff
break;
case 'S': case 's':
//stuff
break;
//and so on
default:
//stuff
break;
}
Just keep in mind that if you do it this way, you're going to enter case 'A': case 'a': whether the user types A, a, add, Add, addition, Addition, ADD, or Apples, or alphabet, or anything that starts with an a.
welcome to the world of C++, hope you enjoy.
Anyway let's talk about your problem. Firstly, methods and functions are synonymous.
Secondly, the single quote is used around a single character and double quotes are used around a string.
As in I have a string "Rabbiya" that consists of characters 'R','a','b','i','y'. Get it?
So you write "add" and 'a' like that in the code. Get it?
Also in the switch statement, you are using two DIFFERENT data types to check the condition, one is a character and the other is a string. "add" and "Add" are strings and 'a' and 'A' are chars. Which is wrong. Cases have the values that the argument of the switch statement can or may take. And the argument will obviously be a variable of a particular type, we will get to that.
The data types of the CASES must be the same as that of the ARGUMENT of switch - statement. Here's one thing you can do, instead of keeping char or string, you ask the user to identify the operation they perform using a number instead. Like
int a = 0;
cout << Enter: 1 for Add\n2 for Sub\n3 for Div\n4 for Sub: ";
cin >> a;
Then u use switch(a) statement with cases : case:1, case:2 and so on.
Here it will be good to have a default case too so that if an invalid input is provided, it generates an error message.
One more thing, in the class, you have two data members namely a and b. You will need to initialize these too!
Otherwise you will get errors or garbage values depending on the compilers. For this purpose, you write class constructors. What are constructors? They help you initialize data members of a class object.
For this purpose you should refer to this link: http://www.learncpp.com/cpp-tutorial/85-constructors/
http://www.learncpp.com/ will help you a lot throughout your course!
string input;
try changing it to
char input
As it was said C++ does not support using user-defined types (std::string is a user defined type) in the switch statement. It allows to use only integral types or enumerations. By the way the type char belongs to integral types. If you want to use strings in the switch statement then write your program in C#.
You can use any type c/c++ switch implementation. Your code will be like this:
SWITCH(input)
CASE("A") FALL
CASE("a") FALL
CASE("Add") FALL
CASE("add") FALL
cout << bo.addNum();
BREAK
DEFAULT
cout << "Not addition";
END

Using the comma operator in if statements

I tried the following:
if(int i=6+4==10)
cout << "works!" << i;
if(int i=6+4,i==10)
cout << "doesn't even compile" << i;
The first works fine while the second doesn't compile. Why is this?
EDIT: Now I know that the first one may not work as I intend it to. The value of i inside the if scope will be 1, not 10. (as pointed out by one of the comments on this question).
So is there a way to initialize and use a variable inside of an if statement at the same time similar to for(int i=0;i<10;i++)? So that you could produce something like if((int i=6+4)==10) (which will not compile) where the value of I inside the if scope would be 10?
I know you could declare and initialize I before the if statement but is there a way to do this within the statement itself?
To give you an idea why I think this would be usefull.
if(int v1=someObject1.getValue(), int v2=someObject2.getValue(), v1!=v2)
{
//v1 and v2 are visible in this scope
//and can be used for further calculation without the need to call
//someObject1.getValue() und someObject2.getValue() again.
}
//if v1==v2 there is nothing to be done which is why v1 und v2
//only need to be visible in the scope of the if.
The expression used as an initializer expression must be an assignment-expression so if you want to use a comma operator you must parenthesize the initializer.
E.g. (not that what you are attempting makes much sense as 6 + 4 has no side effects and the value is discarded and i == 10 uses the uninitialized value of i in its own initializer.)
if (int i = (6 + 4, i == 10)) // behaviour is undefined
Did you really mean something like this?
int i = 6 + 4;
if (i == 10)
When using the form of if that declares a new variable the condition checked is always the value of the initialized variable converted to bool. If you want the condition to be an expression involving the new variable you must declare the variable before the if statement and use the expression that you want to test as the condition.
E.g.
int i;
if ((i = 6 + 4) == 10)
I doubt seriously either example works to do anything useful. All that it does is evaluate to "true" in a complicated fashions.
But the reason the second one doesn't compile is that it's interpreted as two declarations: int i = 6+4; int i==10 and int i==10 isn't valid because that's an equality operator, not an assignment.
There are different alternatives, because what you want cannot be done (you cannot mix the comma operator with declarations). You could, for example, declare the variable outside of the if condition:
int i = 6+4;
if ( i == 10 ) ...
Or you can change the value of i to be 0 instead of 10 and recalculate i inside the else block:
if ( int i = (6+4)-10 ) ; else {
i += 10;
// ...
}
Much simpler, don't declare the variable at all, since you know the value inside the loop:
if ( (6+4)==10 ) {
int i = 10;
// ...
}
Unless of course you need the value of i in the case where it is not 10, in which case the second option is the most appropriate.
As of C++17 what you were trying to do is finally possible:
if (int i=6+4; i==10)
cout << "works, and i is " << i << endl;
Note the use of ; of instead of , to separate the declaration and the actual condition.

Declaring a data type dynamically in C++

I want to be able to do the following:
I have an array of strings that contain data types:
string DataTypeValues[20] = {"char", "unsigned char", "short", "int"};
Then later, I would like to create a variable of one of the data types at runtime. I won't know at compile time what the correct data type should be.
So for example, if at runtime I determined a variable x needed to be of type int:
DataTypeValues[3] x = 100;
Obviously this won't work, so how could I do something like this?
The simple answer is that you can't - types need to be known at compile time in C++. You can do something like it using things like boost::any or unions, but it won't be pretty.
you would have to use unions to achieve something like that, but handling unions is a very difficile matter, so you should choose a container class which wraps the union logic behind an interface like Boost.Variant or Qts QVariant
You can't. This kind of run-time metaprogramming is not supported in C++.
Everyone saying you can't do this in C++ is missing one obvious solution. This is where you could use a base class, you need to define the commonly used interface there, and then all the derived classes are whatever types you need. Put it in a smart pointer appropriate for a container and there you go. You may have to use dynamic type inference if you can't put enough of the interface in the base class, which is always frowned upon because it's ugly, but it's there for a reason. And dynamically allocating your types probably isn't the most efficient thing, but as always, it depends on what you're using it for.
I think you are really looking for a dynamically-typed language. Embed an interpreter if you must stick with C++!
Or you could implement something akin to the component model using interfaces to work with wrapped data. Start with the cosmic base class - IObject, then implement interfaces for IInteger, IDouble, IString, etc. The objects themselves would then get created by a factory.
Or you could just use void buffers with a factory... That's the age-old way of avoiding static typing in C/C++ (without the use of inheritance-based polymorphism). Then sprinkle in generous amounts of reinterpret_cast.
The closest you can get is with templates:
template<int i> class Data { };
template<> class Data<0> { typedef char type; }
template<> class Data<1> { typedef unsigned char type; }
template<> class Data<2 { typedef short type; }
template<> class Data<3> { typedef int type; }
Data<3>::Type x;
If you need something a lot more complex, Boost has a C++-Python bridge.
use union and make your own dynamic class.
the pseudocode like:
union all{
char c;
unsigned char uc;
short s;
int i;
};
class dynamic{
public:
char Type;
all x;
template <class T>
dynamic(T y){
int Int;
char Char;
unsigned char Uchar;
short Short;
if (typeof(y) == typeof(Char)){
Type = 1;
}else if (typeof(y) == typeof(Uchar)) {
Type = 2;
}else if (typeof(y) == typeof(Short)) {
Type = 3;
}else{
Type = 4;
}
switch (Type) {
case 1: x.c = y; break;
case 2: x.uc = y; break;
case 3: x.s = y; break ;
case 4: x.i = y; break ;
}
}
auto get() {
switch(Type) {
case 1: return x.c;
case 2: return x.uc;
case 3: return x.s;
case 4: retuen x.i;
}
}
//also make the operators function you like to use
} ;
however you should avoid using the dynamic type as possible as you can because it is memory inefficient
(in this example, each object of dynamic will takes 5 bytes)
it will also slow down your code (a bit).if in your example you want to use dynamic type of number variable only to reduce memory usage, you should forget about dynamic and just use the integer as the type (where integer can contain all of char, unsigned char, and short at once).
but if you want to use it because you need a dynamic type between something really different (example between an int and a string or a custom object), then it will be one of your option.
The only thing you can do is manually loop through the types and compare each individual one. There's also the potential to use a factory object here - but that would involve the heap.
Visual Basic's 'Variant' data type is what you are talking about. It can hold anything, primary data types, arrays, objects etc.
"The Collection class in OLE Automation can store items of different data types. Since the data type of these items cannot be known at compile time, the methods to add items to and retrieve items from a collection use variants. If in Visual Basic the For Each construct is used, the iterator variable must be of object type, or a variant." -- from http://en.wikipedia.org/wiki/Variant_type
The above page gives some insights on how variants are used and it shows how OLE is used in C++ for dealing with variants.
In your simple example, there would be little benefit in not simply using the widest type in the list as a generic container and casting to the smaller types when necessary (or even relying on implicit casts).
You could get elaborate with unions, classes, polymorphism, RTTI, Boost variants etc, but merely for a list of different width integers it is hardly worth the effort.
It seems to me you have a perceived problem for which you have invented an impractical solution for which you are now asking for help. You'd probably be far better off describing your original problem rather than making your solution the problem!
Also, don't forget that all the functions that must operate on this mysterious data type. Most functions are designed to use only one type, such as addition. The functions are overloaded to handle additional types.
How do you know at run-time what the variable type is?
The only way that come to mind now is the old C style where pointer to void was used like:
void *unkown;
Leter on you can assign any object to it like below:
unkown = (void *)new int(4);
If you know the type in the runtime then you may run specified function on such variable like below:
if(type==0) { // int
printf("%d\n", * ((int*)unkown) );
} else {
// other type
}
This way (casting void*) is used for example when malloc [, etc.] function is used.
I'm not saying it is a good practise when c++ is now much more developed.
Still agree with persons that saying it is not the best solution for your problem. But maybe after some redesign you may find it helpful.
You may find also interesting auto type since C++11.
http://en.cppreference.com/w/cpp/language/auto
I guess this reply would be a few years late. But for people who might happen to view this thread, a possible solution for this would be using variable templates. For example:
template<typename T>
T var;
template<typename T>
T arr[10];
int main() {
int temp;
var<int> = 2;
cout << var<int> << ' '; // this would output 2
var<char> = 'a';
cout << var<int> << ' '; // var<int> value would be a space character
cout << var<char> << ' '; // this would output 'a'
for(int i = 0; i < 10; i++) {
switch(i % 2) {
case 0:
arr<int>[i] = ++temp;
break;
case 1:
arr<char>[i] = 'a' + ++temp;
break;
}
cout << endl;
for(int i = 0; i < 10; i++) {
switch(i % 2) {
case 0:
cout << arr<int>[i] << ' ';
break;
case 1:
cout << arr<char>[i] << ' ';
break;
}
}
return 0;
}
The only problem with this, is that you would need to know the variable type of what is currently within the variable(e.g. storing in an integer array what the variable's "id"(the id you would give it), for a specific type). If you do not know or do not have a condition to know what is inside a specific variable or array location, I do not suggest using this.
I try to post it in here, but I had format error. I decided to put a link.
Any way you can use (long long) to store addresses because size of address is 8 and size of (long long) also is 8 then it can hold an address.
https://www.flatech.com.au/learning-material/programming/c/object-pointers-to-any-type

Enum C++ Get by Index

I was wondering in C++ if I have an enum can I access the value at the second index? For example I have
enum Test{hi, bye};
if I want 'hi', can I do something like Test[0], thanks.
Yes and no. If your Enum does not have explicit values then it is possible. Without an explicit values, enum values are given numeric values 0-N in order of declaration. For example ...
enum Test {
hi, // 0
bye // 1
}
This means that indexes just translates into a literal value.
Test EnumOfIndex(int i) { return static_cast<Test>(i); }
This of course does 0 validation at runtime and as soon as you add an explicit value it will break down. But it will work in the default scenario.
Unless specified otherwise, enums start numbering at 0, and increment by 1 each entry.
enum Test
{
hi, //0
bye, //1
count //2
}
You can cast an int to the type of the enum to get the value you want, such as:
(Test)0;
//or
Test(0);
Which lets you do things like:
for(int i = 0; i < count; i++)
{
DoSomething((Test)i);
}
Enumerations map names to values. In your case, (int)hi would have a value of 0, and (int)bye a value of 1. You can use a cast to get the value of hi:
int myInteger = 0;
Test myValue = (Test)myInteger;
Note, though, that myValue could be an invalid enum value if myInteger is out of range.
No, but you could cast from int
Test test = (Test)0;
Depends what you mean by "I want 'hi'".
If you mean you want the value, then you can get it by casting an int, as others have said.
Casting a numeric literal to enum type is usually pointless - if you know which value you're expecting, you can use the name. That way, the enum can change without breaking your code. I guess it's possible that something really weird is going on, where someone has created an enum, and documented what "3" means but not which enum value it is. But then you'd want to fix the API.
Casting an integer value known at runtime to enum might be helpful if you have serialized data. As long as you know it's in range of the enum, the result is defined.
If you mean you want the string "hi", then you can't have it. Unlike Java, in C++ the names of the values in enumerated types exist only at compile time, not at runtime, and only map in one direction.
Your best option might be something like this:
enum Test{hi = 0, bye};
Then you can simply refer to 'hi' with the number 0, and 'bye' with 1.
Although this really defeats the whole purpose of using an enumeration in the first place.
If you are excepting the value to returned as {Hi or bye} ,then you cannot get the value like that .
i would not suggest this to be done inorder to get the actual value but it can be used as hack
string return_value(int index)
{
string temp = "";
switch (index)
{
case 1: temp = "hi"
break;
case 2: temp = "bye";
break;
defualt :
break;
}
return temp;
}
typecasting to enum would again return the index but you can assign to some other enum variable
#include <iostream>
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
#define FOREACH_TEST(ID) ID(hi) ID(bye) ID(good)
enum TEST { FOREACH_TEST(GENERATE_ENUM) };
static const char * Test[] = { FOREACH_TEST(GENERATE_STRING) };
int main() {
printf("%s ",Test[0]);
printf("%s\n",Test[bye]);
for (int i=0; i<2; i++) printf("Test[%d] = %s\n", i, Test[i]); }
compile and run with: g++ enum-test.cpp -o enum-test; ./enum-test
output:
hi bye
Test[0] = hi
Test[1] = bye