How to avoid multiple chain of if else - c

Hi I have a piece of code as below, I want to avoid multiple if else, is there a better approach for this:
if(strcmp(somename, "some") == 0)
{
fun();
}
else if(strcmp(somename,"some1") == 0)
{
fun();
}
else if(strcmp(somename,"some2") == 0)
{
fun();
}
else if(strcmp(somename,"some3") == 0)
{
fun();
}

You can use a pointer to pointer and a loop:
const char *ap[] = {"some", "some1", "some2", "some3", NULL};
const char **p = ap;
while (*p) {
if (strcmp(somename, *p) == 0) {
fun();
break;
}
p++;
}

Create a map (ordered or unordered) mapping values for somename to std::function instances to call.

You can try a simple approach using switch cases. For example, you can use it like
switch(somename) {
case "some1" :
fun1();
break;
case "some2" :
fun2();
break;
case "some3" :
fun3();
break;
default :
//some default case
}
also you can use str2int in c++11 in case switch does't work with strings well like
switch(str2int(somename)) {
case str2int("some1") :
fun1();
break;
case str2int("some2") :
fun2();
break;
case str2int("some3") :
fun3();
break;
default :
//some default case
}

Related

How to do switching between two diffrent swich statements using C?

I have written a c code for switching between two different switch statements,
but I am looking for a more generic solution, meaning without using state variable and while loop, or jump from one switch statement to another switch statement.
I want some suggestion or key input from you.
Thank you and please excuse my poor English.
#include <stdio.h>
int main()
{
unsigned char state,state1;
enum
{
Add,Sub,Mul,Div,START,STOP
}Arith_Op;
enum
{
Add1,Sub1,Mul1,Div1,START1,STOP1
}Arith_Op1;
Arith_Op = Add;
Arith_Op1 = Add1;
state = START;
while (state != STOP)
{
switch(Arith_Op)
{
case Add :
printf("Add\n");
Arith_Op = Sub;
break;
case Sub :
printf("sub\n");
Arith_Op = Mul;
break;
case Mul :
printf("mul\n");
Arith_Op = Div;
break;
case Div :
printf("div\n");
Arith_Op = STOP;
break;
default :
printf("default\n");
state = STOP;
state1 = START1;
break;
}
}
printf(" state out of while and Switch case ");
while (state1 != STOP1)
{
switch(Arith_Op1)
{
case Add1 :
printf("Add1\n");
Arith_Op1 = Sub1;
break;
case Sub1 :
printf("sub1\n");
Arith_Op1 = Mul1;
break;
case Mul1 :
printf("mul1\n");
Arith_Op1 = Div;
break;
case Div1 :
printf("div1\n");
Arith_Op1 = STOP1;
break;
default :
printf("default1\n");
state1 = STOP1;
break;
}
}
printf(" state 1 out of while and Switch case ");
return 0;
}

Why my double pointer is null? [duplicate]

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 5 years ago.
this is my code:
void n(FILE *f, int *pocet, char **spz) {
int i = 0;
int pocett = 0;
char* r = (char*)malloc(50 * sizeof(char));
if (spz != NULL) {
free(spz);
}
spz = (char**)malloc(sizeof(char*));
if (f == NULL) {
printf_s("File is null");
return;
}
while (fgets(r, 50, f)) {
switch (i % 6) {
case 1: {
if (i == 1) {
spz[0] = (char*)malloc(50 * sizeof(char));
spz[0] = r;
}
else {
spz = (char**) realloc(spz,((i - 1) / 6 + 1) * sizeof(char*));
spz[((i - 1) / 6)] = (char*)malloc(50 * sizeof(char));
strcpy_s(spz[(i-1)/6], 50 ,r);
}
break;
}
case 5: {
pocett++;
break;
}
}
i++;
}
*pocet = ++pocett;
}
and I call my function as this:
int main() {
FILE *f = NULL;
int c;
int pocet = 0;
int* p = &pocet;
char** spz = NULL;
while ((c = getchar()) != 'k') {
getchar();
switch (c) {
case 'v': {
v(&f);
break;
}
case 'o': {
//printf_s("AHOJ\n");
break;
}
case 'n': {
n(f, p, spz);
break;
}
case 's': {
s(spz, *p);
break;
}
case 'p': {
printf_s("AHOJ\n");
break;
}
case 'z': {
printf_s("AHOJ\n");
break;
}
default: {
printf_s("Skus znova\n");
break;
}
}
}
return 0;
}
EDIT: I have edited my code to add main method.
the problem is, when I pass the spz to another method after, it is null, that means I have to use it in method n() as triple pointer, but it is not working when I add asterisk before each spz in method n. Do you have any ideas how to fix this ?
When you call a function you pass a copy of the spz variable from the main() function to an spz variable in the n() function. Then, assignment in n() affects only its local spz.
If you want to get a pointer value back, you need to pass a pointer to the variable and the routine must dereference the pointer to reach the original variable:
void n( char ***spz_ptr) // a pointer to (char **) variable
{
*spz_ptr // dereferenced pointer. i.e. the main's spz
= malloc( ... );
}
void main()
{
char **spz;
n( & spz ); // pass a pointer to spz
if( spz == NULL) { // test the value assigned by n()
.... // handle the error
}
else {
.... // proceed with actual work
}
}

