How to switch and case for string? - c

I have the following code
#define SWITCH(S) char *_S = S; if (0)
#define CASE(S) } else if (strcmp(_S, S) == 0) {switch(1) { case 1
#define BREAK }
#define DEFAULT } else {switch(1) { case 1
int main()
{
char buf[256];
printf("\nString - Enter your string: ");
scanf ("%s", buf);
SWITCH (buf) {
CASE ("abcdef"):
printf ("B1!\n");
BREAK;
CASE ("ghijkl"):
printf ("C1!\n");
BREAK;
DEFAULT:
printf ("D1!\n");
BREAK;
}
}
If I generate the pre-processor code with gcc -E, I will get the following code
int main()
{
char buf[256];
printf("\nString - Enter your string: ");
scanf ("%s", buf);
char *_S = buf;
if (0) {
} else if (strcmp(_S, "abcdef") == 0) {switch(1) { case 1:
printf ("B1!\n");
};
} else if (strcmp(_S, "ghijkl") == 0) {switch(1) { case 1:
printf ("C1!\n");
};
} else {switch(1) { case 1:
printf ("D1!\n");
};
}
}
But for some gcc defining char *_S = buf; in the middle of the code is not wolcome and could provide compilation error
How to fix that in my macro?
Please do not suggest to define char *_S as global (out of the main)

