for loop with switch statements [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am relatively new to C/C++ and i was wondering how I could use for loop so I wouldn't have to make a bunch of switch statements I have already made the switch statement I just need help on integrating the for loop into it. Thank you.
#include <stdio.h>
#pragma warning(disable : 4996)
int main() {
char ch;
ch = getchar();
int f, a = 10, b = 20;
printf("ch = %c\n", ch);
switch (ch) {
case '+': f = a + b; printf("f = %d\n", f); break;
case '-': f = a - b; printf("f = %d\n", f); break;
case '*': f = a * b; printf("f = %d\n", f); break;
case '/': f = a / b; printf("f = %d\n", f); break;
default: printf("invalid operator\n");
}
}
the purpose of the program is to enter in either +,-,*,/ and then based on that input it will execute the case that was entered in so + would add a and be together.

Basically, you need to map operator characters to operations.
Your current code represents that mapping via execution flow control.
In C++ the standard library's map collection is a good choice for instead representing it as data, so that you don't even need to use a loop. In C an array of structs where each contains a char and a function pointer, can do the same job. However, you then have to define the functions yourself, because unlike the C++ standard library the C standard library doesn't provide convenient named functions for the arithmetic operations.
In a similar fashion, a Boolean state, whether something is true or false, can be represented as an execution position or as data, usually as a variable of type bool. What to choose is mainly engineering gut feeling. Sometimes representation via flow control is simplest and most clear, sometimes representation as data is simplest and most clear.
C++ example, mostly reproducing the given example code's effect, but with the mapping as data:
#include <iostream>
#include <functional>
#include <map>
using namespace std;
auto main() -> int
{
const map<char, function<int(int,int)>> op =
{
{ '+', plus<int>() },
{ '-', minus<int>() },
{ '*', multiplies<int>() },
{ '/', divides<int>() }
};
char ch;
cout << "Operator? "; cin >> ch;
cout << "ch = '" << ch << "'\n";
if( op.count( ch ) == 0 )
{
cout << "invalid operator\n";
}
else
{
const int a = 10;
const int b = 20;
cout << "f = " << op.at( ch )( a, b ) << "\n";
}
}
Corresponding C example, which does include a for loop as mentioned in the question:
#include <stdio.h>
int plus( int a, int b ) { return a+b; }
int minus( int a, int b ) { return a-b; }
int multiplies( int a, int b ) { return a*b; }
int divides( int a, int b ) { return a/b; }
typedef int(*Func_ptr)(int, int);
struct Mapping
{
char ch;
Func_ptr f;
};
const struct Mapping op[] =
{
{ '+', plus },
{ '-', minus },
{ '*', multiplies },
{ '/', divides }
};
const int n_ops = sizeof( op )/sizeof( *op );
Func_ptr op_at( char ch )
{
for( int i = 0; i < n_ops; ++i )
{
if( op[i].ch == ch ) { return op[i].f; }
}
return NULL;
}
int main()
{
int ch; // Note: type `int` to accommodate EOF value.
printf( "Operator? " ); ch = getchar();
printf( "ch = '%c'\n", ch );
if( op_at( ch ) == NULL )
{
printf( "invalid operator\n" );
}
else
{
const int a = 10;
const int b = 20;
printf( "f = %d\n", op_at( ch )( a, b ) );
}
}
C11, I think it was, introduced some machinery for effectively overloading functions so they can be used much like overloaded functions in C++. I don't remember much about and didn't use it here. I would suggest that if you need to handle different data types, just use different function names.
Note that the C example also compiles as C++, so both these examples are technically C++. However, the last example is in C style, using C idioms and C i/o, and does things that are unnecessary in C++. We usually just say that such code is C, not that it's C style; such code might not always compile as C++, because while C is largely a subset of C++ these are two different, separate languages: there is technically no such thing as C/C++.

i was wondering how I could use for loop so I wouldn't have to make a bunch of switch statements I have already made the switch statement I just need help on integrating the for loop into it.
A for loop is used to repeat a block of statements until a condition is met.
A switch statement is used for making a decision about which block of statements to run based on a given value, instead of using a bunch of if statements.
It doesn't make sense to replace a switch statement with a for loop. What does make sense is using a switch statement inside of a loop, to act on something that the loop generates, like asking for user input. For example:
#include <stdio.h>
#pragma warning(disable : 4996)
int main() {
int f, a = 10, b = 20;
char ch;
int finished = 0;
do {
ch = getchar();
printf("ch = %c\n", ch);
switch (ch) {
case '+': f = a + b; printf("f = %d\n", f); break;
case '-': f = a - b; printf("f = %d\n", f); break;
case '*': f = a * b; printf("f = %d\n", f); break;
case '/': f = a / b; printf("f = %d\n", f); break;
case 'q': finished = 1; break;
default: printf("invalid operator\n"); break;
}
}
while (!finished);
return 0;
}

Related

Make compiler assume that all cases are handled in switch without default

Let's start with some code. This is an extremely simplified version of my program.
#include <stdint.h>
volatile uint16_t dummyColorRecepient;
void updateColor(const uint8_t iteration)
{
uint16_t colorData;
switch(iteration)
{
case 0:
colorData = 123;
break;
case 1:
colorData = 234;
break;
case 2:
colorData = 345;
break;
}
dummyColorRecepient = colorData;
}
// dummy main function
int main()
{
uint8_t iteration = 0;
while (true)
{
updateColor(iteration);
if (++iteration == 3)
iteration = 0;
}
}
The program compiles with a warning:
./test.cpp: In function ‘void updateColor(uint8_t)’:
./test.cpp:20:25: warning: ‘colorData’ may be used uninitialized in this function [-Wmaybe-uninitialized]
dummyColorRecepient = colorData;
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
As you can see, there is an absolute certainty that the variable iteration is always 0, 1 or 2. However, the compiler doesn't know that and it assumes that switch may not initialize colorData. (Any amount of static analysis during compilation won't help here because the real program is spread over multiple files.)
Of course I could just add a default statement, like default: colorData = 0; but this adds additional 24 bytes to the program. This is a program for a microcontroller and I have very strict limits for its size.
I would like to inform the compiler that this switch is guaranteed to cover all possible values of iteration.
As you can see, there is an absolute certainty that the variable iteration is always 0, 1 or 2.
From the perspective of the toolchain, this is not true. You can call this function from someplace else, even from another translation unit. The only place that your constraint is enforced is in main, and even there it's done in a such a way that might be difficult for the compiler to reason about.
For our purposes, though, let's take as read that you're not going to link any other translation units, and that we want to tell the toolchain about that. Well, fortunately, we can!
If you don't mind being unportable, then there's GCC's __builtin_unreachable built-in to inform it that the default case is not expected to be reached, and should be considered unreachable. My GCC is smart enough to know that this means colorData is never going to be left uninitialised unless all bets are off anyway.
#include <stdint.h>
volatile uint16_t dummyColorRecepient;
void updateColor(const uint8_t iteration)
{
uint16_t colorData;
switch(iteration)
{
case 0:
colorData = 123;
break;
case 1:
colorData = 234;
break;
case 2:
colorData = 345;
break;
// Comment out this default case to get the warnings back!
default:
__builtin_unreachable();
}
dummyColorRecepient = colorData;
}
// dummy main function
int main()
{
uint8_t iteration = 0;
while (true)
{
updateColor(iteration);
if (++iteration == 3)
iteration = 0;
}
}
(live demo)
This won't add an actual default branch, because there's no "code" inside it. In fact, when I plugged this into Godbolt using x86_64 GCC with -O2, the program was smaller with this addition than without it — logically, you've just added a major optimisation hint.
There's actually a proposal to make this a standard attribute in C++ so it could be an even more attractive solution in the future.
Use the "immediately invoked lambda expression" idiom and an assert:
void updateColor(const uint8_t iteration)
{
const auto colorData = [&]() -> uint16_t
{
switch(iteration)
{
case 0: return 123;
case 1: return 234;
}
assert(iteration == 2);
return 345;
}();
dummyColorRecepient = colorData;
}
The lambda expression allows you to mark colorData as const. const variables must always be initialized.
The combination of assert + return statements allows you to avoid warnings and handle all possible cases.
assert doesn't get compiled in release mode, preventing overhead.
You can also factor out the function:
uint16_t getColorData(const uint8_t iteration)
{
switch(iteration)
{
case 0: return 123;
case 1: return 234;
}
assert(iteration == 2);
return 345;
}
void updateColor(const uint8_t iteration)
{
const uint16_t colorData = getColorData(iteration);
dummyColorRecepient = colorData;
}
You can get this to compile without warnings simply by adding a default label to one of the cases:
switch(iteration)
{
case 0:
colorData = 123;
break;
case 1:
colorData = 234;
break;
case 2: default:
colorData = 345;
break;
}
Alternatively:
uint16_t colorData = 345;
switch(iteration)
{
case 0:
colorData = 123;
break;
case 1:
colorData = 234;
break;
}
Try both, and use the shorter of the two.
I know there have been some good solutions, but alternatively If your values are going to be known at compile time, instead of a switch statement you can use constexpr with a static function template and a couple of enumerators; it would look something like this within a single class:
#include <iostream>
class ColorInfo {
public:
enum ColorRecipient {
CR_0 = 0,
CR_1,
CR_2
};
enum ColorType {
CT_0 = 123,
CT_1 = 234,
CT_2 = 345
};
template<const uint8_t Iter>
static constexpr uint16_t updateColor() {
if constexpr (Iter == CR_0) {
std::cout << "ColorData updated to: " << CT_0 << '\n';
return CT_0;
}
if constexpr (Iter == CR_1) {
std::cout << "ColorData updated to: " << CT_1 << '\n';
return CT_1;
}
if constexpr (Iter == CR_2) {
std::cout << "ColorData updated to: " << CT_2 << '\n';
return CT_2;
}
}
};
int main() {
const uint16_t colorRecipient0 = ColorInfo::updateColor<ColorInfo::CR_0>();
const uint16_t colorRecipient1 = ColorInfo::updateColor<ColorInfo::CR_1>();
const uint16_t colorRecipient2 = ColorInfo::updateColor<ColorInfo::CR_2>();
std::cout << "\n--------------------------------\n";
std::cout << "Recipient0: " << colorRecipient0 << '\n'
<< "Recipient1: " << colorRecipient1 << '\n'
<< "Recipient2: " << colorRecipient2 << '\n';
return 0;
}
The cout statements within the if constexpr are only added for testing purposes, but this should illustrate another possible way to do this without having to use a switch statement provided your values will be known at compile time. If these values are generated at runtime I'm not completely sure if there is a way to use constexpr to achieve this type of code structure, but if there is I'd appreciate it if someone else with a little more experience could elaborate on how this could be done with constexpr using runtime values. However, this code is very readable as there are no magic numbers and the code is quite expressive.
-Update-
After reading more about constexpr it has come to my attention that they can be used to generate compile time constants. I also learned that they can not generate runtime constants but they can be used within a runtime function. We can take the above class structure and use it within a runtime function as such by adding this static function to the class:
static uint16_t colorUpdater(const uint8_t input) {
// Don't forget to offset input due to std::cin with ASCII value.
if ( (input - '0') == CR_0)
return updateColor<CR_0>();
if ( (input - '0') == CR_1)
return updateColor<CR_1>();
if ( (input - '0') == CR_2)
return updateColor<CR_2>();
return updateColor<CR_2>(); // Return the default type
}
However I want to change the naming conventions of the two functions. The first function I will name colorUpdater() and this new function that I just shown above I will name it updateColor() as it seems more intuitive this way. So the updated class will now look like this:
class ColorInfo {
public:
enum ColorRecipient {
CR_0 = 0,
CR_1,
CR_2
};
enum ColorType {
CT_0 = 123,
CT_1 = 234,
CT_2 = 345
};
static uint16_t updateColor(uint8_t input) {
if ( (input - '0') == CR_0 ) {
return colorUpdater<CR_0>();
}
if ( (input - '0') == CR_1 ) {
return colorUpdater<CR_1>();
}
if ( (input - '0') == CR_2 ) {
return colorUpdater<CR_2>();
}
return colorUpdater<CR_0>(); // Return the default type
}
template<const uint8_t Iter>
static constexpr uint16_t colorUpdater() {
if constexpr (Iter == CR_0) {
std::cout << "ColorData updated to: " << CT_0 << '\n';
return CT_0;
}
if constexpr (Iter == CR_1) {
std::cout << "ColorData updated to: " << CT_1 << '\n';
return CT_1;
}
if constexpr (Iter == CR_2) {
std::cout << "ColorData updated to: " << CT_2 << '\n';
return CT_2;
}
}
};
If you want to use this with compile time constants only you can use it just as before but with the function's updated name.
#include <iostream>
int main() {
auto output0 = ColorInfo::colorUpdater<ColorInfo::CR_0>();
auto output1 = ColorInfo::colorUpdater<ColorInfo::CR_1>();
auto output2 = ColorInfo::colorUpdater<ColorInfo::CR_2>();
std::cout << "\n--------------------------------\n";
std::cout << "Recipient0: " << output0 << '\n'
<< "Recipient1: " << output1 << '\n'
<< "Recipient2: " << output2 << '\n';
return 0;
}
And if you want to use this mechanism with runtime values you can simply do the following:
int main() {
uint8_t input;
std::cout << "Please enter input value [0,2]\n";
std::cin >> input;
auto output = ColorInfo::updateColor(input);
std::cout << "Output: " << output << '\n';
return 0;
}
And this will work with runtime values.
Well, if you are sure you won't have to handle other possible values, you can just use arithmetic. Gets rid of he branching and the load.
void updateColor(const uint8_t iteration)
{
dummyColorRecepient = 123 + 111 * iteration;
}
I'm going to extend the Lightness Races in Orbit's answer.
The code I'm using currently is:
#ifdef __GNUC__
__builtin_unreachable();
#else
__assume(false);
#endif
__builtin_unreachable() works in GCC and Clang but not MSVC. I used __GNUC__ to check whether it is one of the first two (or another compatible compiler) and used __assume(false) for MSVC instead.