C error C2660: 'Menu' : function does not take 3 arguments

I am new to programming and do not understand this error.
I have the same arguments in the Menu () function and when I call the same function in the menu_principal () function.
In function menu_principal(), I want execute the switch-case statement by the function Menu() with 'option' variable.
Can you help please?
int main()
{
void menu_principal();
return 0;
}
void menu_principal()
{
bool stop = true;
int option;
const char *title = "MENU PRINCIPAL";
const char *options_menu[] = { "ARTIGOS", "CLIENTES", "ORCAMENTOS", "SAIR" };
int n_options = 4;
do
{
option = Menu(title, options_menu, n_options);
switch (option)
{
case 1:
Menu_Item();
break;
case 2:
Menu_Client();
break;
case 3:
Menu_Billing();
break;
case 4:
stop = false;
break;
}
} while (stop);
}
int Menu(const char *title1, const char *options_menu1[], int n_options1)
{
int OptionSelected= 1;
int key;
bool stop = true;
do
{
system("cls");
gotoxy(5, 3 + OptionSelected); printf(">>");
gotoxy(15, 2); printf("%s", title1);
for (int i = 0; i < n_options1; i++)
{
gotoxy(10, 4 + i);
printf("%s ", options_menu1[i]);
}
do
{
key = _getch();
} while (key != KEY_UP && key != KEY_DOWN && key != KEY_ENTER );
switch (key)
{
case KEY_UP:
OptionSelected--;
if (OptionSelected < 1)
{
OptionSelected = n_options1;
}
break;
case KEY_DOWN:
OptionSelected--;
if (OptionSelected > n_options1)
{
OptionSelected = 1;
}
break;
case KEY_ENTER:
stop = false;
break;
}
} while (stop);
return OptionSelected;
}
The compiler reads your program top to bottom, so it sees:
option = Menu(title, options_menu, n_options);
On this line, you call a previously unknown function, Menu.
Because the function is unknown, the compiler assumes it will be int Menu(void). (takes no parameters, returns an int).
That assumption is obviously different from how Menu eventually gets declared.
To fix this, declare the function properly near the top of your file:
int Menu(const char *title1, const char *options_menu1[], int n_options1);
Then, when the compiler encounters your function-call, it will not assume a declaration, it will use the declaration you already provided (takes 3 parameters, and returns an int)

c error: case label does not reduce to an integer constant