Remove the macros altogether, and write it in the "expanded" way, moving the declaration to the top. These macros are horrific.
Failing that, tweak SWITCH to introduce a new scope (a second {). This will of course force you to have to close two scopes, so perhaps add a SWITCH_END abomination to use at the end, to encapsulate that. Whatever.

Oh no!!!
I wrote this as a joke in this post
Don't use it is very very horrific, if you want to avoid if-else you can do it without torturing the compiler, consider using pair of strings:
#include <stdio.h>
#include <string.h>
int main(void)
{
char buf[256];
const char *ap[] = {
"abcdef", "B1!\n",
"ghijkl", "C1!\n",
NULL , "D1!\n",
}, **p = ap;
printf("\nString - Enter your string: ");
scanf ("%s", buf);
while (*p) {
if (strcmp(buf, *p) == 0) break;
p += 2;
}
printf("%s", *(++p));
return 0;
}

Make sure the code is being compiled as C99 or later; otherwise, you will need to use a different control structure.
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
SWITCH(buf)
{
...
}
#else
if (strcmp(buf, "abcdef") == 0)
{
...
}
else if (strcmp (buf, "ghijkl") == 0)
{
...
}
else
{
...
}
#endif
It's generally not a good idea to use the preprocessor to "alter" or extend C syntax (I have the scar tissue to prove it); switch isn't defined on string expressions for a reason.
If you really want to use a switch in this situation, then it may be better to code up a hash function that returns a key for each string, and switch on the result:
#define ABCDEF ... // hash key generated for "abcdef"
#define GHIJKL ... // hash key generated for "ghijkl"
...
switch(hash(buf))
{
case ABCDEF :
...
break;
case GHIJKL :
...
break;
default:
...
break;
}

Related

result of comparison against a string literal is unspecified (use strncmp instead) [-Wstring-compare] is the error i get please help me

please help me i am struggling with this it keeps giving me errors on errors btw LABEL 2 leads to the main part
#include <stdio.h>
void main()
{
int a,b,c;
char d[10],e[10];
Label:
printf("Username of the agent: ");
scanf("%s",d);
printf("Password: ");
scanf("%s",e);
if(d=="Vayush" && e=="Vasireddy")
{ goto Label2;}
else
printf("wrong username and password\n");
goto Label;
}
if(d=="Vayush" && e=="Vasireddy")
is comparing pointers to string literals, thats wrong because you want to compare contents and not addresses. The compiler is telling you to use the standard function strncmp instead of ==, in this case strcmp can do the job:
#include <stdio.h>
#include <string.h> // strcmp
int main(void) // Use a valid signature
{
// Use meaningful names for your vars
char usr[10];
char pwd[10];
// Do not use goto, loop until you get valid values
while (1)
{
printf("Username of the agent: ");
// scanf return the number of input items successfully matched or EOF
int n = scanf("%9s", usr); // %9s in order to avoid buffer overflows
if (n == EOF) { break; }
if (n == 1)
{
printf("Password: ");
n = scanf("%9s", pwd);
if (n == EOF) { break; }
if ((n == 1) &&
(strcmp(usr, "Vayush") == 0) &&
(strcmp(pwd, "Vasireddy") == 0))
{
break;
}
}
printf("wrong username and password\n");
}
}

Command-line parsing: How to parse a string as an argument

I am attempting to parse a command line argument, which in turn will execute an associated case within a switch statement. When I parse an integer argument (as seen in the code below), the associated case executes correctly. When I attempt to parse a string such as "CPU", I do not get the correct output.
Functioning code (parsing an integer e.g. an argument of 4 gives athe correct output of hello):
#include <stdio.h>
int main(int argc, char *argv[]) {
char execution_mode = atoi (argv[1]);
switch (execution_mode)
{
case (4) :
printf("Hello");
getchar();
break;
case (8) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
My attempt at parsing a string e.g. the argumentCPU:
#include <stdio.h>
int main(int argc, char *argv[]) {
typedef enum MODE { CPU, OPENMP } MODE;
MODE execution_mode = (char)argv[1];
switch (execution_mode)
{
case (CPU) :
printf("Hello");
getchar();
break;
case (OPENMP) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
You cannot convert a string to an enumerate like this. What you're doing is just converting the pointer to the string to char. Which fails.
One alternative (besides comparing first argument with strcmp) to avoid this would be to give a character value to your enumerates:
typedef enum { CPU='C', OPENMP='O' } MODE;
and now you can pick the first letter of the first argument and convert it:
MODE execution_mode = (MODE)argv[1][0];
The letters must be of course all different. And check argc>1 to see if argv[1] is valid, of course
If you want full string match, you have no other choice than using strcmp:
const char *execution_mode = argv[1];
if (strcmp(execution_mode,"CPU")==0)
{
// do something
}
else if (strcmp(execution_mode,"OPENMP")==0)
{
// do something else
}
With the help of the users who have answered this question, I have found a working solution by using strcmp as seen below. I have also added some error checking to ensure enough arguments have been enterred on the command-line.
#include <stdio.h>
int main(int argc, char *argv[]) {
//Ensure there are enough arguments
if (argc < 2)
{
printf("Error: not enough arguments");
exit(1);
}
typedef enum MODE { CPU, OPENMP, CUDA, ALL } MODE;
MODE execution_mode = (MODE)argv[1];
//Compare string with command-line arguments
if (strcmp("CPU", execution_mode) == 0)
{
//selects CPU case
execution_mode = CPU;
}
else if (strcmp("OPENMP", execution_mode) == 0)
{
//selects OPENMP case
execution_mode = OPENMP;
}
else
{
printf("invalid arg");
}
//Switch statement
switch (execution_mode)
{
case (CPU) :
printf("CPU MODE SELECTED");
getchar();
break;
case (OPENMP) :
printf("OPENMP MODE SELECTED");
getchar();
break;
default:
printf("Error: execution mode is not correct");
getchar();
break;
}
return 0;
}

Program Works only debug mode but not in normal exe (using c lion)?

SO i created a program that converts from infix to post fix and prefix which works just fine. The thing is that I am using C-LION which has its own debugger that allows me to go step by step and I do that the program works fine and outputs the expected results BUT then when I run it normally IT DOES NOT WORK AND GIVES ME A "main.c not working " ERROR.
This the main function that has the menu:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <tgmath.h>
char*infixToPostfix(char *infinx);
char* postixToinfix(char *infinx);
char* postixToprefix(char *infinx);
char* prefixToinfix(char *infinx);
char* prefixTopostfix(char *infinx);
char* infixToPrefix(char *infinx);
char*evaluate(char *infinx );
int exp_det(char*exp);
typedef struct node
{
char *op;
int p;
struct node *next; /* Pointer to the next node. Notice that the
existence of the structure tag enables us to declare its type. */
} node;
node *head=NULL; /* Global pointer that always points to the head of the
stack. */
int precedence(char symbol);
void add_stack(const node *p);
void pop(void);
int main(void)
{
char postfix[100];
int choice;
//converting from ininfinx to postfix
printf("\t\t***** Conversion Calculator 1.0 ******\t\t\n");
printf("\t\t1.Convert\n\t\t2.Evaluate\n\t\t3.Exit\nEnter Choice : ");
scanf("%d",&choice);
//switch (choice){
if (choice==1) {
printf("\n\t\t1.Input from File\n\t\t2.standered input\nEnter Choice :");
int ch2;
scanf("%d", &ch2);
switch (ch2) {
case 1:
printf("FILE MANGAMENT STILL NOT DONE !!!");
break;
case 2:
printf("Enter Expression : ");
char line[256];
scanf(" %[^\n]s", postfix);
char in2[100] = {'\0'};
char in3[100] = {'\0'};
char *conv;
char *conv2;
strcpy(in2, postfix);
strcpy(in3, postfix);
int exp = exp_det(in2);
if (exp == 1) {
printf("\nThis is a Prefix expression do you want to\n\t\t1.Infix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
conv = prefixToinfix(in3);
printf("Expression in Infix form: %s \n", in3);
break;
case 2:
conv = prefixTopostfix(in3);
printf("Expression in Postfix form: %s \n", in3);
break;
case 3:
conv = prefixToinfix(in3);
conv2 = prefixTopostfix(postfix);
printf("Expression in Infix form: %s \n", conv);
printf("Expression in Postfix form: %s \n", conv2);
break;
default:
printf("ERROROR WHEN EXPRESSION IN PREFIX ");
break;
}
} else if (exp == 2) {
printf("\nThis is a Infix expression do you want to\n\t\t1.Prefix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
break;
case 2:
printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
break;
case 3:
printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
break;
default:
printf("ERROROR R");
break;
}
} else if (exp == 3) {
printf("This is a Postfix expression do you want to\n\t\t1.Infix\n\t\t2.Prefix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
printf("Expression in Infix form: %s \n", postixToinfix(postfix));
break;
case 2:
printf("Expression in prefix form: %s \n", postixToprefix(postfix));
break;
case 3:
printf("Expression in Infix form: %s \n", postixToinfix(postfix));
printf("Expression in Prefix form: %s \n", postixToprefix(postfix));
break;
default:
printf("ERROR... 3:(\n");
break;
}
}
break;//for the switch with ch2 case 1
default:
printf("ERROR... 2:(\n");
break;
}
//break;
}if(choice==2) {
printf("Enter Expression : ");
scanf(" %[^\n]s", postfix);
char in2[100] = {'\0'};
char in3[100] = {'\0'};
char *conv;
char *conv2;
strcpy(in2, postfix);
conv = evaluate(in2);
printf("\nExpression evaluated = %s \n", conv);
//break;
}if(choice==3) {
printf("BYE...... :D\n");
}
system("PAUSE");
}
OK Now after much trials I am starting to think that the problem is in the conversion itself. This is one of the functions i am using for me it looks fine. If anyone has another opinion help is greatly appropriated.
char* infixToPostfix(char *infinx){
char* token;
char * infinx1=malloc(sizeof(infinx)+1);
infinx1=strcpy(infinx1,infinx);
token = strtok(infinx1," ");
char* res;
res=malloc(sizeof(infinx)+sizeof(head->op)*strlen(infinx));
strcpy(res," ");
if(*token=='\n' ){token=strtok(NULL," ");}
while( token != NULL ) {
node n;
n.op=token;
n.p=precedence(*token);
if(isalpha(*token) || isdigit(*token)){
// strcat(result,infinx[i]);
//printf("%c",infinx[i]);
res=strcat(res,token);
res=strcat(res," ");
}
//case when encounter a left paranthessisis
else if(*token=='(' || *token==')'){
if (*token=='('){
add_stack(&n);
}else if(*token==')') {
while (*head->op != '(') {
// strcat(result, n.op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
pop();
}
}
//if head if null meaning the stack is empty or if the presendance of the head is less thatn or equal to new character
else if(head==NULL || head->p < n.p ){
if (head->p == n.p){}
add_stack(&n);
}
//in case the head has higher presendance he we pop and print untill we reach the same presedance
else {
while( head!=NULL && head->p >= n.p){
//strcat(result,n.op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
add_stack(&n);
}
token=strtok(NULL," ");
}
while(head!=NULL){
//strcat(result,head->op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
return res;
}
This is the answer to your question "So your saying I should define them outside the switch statement?" which reflects correctly one of the problems in your code.
Either: You can define them outside to solve the issue.
Or: You can introduce appropriate block scopes to solve the issue.
As the former is trivial, I will elaborate the latter:
1. Scope and Variables
The life-time of a local variable starts at its declaration and ends with surrounding block scope.
Example:
int main()
{
int a = 0; /* a starts to live. */
{ /* new scope */
int b = 1; /* b starts to live */
int a = 2; /* a new a starts to live. (The one of out scope is eclipsed.) */
} /* Life of b and the inner a ends. The eclipsed outer a becomes visible again. */
return 0;
}
2. switch and case
In opposition to other languages (like e.g. Pascal), the C switch statement is rather a "goto depending on expression" than a multiway branching with multiple alternatives. (This does not mean that switch cannot be used for the latter but it can be used different as well.) (Please, see Wikipedia: Control Flow: 5.2 Case and switch statements to understand what I mean.)
Imagine the following (wrong) code:
#include <stdio.h>
int main()
{
goto L1;
int i = 1;
L1:
printf("%d\n", i);
return 0;
}
The goto L1; skips the declaration of int i = 1; but after L1: it is used in printf() – ouch!
Out of curiosity, I tried it in ideone.com – it compiled and ran without complaints. Output was 0 although it could have been as well 1, 2, or any other number which can be stored as int.
This is the same in the following (wrong) sample:
#include <stdio.h>
int main()
{
int cond = 2;
switch (cond) {
case 1:
printf("case 1\n");
int i = 1;
case 2:
printf("case 2: %d\n", i);
} /* Here ends the life-time of i */
return 0;
}
Again, I compiled and tested in ideone.com.
Output was case 2: 0. Ouch again!
Solution
To mimic multi-branching correctly, the following things are necessary:
End each case with a break.
Start a scope after each colon of a case.
End this scope before the corresponding break.
Example again:
#include <stdio.h>
int main()
{
int cond = 2;
switch (cond) {
case 0: case 1: { /* <- start scope */
int i = 1;
printf("case 1: %d\n", i);
} break; /* <- end scope and jump to end of switch */
case 2:
printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
}
return 0;
}
Compiled in ideone:
prog.c: In function ‘main’:
prog.c:12:34: error: ‘i’ undeclared (first use in this function)
printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
^
As the scope of variable i is limited to the range from the possible entrance (case 0: case 1:) until the possible exit (break) – no other possible code path may access it.

How to use switch and case for strings

Based on an answer of the following question: How do I transform an IF statement with 2 variables onto a switch function using C?
I want to develop SWITCH and CASE macros to use it (like switch and case) for strings.
Some thing like that:
char buf[256];
SWITCH (buf) {
CASE ("abcdef"):
printf ("A1!\n");
BREAK;
CASE ("ghijkl"):
printf ("B1!\n");
BREAK;
DEFAULT:
printf ("D1!\n");
BREAK;
}
what could be SWITCH and CASE and BREAK and DEFAULT here ?
If you really want it, well, here it is:
#include <string.h>
#include <stdio.h>
const char *kludge;
#define evilmacro(line) label##line
#define fakelabel(line) evilmacro(line)
#define SWITCH(str) while((kludge = (str)))
#define CASE(str) if(strcmp(kludge, str) == 0) { fakelabel(__LINE__)
#define BREAK break; /* out of while loop */ }
#define DEFAULT if(1) { fakelabel(__LINE__)
int main(int argc, char *argv[]) {
SWITCH (argv[1]) {
CASE ("abcdef"):
printf ("A1!\n");
BREAK;
CASE ("ghijkl"):
printf ("B1!\n");
BREAK;
DEFAULT:
printf ("D1!\n");
BREAK;
}
return 0;
}
Getting rid of the unused labels is left as an exercise for the reader :)
EDIT: fwiw, what I would really do is table driven code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SWITCH(S) char *_S = S; if (0)
#define CASE(S) } else if (strcmp(_S, S) == 0) {switch(1) { case 1
#define BREAK }
#define DEFAULT } else {switch(1) { case 1
int main()
{
char buf[256];
printf("\nString - Enter your string: ");
scanf ("%s", buf);
SWITCH (buf) {
CASE ("abcdef"):
printf ("B1!\n");
BREAK;
CASE ("ghijkl"):
printf ("C1!\n");
BREAK;
DEFAULT:
printf ("D1!\n");
BREAK;
}
}

How to set a string to perform a function or command

I kind of have a basic question for you because it's driving me crazy. How do I go about writing my functions to specific strings? Like, if I was creating a while loop and wanted the program to end, how would I write it so that the program itself ends when I type in "end" when it asks for input?
EDIT: Alright, so I figured out pretty easily how to end my function by typing "end", but now for some reason depending on how many sentences I write, my program keeps repeating itself.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int i;
char buf[10];
printf("Command? ");
scanf("%s", buf);
while(buf != "end")
{
if(strcmp(buf, "end")== 0){
break;
}
switch( buf[i] ){
//Where the cases will inevitably go
default:
puts("I'm sorry, but that's not a command.\n");
break;
}
printf("Command? ");
scanf("%s", buf);
}
puts("End of Program.");
getch();
}
char *myInputString = NULL;
while (1) {
/* read in myInputString from user input, and test... */
if (strcmp(myInputString, "foo") == 0)
break;
}
return EXIT_SUCCESS;

Resources