how to make a type that supports short or unsigned..etc modifiers c++

I am trying to make type in c++ and what am trying to do is:
here is an example:
this is a type i made called bbool.
class bbool
{
public:
bbool();
bbool(unsigned short int);
private:
bool x = false,
y = false,
z = false;
unsigned short int a, b;
void check(unsigned short int);
};
void bbool::check(unsigned short int c){
if ( c < 0 || c >= 3 ){
throw invalid_argument("Wrong value::Not 1, 2 or 3");
}
}
bbool::bbool(){
}
bbool::bbool(unsigned short int c){
check(c);
switch ( c )
{
case 0:
x = true;
break;
case 1:
y = true;
break;
case 2:
z = true;
break;
}
}
and what I want to be able to do is if possible
unsigned bbool x;
and to be able to define what the modifires unsigned or short or .. etc do. i found "that i must to make a group!!??" (not so sure what it means). and btw is the "unsigned typeA" different than "typeA" (not in value like (int x
positive or negative value or unsigned postive only) like if it have a different class)
thanks in advance and please forgive me if it is not a good question.

How to write Console terminal with C++ [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am studying for an exam and need your help.
I must write my own console terminal in C++, which must work in this way:
Example:
:>plus 5 7 "hit ENTER"
:>12
:>minus 10 12 "hit ENTER"
:>-2
:>combine Hello World "hit ENTER"
:>HelloWorld
:>run netstat "hit ENTER"
:>runs netstat
:>help
:>plus int1 int2
minus int1 int2
combine string1 string2
run ?????
:>exit
program exits
For main block I think it would be something like this
int main(void) {
string x;
while (true) {
getline(cin, x);
detect_command(x);
}
return 0;
}
The functions would be something like this
void my_plus(int a, int b) {
cout << a + b;
}
void my_minus(int a, int b) {
cout << a - b;
}
void my_combine(string a, string b) {
?????????????;
}
void my_run(?????????) {
???????????;
}
And the finally detect_command
void detect_command(string a) {
const int arr_length = 10;
string commands[arr_length] = { "plus", "minus", "help", "exit" };
for (int i = 0; i < arr_length; i++) {
if (a.compare(0, commands[i].length(), commands[i]) == 0) {
?????????????????????;
}
}
}
????? - means I don`t know what to write.
Help to make this program work.
Thanks.
I'm going to use the minus operation as an example...
Make a structure like so:
struct cmd_struct {
const char *name;
void (*func) (void *data);
};
Since your function parameters aren't the same, you gotta make a structure for each, e.g.:
struct minus_op {
int rhs;
int lhs;
};
And use the cmd_struct as an array, like so:
static cmd_struct commands[] = {
{ "minus", &my_minus },
...
};
my_minus would then be:
void my_minus(void *data) {
struct minus_op *mop = data;
... do the computation and return ...
}
And loop through it to detect the command used:
for (int i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
if (strcmp(commands[i].name, a) == 0) {
... prepare the data ...
commands[i].func(data);
}
}
Side Note: In order to get the function parameters from command line, have a splitter, e.g. a white space. Use a vector for this and pass that vector to detect_command
Do also note: Get rid of the void param used in this example and use a char **argv and int argc like in main(). argv would be the arguments, and argc would be the number of arguments passed to the function. e.g. if you say to the program:
>> minus 5 1
Then argc should be 2 (the 5 and the 1) and argv[0] = "5" and argv[1] = "1".
Now that you know the idea behind it, implementing a more flexible version is left to you.
Call a respective function to handle each word. For example:
enum commands {
PLUS,
MINUS,
HELP,
EXIT
//....
};
int detect_command(string a) {
const int arr_length = 10;
string commands[arr_length] = { "plus", "minus", "help", "exit" };
for (int i = 0; i < arr_length; i++) {
if (a.compare(0, commands[i].length(), commands[i]) == 0)
return i;
}
return -1; //unknow word
}
Give the string to detect_command() the function return the respective integer to enum commands (that's our i value) or -1 if word is unknow. Then you can write a function like this to use and process the value determined by detect_command():
void run_command(int cmd)
{
switch(cmd) {
case PLUS: run_plus(); break;
case MINUS: run_minus(); break;
// and so on to all comamnds available
default: error("unknow command");
}
}
each function run_*() should continues the command parsing according to own rules, i.e, the "plus" command should be follow by one integer, one white-space and then another integer, right? run_plus() must validate it and then compute the result. e.g.:
//pseudo code
void run_plus()
{
//input here is one after "plus" word
//here we must validate our valid input: two digits split by a white-spaces
int x = parse_digit();
check(white-space);
int y = parse_digit();
int r = x + y;
display_result(r);
}
NOTE: I'm not a C++ programmer; I did detect_command() code modification to you get my idea. I even don't know if it will compile in C++ for the mismatch types.

Bind a char to an enum type

I have a piece of code pretty similar to this:
class someclass
{
public:
enum Section{START,MID,END};
vector<Section> Full;
void ex(){
for(int i=0;i<Full.size();i++)
{
switch (Full[i])
{
case START :
cout<<"S";
break;
case MID :
cout<<"M";
break;
case END:
cout<<"E";
break;
}
}
}
};
Now imagine I have much more enum types and their names are longer....
well what i get is not a very good looking code and i was wondering if it possible to bind a specific char to an enum type and maybe do something like this:
for(int i=0;i<Full.size();i++)
{
cout<(Full[i]).MyChar();
}
Or any other method that could make this code "prettier".
Is this possible?
Unfortunately there is not much you can do to clean this up. If you have access to the C++11 strongly typed enumerator feature, then you could do something like the following:
enum class Section : char {
START = 'S',
MID = 'M',
END = 'E',
};
And then you could do something like:
std::cout << static_cast<char>(Full[i]) << std::endl;
However, if you do not have access to this feature then there's not much you can do, my advice would be to have either a global map std::map<Section, char>, which relates each enum section to a character, or a helper function with the prototype:
inline char SectionToChar( Section section );
Which just implements the switch() statement in a more accessible way, e.g:
inline char SectionToChar( Section section ) {
switch( section )
{
default:
{
throw std::invalid_argument( "Invalid Section value" );
break;
}
case START:
{
return 'S';
break;
}
case MID:
{
return 'M';
break;
}
case END:
{
return 'E';
break;
}
}
}
In a situation like this you could be tricky and cast your chars.
enum Section{
START = (int)'S',
MID = (int)'M',
END = (int)'E'
};
...
inline char getChar(Section section)
{
return (char)section;
}
I think the best solution in this case would be to use a map:
#include <iostream>
#include <map>
class someclass
{
public:
enum Section{START = 0,MID,END};
map<Section,string> Full;
// set using Full[START] = "S", etc
void ex(){
for(int i=0;i<Full.size();i++)
{
cout << Full[i];
}
}
};

Using a function call in a case statement label

Can you have a function call as a case statement label. For instance:
char x
switch(x)
{
case isCapital():
capitalcount++;
break;
case isVowel():
vowelcount++;
break;
.
.
.
.
.
}
Is this permitted within C++?
The value in a case label needs to be a constant expression. That is, the answer to your immediate question is: yes, you can call certain functions in a case label. However, not the ones you tried to call. You can have multiple labels refer to one group of statements, though:
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
do_vowels();
break;
I know this doesn't answer your question per se, but you might try coding it like this....
capitalcount += isCapital(x);
vowelcount += isVowel(x);
The boolean return type of the isXXX() functions would get promoted to an int and added to the counts as either 0 (false) or 1 (true).
First of all: in your desired code isCapital and isVowel should be not functions (and not a function call, definitely), but functors -- because to check a value they have to receive it via parameters...
anyway your code is not possible in C++... but can be simulated with a sequence of pairs of functions: predicate + effect. Predicate have to take some parameter and respond with a boolean. Effect will do smth if predicate is true. To simulate break and fallback to next case (i.e. when no break in a case) effect function also have to return a boolean.
Sample code may look like this:
#include <cctype>
#include <functional>
#include <iostream>
#include <vector>
int main(int argc, char* argv[])
{
typedef std::vector<
std::pair<
std::function<bool(char)> // predicate
, std::function<bool()> // effect: return true if `break' required
>
> case_seq_t;
unsigned digits = 0;
unsigned upper = 0;
unsigned lower = 0;
unsigned total = 0;
unsigned other = 0;
case_seq_t switch_seq = {
{
// predicate lambda can be replaced by std::bind
// in this simple case... but need to change param type.
// std::bind(&std::isdigit, std::placeholders::_1)
[](char c) { return std::isdigit(c); }
, [&]() { digits++; return true; }
}
, {
[](char c) { return std::islower(c); }
, [&]() { lower++; return true; }
}
, {
[](char c) { return std::isupper(c); }
, [&]() { upper++; return true; }
}
// `default` case
, {
[](char c) { return true; }
, [&]() { other++; return true; }
}
};
for (int i = 1; i < argc; i++)
for (int pos = 0; argv[i][pos]; pos++)
for (const auto& p : switch_seq)
if (p.first(argv[i][pos]))
if (p.second())
break;
std::cout << "digits=" << digits << std::endl;
std::cout << "upper=" << upper << std::endl;
std::cout << "lower=" << lower << std::endl;
std::cout << "other=" << other << std::endl;
return 0;
}
Not so simple as switch but (IMHO) obvious enough... and maybe, in some real cases, have better flexibility (and probably maintainability) :)