This is the switch case concerned by the error:
switch(event.type)
{
case SDL_Quit:
for (int i=0;i<NUMMENU;i++)
SDL_FreeSurface(menus[i]);
return 1;
case SDL_MOUSEMOTION:
x=event.motion.x;
y=event.motion.y;
for(int i=0;i<NUMMENU;i++)
{
if(x>=position[i].x && x<=position[i].x+position[i].w && y>=position[i].y && y<=position[i].y+position[i].h)
{
if(!selected[i])
{
selected[i]=1;
SDL_FreeSurface(menus[i]);
menus[i]=TTF_RenderText_Solid(font,labels[i],color[1]);
}
}else{
if(selected[i])
{
selected[i]=0;
SDL_FreeSurface(menus[i]);
menus[i]=TTF_RenderText_Solid(font,labels[i],color[0]);
}
}
}
case SDL_MOUSEBUTTONDOWN:
x=event.button.x;
y=event.button.y;
for(int i=0;i<NUMMENU;i++)
if(x>=position[1].x && x<=position[1].x+position[i].w && y>=position[i].y && y<=position[i].y+position[i].h)
{
for(int j=0;j<NUMMENU;j++)
SDL_FreeSurface(menus[j]);
return i;
}
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym==SDLK_ESCAPE)
{
for(int i=0;i<NUMMENU;i++)
SDL_FreeSurface(menus[i]);
return 0;
}
}
I have this error and I haven't any idea of why and what should I do to resolve this. I have tried to add break; at the end of each case but no results.
If you need more code or further information, I can give precisions.
Regards,
You are using the function void SDL_Quit(void) rather than the SDL_QUIT event type at line 3.
case SDL_Quit:
^^^^^^^^
for (int i=0;i<NUMMENU;i++)
SDL_FreeSurface(menus[i]);
return 1;
Your case labels such as SDL_Quit/SDL_MOUSEMOTION... could not be integer constants. For example its valid if they are characters labels but not something like const char * string literals which are not integer constants.

managing if statements

gcc 4.4.3 c89
I have some functions that initialize some hardware and return either true or false. If false then I have to uninitialize in the reverse order.
However, my code is looking very untidy with all the if statements.
For example each function can return either true of false. This is a sample. As you can see the code looks very untidy. I am just looking for any advice on how I can clean it up to make it more manageable and if possible scable?
Many thanks for any advice,
if(init_A() == TRUE) {
if(init_B() == TRUE) {
if(init_C() == TRUE) {
if(init_D() == TRUE) {
if(init_E() == TRUE) {
/* ALL STARTED OK */
}
else {
uninit_A();
uninit_B();
uninit_C();
uninit_D();
}
}
else {
uninit_A();
uninit_B();
uninit_C();
}
}
else {
uninit_A();
uninit_B();
}
}
else {
/* Failed to initialize B */
uninit_B();
}
}
else {
/* Failed to start */
}
if(init_A() != TRUE) {
goto EndA;
}
if(init_B() != TRUE) {
goto EndB;
}
if(init_C() != TRUE) {
goto EndC;
}
if(init_D() != TRUE) {
goto EndD;
}
if(init_E() != TRUE) {
goto EndE;
}
...
return;
EndE: uninitD();
EndD: uninitC();
EndC: uninitB();
EndB: uninitA();
EndA: return;
This is quite a common problem, where the "init" steps correspond to things like malloc() or lock(), and the "uninit" steps correspond to things like free() and unlock(). It is particularly an issue when resources have to be deallocated in strictly the reverse order in which they were allocated.
This is one case where the use of goto is justified:
int somefunc()
{
int retval = ERROR;
if (init_A() != TRUE)
goto out_a;
if (init_B() != TRUE)
goto out_b;
if (init_C() != TRUE)
goto out_c;
if (init_D() != TRUE)
goto out_d;
if (init_E() != TRUE)
goto out_e;
/* ALL STARTED OK */
/* ... normal processing here ... */
retval = OK;
uninit_E();
out_e:
uninit_D();
out_d:
uninit_C();
out_c:
uninit_B();
out_b:
uninit_A();
out_a:
return retval;
}
I would loop through an array of function pointers, call the functions in the loop, then if that function returned false, perform the corresponding uninit_* function.
Here's an example:
void (*inits[5]) (void);
void (*uninits[4]) (void);
int main(void) {
inits[0] = init_A;
inits[1] = init_B;
inits[2] = init_C;
inits[3] = init_D;
inits[4] = init_E;
uninits[0] = uninit_A;
uninits[1] = uninit_B;
uninits[2] = uninit_C;
uninits[3] = uninit_D;
for(int i = 0; i < 5; i++) {
if((*inits[i])() != TRUE) {
int j = (i < 4) ? i : 4;
while(j--) {
(*uninits[j])();
}
break;
}
}
return 1;
}
BOOL a = FALSE, b = FALSE, c = FALSE, d = FALSE, e = FALSE;
if ( (a = init_A()) && (b = init_B()) && (c = init_C()) && (d = init_D()) && (e = init_E()) )
{
}
else
{
if ( e ) uninit_E();
if ( d ) uninit_D();
if ( c ) uninit_C();
if ( b ) uninit_B();
if ( a ) uninit_A();
}
uninit functions are called in direct order, as in your code. If reverse order is required, just change this.
If your uninit_* functions can detect whether or not they need to do anything you can simply:
if (!init_A() || !init_B() || !init_C() || !init_D() )
{
uninit_C();
uninit_B();
uninit_A();
return FALSE;
}
Is that "reverse order"? For me reverse order is like this:
void uninit(int from) {
switch (from) {
/* ... */
case 3: uninit_C(); /* fall_through */
case 2: uninit_B(); /* fall_through */
case 1: uninit_A(); /* fall_through */
case 0: break;
}
}
And the init process would go like this
int count = 0;
if (init_A()) {
count++;
if (init_B()) {
count++;
if(init_C()) {
count++;
if(init_D()) {
count++;
if(init_E()) {
count++;
}
}
}
}
}
if (count == 5) /* ALL OK */;
uninit(count);
Limited understanding of C at work here, if you do decide to downvote, please tell me why.
#include <stdio.h>
int init_a() { return 1; }; // succeed
int init_b() { return 1; }; // succeed
int init_c() { return 0; }; // fail
void uninit_a() { printf("uninit_a()\n"); }
void uninit_b() { printf("uninit_b()\n"); }
void uninit_c() { printf("uninit_c()\n"); }
typedef struct _fp {
int (*init)();
void (*uninit)();
} fp;
int init() {
fp fps[] = {
(fp){&init_a, &uninit_a},
(fp){&init_b, &uninit_b},
(fp){&init_c, &uninit_c}
};
unsigned int i = 0, j;
for(; i < sizeof(fps) / sizeof(fp); ++i) {
if(!(*fps[i].init)()) {
for(j = 0; j < i; ++j) {
(*fps[j].uninit)();
}
return -1;
}
}
return 0;
}
int main() {
init();
return 0;
}
Output:
uninit_a()
uninit_b()
This is the same order that the code in original post would be executed in, but you may want to reverse it (inner loop).
What you perhaps are looking for is "scope bound resource management". C++ traditionally does that with constructors/destructors. But there is a way to do that differently (in C99 as well as in C++) by abusing the for-statement a bit. I wrote something up upon this line here:
scope bound resource management with for scopes.
I've not got a compiler to try this out. But something like this might work?
int (*init[])() = {init_A, init_B, init_C, init_D, init_E};
int (*uninit[])() = {uninit_A, uninit_B, uninit_C, uninit_D, uninit_E};
int main()
{
initfunction(init, 0)
return 0;
}
void initfunction((*init[])(), pos)
{
if(init[pos]() == TRUE)
initfunction(init, pos++)
else
return;
uninit[pos]();
}
int X = 0;
if(init_A() == TRUE) {
X++;
if(init_B() == TRUE) {
X++;
if(init_C() == TRUE) {
X++;
if(init_D() == TRUE) {
X++;
if(init_E() == TRUE) {
X++;
/* ALL STARTED OK */
}
}
}
}
}
/* You said reverse order which I took to mean this,
* though your did not do it this way. */
switch (X) {
case 5:
return SUCCESS;
case 4:
uninit_D();
case 3:
uninit_C();
case 2:
uninit_B();
case 1:
uninit_A();
return FAILURE;
}
Something I find myself doing to prevent myself from making errors in code like this is:
static int do_A(void);
static int do_B(void);
static int do_C(void);
static int do_D(void);
static int do_A(void) {
if (init_A() == FALSE) {
return FALSE;
}
if (do_B() == FALSE) {
uninit_A();
return FALSE;
}
return TRUE;
}
...
static int do_D(void) {
return init_D();
}
All of the other do_ functions should look similar to do_A.

Resources