parsing with recursion - brackets - c

Could some give me a hint at this problem :
An expression is correct only if it contains parentheses and braces properly closed and no other character, even space. For example, () ({} () ({})) is a correct expression, whereas ({)} is not a correct expression or {} ({})). An empty expression (which does not contain any character) is correct.
Given a string expression determine if the expressions is correct and if is determine the maximum level of nesting. Maximum level of nesting parentheses is the maximum number of one another.
Examples
{}({}){{(({}))}}
answer : 5
{}({})) -1 (because the expression is incorrect)
That's what I've did so far.
#include <stdio.h>
#include <stdlib.h>
FILE *fi, *fo;
int first, er;
void X();
void Y();
void S() {
X();
Y();
}
void X() {
if(first=='{') {
first=fgetc(fi);
X();
if(first=='}')
first=fgetc(fi);
else
er=1;
S();
}
}
void Y() {
if(first=='(') {
first=fgetc(fi);
Y();
if(first==')')
first=fgetc(fi);
else
er=1;
S();
}
}
int main()
{
fi = fopen("brackets.in","r");
fo = fopen("brackets.out","w");
first=fgetc(fi);
S();
if(first!='\n')
er=-1;
fprintf(fo,"%d",er);
fclose(fi);
fclose(fo);
return 0;
}

First off, it helps to think of your problem as a formal grammar.
S = The Language you are testing for
S->
NUL // Empty
SS // S followed by itself.
[ S ] // Case 1
( S ) // Case 2
{ S } // Case 3
Since this grammar only has one symbol (S), you only need one parsing method.
The following code is incomplete but hopefully it gets the idea across.
char curr_char;
int main (void)
{
curr_char = getc();
result = parse_s();
return 0;
}
// Parse the S pattern off input. When this method completes, curr_char points to the character AFTER S.
// Returns recursion count or -1 on fail.
int parse_s()
{
max_count = 0;
while(true)
{
int curr_count = 0;
switch 'curr_char':
{
case '[': // [
int count = parse_s(); // S
if (count == -1) return -1; // The S must be valid
if (curr_char != ']') return -1; // ]
curr_char = getc(); // Advance past the ]
curr_count = count + 1; // This expression is 1 nest greater than its contained S
break;
case '(':
// XXX
break;
case '{':
// XXX
break;
default:
// This is either the SS (find the max of the two), the NUL case (return 0), or an error (return -1)
break;
}
// In the SS case you're gonna have to loop and do something here.
}
return max_count;
}

Related

(C) Am I properly converting enum type to string?

I am very new to coding, and am taking an online course with very little help. I am working through an assignment creating a bunch of functions that will be used at a later date. I have not learned anything about points, arrays, or recursions at this point. My knowledge of strings is pretty much limited to the "printf" function.
With that being said, I have been given this description for how the function "ranking_to_string" should operate:
This function should convert the
hand_ranking_t enumerated value passed
in to a string that describes it.
The enumerated type here is hand_ranking_t, which ranks a poker hand in descending order of value from STRAIGHT_FLUSH (0) to NOTHING (8). With that all being said, this is the function I have created to attempt to follow my instructions:
const char * ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: printf("STRAIGHT_FLUSH\n"); break;
case FOUR_OF_A_KIND: printf("FOUR_OF_A_KIND\n"); break;
case FULL_HOUSE: printf("FULL_HOUSE\n"); break;
case FLUSH: printf("FLUSH\n"); break;
case STRAIGHT: printf("STRAIGHT\n"); break;
case THREE_OF_A_KIND: printf("THREE_OF_A_KIND\n"); break;
case TWO_PAIR: printf("TWO_PAIR\n"); break;
case PAIR: printf("PAIR\n"); break;
case NOTHING: printf("NOTHING\n"); break;
default: printf("Invalid thing\n"); break;
}
return EXIT_SUCCESS;
}
I am wondering, am I correct in returning EXIT_SUCCESS (0) at the end of the function? Is there another way to convert the enum value entered into a string using printf?
EXIT_SUCCESS is a macro that will expand into an environment defined indicator to be returned from main (or via exit, etc.) to indicate that your entire program has successfully done what it is supposed to do. It's generally not used outside this context.
printf is used to send output to the stream associated with stdout. For example, you might call printf to display text in your terminal.
Your function should instead return the string literals, to be used by the caller of ranking_to_string.
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
An example program:
#include <stdio.h>
typedef enum {
STRAIGHT_FLUSH,
FOUR_OF_A_KIND,
/* ... and so on ... */
} hand_ranking_t;
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
int main(void) {
hand_ranking_t rank = FOUR_OF_A_KIND;
const char *rank_string = ranking_to_string(rank);
printf("My ranking is <%s>\n", rank_string);
}
Output:
My ranking is <FOUR_OF_A_KIND>
Probably not covered in your course, but it's possible to automate ranking_to_string entirely by using X-Macros. Also, since poker hands have value, it makes sense to list them by it.
#include <stdlib.h>
#include <stdio.h>
#define HANDS X(HIGH_CARD), X(PAIR), X(TWO_PAIR), X(THREE_OF_A_KIND), \
X(STRAIGHT), X(FLUSH), X(FULL_HOUSE), X(FOUR_OF_A_KIND), \
X(STRAIGHT_FLUSH), X(ROYAL_FLUSH)
#define X(name) name
enum hand { HANDS };
#undef X
#define X(name) #name
static const char *hand_str[] = { HANDS };
#undef X
static const size_t hand_size = sizeof hand_str / sizeof *hand_str;
int main(void) {
enum hand i, j;
for(i = 0; i < hand_size; i++) printf("%s\n", hand_str[i]);
i = FULL_HOUSE;
j = FLUSH;
printf("%s is %s than %s.\n",
hand_str[i], i < j ? "less" : "greater", hand_str[j]);
return EXIT_SUCCESS;
}
Where # is the stringizing operator of the pre-processor.

Checking balanced parentheses in a string with stacks in c

I am trying to write a program where i implement stacks with arrays and use them to check if a given string has balanced parentheses.
For ex. if inputted '(()){}[()]' ,program would output 'Balanced', otherwise if inputted '({})[' the program would output 'Not balanced'.
This part is the array implementation of the stack.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int stack[MAX];
int top=-1;
void push(char val){
if(top==MAX-1){
printf("stack is already full,error\n");
}else{
top++;
stack[top]=val;
}
}
char pop(){
if(top==-1){
printf("not enough elements,error\n");
exit(1);
}else{
top--;
return stack[top];
}
}
This part is the implementation of a common method to solve the problem.
int isMatching(char c1, char c2){
if(c1=='{' && c2=='}')
return 1;
else if(c1 =='(' && c2==')')
return 1;
else if(c1=='[' && c2==']')
return 1;
return 0;
}
int isBalanced(char str[]){
int i=0;
while(str[i]!='\0'){
if(str[i]=='{' || str[i]=='[' || str[i]=='('){
push(str[i]);
}
if(str[i]==')' || str[i] == ']' || str[i]=='}'){
if(stack==NULL){
return 0;
}
if(!isMatching(pop(), str[i])){
return 0;
}
}
i++;
}
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
}
And this is the main function where the user inputs a string and it's tested if it's 'Balanced' or not.
int main(){
char str[MAX];
int flag;
printf("Enter the string with the brackets and etc.\n");
fgets(str, sizeof(str),stdin);
flag=isBalanced(str);
if(flag==1){
printf("Balanced\n");
}
else{
printf("Not balanced\n");
}
return 0;
}
When i input a very simple example, i get a wrong answer, for instance
Enter the string with the brackets and etc.
()
Not balanced
This is supposed to output 'Balanced' instead.I don't understand how this could have occured.
in pop(), you are decrementing before returning the top element. Change:
top--;
return stack[top];
to
return stack[top--];
Also, in isBalanced(), stack is NEVER null, so delete:
if(stack==NULL){
return 0;
}
and change the balanced check to look for the empty stack from:
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
To:
if(top==-1){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
After making these changes, your code appeared to work on my box. This isn't quite how I'd have coded it, but this is the minimal set of changes to make it work.
if (stack==NULL) is the problem here, stack will never be NULL.
You need to check if there are still elements in your stack, by verifying that top > 0
You implemented the push/pop combo wrong. If you push one character top becomes 0. If you popping it immediately it finally executes top--; return stack[top], which evaluates to stack[-1].
Try this push/pop:
int top=-1; //idx to be popped next; <0 -> invalid
void push(char val)
{
if(top==MAX-2)
printf("stack is already full,error\n");
else
stack[++top]=val;
}
char pop()
{
if(top<0) return '\0'; //no abort, just return invalid char
return stack[top--];
}
The answer to your question has already been satisfactorily answered, but as a suggestion for a different approach, consider the following.
Since there are only a very small number of common enclosures used within C source code you can easily track pairs of them using an increment-decrement counter. The following uses a struct, typedefed to balanced_s which is encapsulated into a function to simplify the evaluation. Following is a sample implementation:
typedef struct {
int paren;
int curly;
int square;
bool bBal
}balanced_s;
balanced_s * balanced_enclosures(const char *source);
int main(void)
{
char in[5000] = {0};//you could improve this by reading file size
//first then creating array sized accordingly
FILE *fp = fopen("C:\\play\\source.c", "r");//using copy of this source to test
if(fp)
{
size_t bytes = fread(in, 1, sizeof(in), fp);
}
balanced_s * b = balanced_enclosures(in);
bool balanced = b->bBal;//If not true, inspect the rest of the
//members to see where the imbalance has occurred.
free(b);
return 0;
}
balanced_s * balanced_enclosures(const char *source)
{
balanced_s *pBal = malloc(sizeof(*pBal));
memset(pBal, 0, sizeof(*pBal));
while(*source)
{
switch(*source) {
case '(':
pBal->paren++;
break;
case ')':
pBal->paren--;
break;
case '{':
pBal->curly++;
break;
case '}':
pBal->curly--;
break;
case '[':
pBal->square++;
break;
case ']':
pBal->square--;
break;
}
source++;
pBal->bBal = (!pBal->paren && !pBal->curly && !pBal->square);
}
return pBal;
}

Why does my program keep getting stuck while running the mandelbrot brainf*** program?

I wanted to improve my C skills, so I search some program's ideas.
Someone propose to create a simple Brainf*** interpreter and then a compiler. So here I am.
I created the interpreter and it works as expected, except with the Mandelbrot program:
A mandelbrot set fractal viewer in brainfuck written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
<<<<<]]>>>]
I don't understand why, but my program keeps getting stuck in some sort of endless loop. I try to debug it using gdb but it's hard to find the right breakpoint in order to see why it stuck.
The program is as follows:
#include <stdio.h>
#include <stdlib.h>
// Brainfuck instructions
// > Math stuff
#define INCR '+' // +1 on current MS
#define DECR '-' // -1 on current MS
// > Memory slot stuff
#define FORW '>' // Go to next MS
#define BACK '<' // Go to previous MS
// > Logic stuff
#define SJMP '[' // Loop till current MS value is equal to zero
#define EJMP ']' // Jump to the beginning of the loop
// > I/O stuff
#define PRTC '.' // Print character with MS value as ASCII code
#define GETC ',' // Get an user input ASCII character code
typedef unsigned char byte;
// The brainfuck program struct
typedef struct {
byte *values;
int size;
int index;
byte *loops_starts;
int loop_size;
int loop_index;
} BrainfuckProgram;
void initialize(BrainfuckProgram *bfp) {
bfp->values = malloc(bfp->size * sizeof(*bfp->values));
bfp->loops_starts = malloc(bfp->size * sizeof(*bfp->loops_starts));
}
int allocate_values(BrainfuckProgram *bfp) {
byte *newMem = realloc(bfp->values, bfp->size * sizeof(byte));
if (!newMem) {
return 1;
}
bfp->values = newMem;
return 0;
}
int allocate_new_loop(BrainfuckProgram *bfp) {
byte *newMem = realloc(bfp->loops_starts, bfp->loop_size * sizeof(byte));
if (!newMem) {
return 1;
}
bfp->loops_starts = newMem;
return 0;
}
void set_value(BrainfuckProgram *bfp, byte value) {
int tempValue = value < 0 ? 255: value % 256;
*(bfp->values + bfp->index) = tempValue;
}
int get_value(BrainfuckProgram *bfp) {
return *(bfp->values + bfp->index);
}
// FILE functions
int get_file_name(int argc, char *argv[], char** fname) {
if (argc == 1) {
printf("File name is missing\n");
return 1;
}
*fname = argv[1];
return 0;
}
int get_file_size(FILE *file) {
fseek(file, 0L, SEEK_END);
int size = ftell(file);
rewind(file);
return size;
}
// Main function
int main(int argc, char *argv[]) {
// Vector part
BrainfuckProgram bfp = {
.values = NULL,
.size = 1,
.index = 0,
.loops_starts = NULL,
.loop_index = 0,
.loop_size = 0
};
initialize(&bfp);
// FILE Part
char* fname = NULL;
int error = get_file_name(argc, argv, &fname);
if (error) {
goto exit;
}
// Create file variable
FILE *fin = NULL;
fin = fopen(fname, "r");
int size = get_file_size(fin);
// Create a char array of the right size
byte *prog = NULL;
prog = malloc(size * sizeof(*prog));
// Read 1 byte size times
fread(prog, 1, size, fin);
for (int i = 0; i < size; i++) {
byte current = *(prog+i);
switch (current) {
case INCR:
set_value(&bfp, get_value(&bfp) + 1);
break;
case DECR:
set_value(&bfp, get_value(&bfp) - 1);
break;
case FORW:
// if index+1 == size then we are at the
// last element of the vector cause
// size = index - 1
if (bfp.index+1 == bfp.size) {
bfp.size++;
int error = allocate_values(&bfp);
if (error) {
printf("an error occured while forwarding pointer");
goto close;
}
}
bfp.index++;
break;
case BACK:
// bfp.index == 0 then !bfp.index == true
if (!bfp.index) {
printf("can go back from index 0\n");
goto close;
}
bfp.index--;
break;
case SJMP:
if (bfp.loop_index == bfp.size) {
bfp.loop_size++;
int error = allocate_new_loop(&bfp);
if (error) {
printf("an error occured while forwarding pointer");
goto close;
}
}
bfp.loop_index++;
*(bfp.loops_starts + bfp.loop_index) = i;
break;
case EJMP:
if (bfp.loop_index == -1) {
printf("cannot go back");
goto close;
}
if (get_value(&bfp) != 0) {
i = *(bfp.loops_starts + bfp.loop_index);
} else {
bfp.loop_index--;
}
break;
case PRTC:
printf("%c", get_value(&bfp));
break;
case GETC:
; // Semicolon here because of the label error
byte buf;
scanf("%c", &buf);
set_value(&bfp, buf);
break;
}
}
close:
fclose(fin);
exit:
;
return 0;
}
I'd like to have some C related advice on what I have done wrong too.
The Mandelbrot program takes a decent time to run on a good interpreter. Yours, well, it isn't that good. That's why it "hangs" at the start.
Some good ideas that you had, performance-wise:
precalculating loops
Some bad ideas, performance-wise:
Using abstracted allocation functions instead of calling realloc
using scanf and printf instead of getchar and putchar
Some odd things that you did:
Manually truncating an unsigned char when wraparound is implicit
checking if an unsigned char is less than 0
using *(x + y) syntax instead of array indexing x[y]
I don't think you actually use those precalculated loops, if you do then probably not correctly
You also probably create a new precalculated loop every time you go over the loop again
Using the get_value and set_value functions instead of pointers (this will be a performance issue if you don't compile with optimizations)
A couple suggestions:
Try to avoid calling functions when you don't need to as much as possible.
Write a BrainFuck->C compiler using this reference.
On second thought, maybe you should try to debug this program instead.
You may also use my interpreter as a reference if you're OK with GPLv3. Note that it doesn't precalculate loops.

can we use switch-case statement with strings in c? [duplicate]

This question already has answers here:
How can I compare strings in C using a `switch` statement?
(16 answers)
Closed 5 years ago.
int a = 0 , b = 0;
char* c = NULL;
int main(int argc , char ** argv){
c = argv[2];
a = atoi(argv[1]);
b = atoi(argv[3]);
switch(c){
case "+": printf(a+b);
break;
}
printf("\n\n");
return 0;
}
No, you can't. Switch is intended to compare numeric types, and for extension char types.
Instead you should use the strcmp function, included in string header:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
if (argc != 4) {
puts("Incorrect usage");
return 1;
}
/* You should check the number of arguments */
char * op = argv[1];
int a = atoi(argv[2]);
int b = atoi(argv[3]);
/* You should check correct input too */
if (strcmp(op, "+") == 0)
printf("%d + %d = %d\n", a, b, a + b);
else if (strcmp(op, "-") == 0)
printf("%d - %d = %d\n", a, b, a - b);
/* Add more functions here */
return 0;
}
No you can't. The case labels of a switch need to be compile time evaluable constant expressions with an integral type.
But int literals like '+' satisfy that requirement. (As do enum values for that matter.)
Some folk like to use implementation-defined multi-character literals (e.g. 'eax') as case labels as they claim it helps readability, but at that point, you're giving up consistent behaviour across different platforms.
If you need to branch on the value of a NUL-terminated char array, then use an if block.
There are two cases to the answer ..
Firstly 6.8.4.2 (switch case)
The controlling expression of a switch statement shall have integer
type
Secondly 6.8.4.2 (the case statements)
The expression of each case label shall be an integer constant
expression and no two of the case constant expressions in the same
switch statement shall have the same value after conversion
Long story short - you can't use string literal like that. Neither in switch controlling expression nor in case.
You can do the string comparisons using strcmp and then do the if-else conditioning. The context on which you ask this, you can simply pass the character + (argv[2][0]) instead of passing the whole literal. That way you will be passing char to the switch expression and then work accordingly.
Nope, that's not possible.
Quoting C11, chapter §6.8.4.2
The controlling expression of a switch statement shall have integer type.
in your case, you don't seem to need a string but rather the first (and only character) of the string passed in the switch statement, in that case that's possible using character literal (which has integer type) in the case statements:
if (strlen(c)==1)
{
switch(c[0]){
case '+': printf(a+b);
break;
...
}
}
some good other alternatives are described in best way to switch on a string in C when the string has multiple characters.
Not directly. But yes, you can.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
// The way you store and search for names is entirely
// up to you. This is a simple linear search of an
// array. If you have a lot of names, you might choose
// a better storage + lookup, such as a hash table.
int find( const char** ss, int n, const char* s )
{
int i = 0;
while (i < n)
if (strcmp( ss[i], s ) == 0) break;
else i += 1;
return i;
}
// A bevvy of little utilities to help out.
char* strupper( char* s )
{
char* p = s;
while ((*p = toupper( *p ))) ++p;
return s;
}
char* zero( char* p ) { if (p) *p = 0; return p; }
#define STRINGIFY(S) STRINGIFY0(S)
#define STRINGIFY0(S) #S
int main()
{
// Our list of names are enumerated constants with associated
// string data. We use the Enum Macro Trick for succinct ODR happiness.
#define NAMES(F) \
F(MARINETTE) \
F(ADRIAN) \
F(ALYA) \
F(DINO)
#define ENUM_F(NAME) NAME,
#define STRING_F(NAME) STRINGIFY(NAME),
enum names { NAMES(ENUM_F) NUM_NAMES };
const char* names[ NUM_NAMES ] = { NAMES(STRING_F) NULL };
#undef STRING_F
#undef ENUM_F
#undef NAMES
// Ask user for a name
char s[ 500 ];
printf( "name? " );
fflush( stdout );
fgets( s, sizeof( s ), stdin );
zero( strchr( s, '\n' ) );
// Preprocess and search for the name
switch (find( names, sizeof(names)/sizeof(*names), strupper( s ) ))
{
case MARINETTE: puts( "Ladybug!" ); break;
case ADRIAN: puts( "Chat Noir!" ); break;
case ALYA:
case DINO: puts( "Best friend!" ); break;
default: puts( "Who?" );
}
}
Keep in mind this works by pure, unadulterated magic tricks, and is not suitable for large collections of text values.
Also, the validity of the match is entirely dependent on the degree to which you pre-process the user’s input. In this example we only ignore case, but a more advanced application might perform some more sophisticated matching.
As others pointed out in C one cannot use a string as argument to a switch, nor to its case-labels.
To get around this limitation one could map each string to a specific integer and pass this to the switch.
Looking up the mapping requires searching the map, which can be done using the Standard C bsearch() function.
An example might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>
enum Operation {
OP_INVALID = -1,
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_MAX
};
struct Operation_Descriptor {
char * name;
enum Operation op;
};
struct Operation_Descriptor operations [] = {
{"add", OP_ADD},
{"subtract", OP_SUBTRACT},
{"multiply", OP_MULTIPLY},
{"divide", OP_DIVIDE}
};
int cmp(const void * pv1, const void * pv2)
{
const struct Operation_Descriptor * pop1 = pv1;
const struct Operation_Descriptor * pop2 = pv2;
return strcmp(pop1->name, pop2->name);
}
int main(int argc, char ** argv)
{
size_t s = sizeof operations / sizeof *operations;
/* bsearch() requires the array to search to be sorted. */
qsort(operations, s, sizeof *operations, cmp);
{
struct Operation_Descriptor * pop =
bsearch(
&(struct Operation_Descriptor){argv[1], OP_INVALID},
operations, s, sizeof *operations, cmp);
switch(pop ?pop->op :OP_INVALID)
{
case OP_ADD:
/* Code to add goes here, */
break;
case OP_SUBTRACT:
/* Code to subtract goes here, */
break;
case OP_MULTIPLY:
/* Code to multiply goes here, */
break;
case OP_DIVIDE:
/* Code to divide goes here, */
break;
case OP_INVALID:
default:
fprintf(stderr, "unhandled or invalid operation '%s'\n", argv[1]);
break;
}
}
}
If on POSIX one can even use a hash table, which is the fastest way to lookup the mapping.
An example might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>
enum Operation {
OP_INVALID = -1,
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_MAX
};
struct Operation_Descriptor {
char * name;
enum Operation op;
};
struct Operation_Descriptor operations [] = {
{"add", OP_ADD},
{"subtract", OP_SUBTRACT},
{"multiply", OP_MULTIPLY},
{"divide", OP_DIVIDE}
};
int main(int argc, char ** argv)
{
if (0 == hcreate(5))
{
perror("hcreate() failed");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < s; ++i)
{
if (!hsearch((ENTRY){operations[i].name, &operations[i].op}, ENTER))
{
perror("hsearch(ENTER) failed");
exit(EXIT_FAILURE);
}
}
{
ENTRY * ep = hsearch((ENTRY){argv[1], NULL}, FIND);
switch(ep ?*((enum Operation *)ep->data) :OP_INVALID)
{
case OP_ADD:
/* Code to add goes here, */
break;
case OP_SUBTRACT:
/* Code to subtract goes here, */
break;
case OP_MULTIPLY:
/* Code to multiply goes here, */
break;
case OP_DIVIDE:
/* Code to divide goes here, */
break;
case OP_INVALID:
default:
fprintf(stderr, "unhandled or invalid operation '%s'\n", argv[1]);
break;
}
}
hdestroy(); /* Clean up. */
}

Switch Statement in C

I have the following if-statements:
if (strcmp(registerName, "zero"))
return 00000;
else if (strcmp(registerName, "at"))
return 00001;
else if (strcmp(registerName, "v0"))
return 00010;
else if (strcmp(registerName, "v1"))
return 00011;
It's actually really long - about 20 if-statements. Therefore, I would like to use a switch. How would I convert that to switch when each statement has a different condition?
I tried something as the code below, but it does not work:
int registerAddress;
switch(registerAddress) {
case 1 (strcmp(registerName, "zero")):
regsiterAddress = 00000;
break;
case 2 (strcmp(registerName, "at")):
registerAddress = 00001;
break;
}
You can't — switch statements in C only work on primitive types, not on strings. You could use, say, a hash table or a search tree to optimize the matching, but for only 20 options that may not be worth the trouble.
What you could do, to clean up the code, is set up a mapping table:
struct str2Num {
char *str;
int num;
};
const struct str2Num registerMap[] = {
{ "zero", 00000 },
{ "at", 00001 },
{ "v0", 00010 },
{ "v1", 00011 },
{ NULL, 0 } /* end marker */
};
and do your matching like this:
int i;
for (i = 0; registerMap[i].str != NULL; i++) {
if (strcmp(registerName, registerMap[i].str) == 0) {
return registerMap[i].num;
}
}
/* handle no-match case here */
In fact, if you sorted the table alphabetically, you could even use bsearch() for fast matching.
You can only switch on integers, so this will not work.
If all you're doing is converting a string to an int, store the info in an array and look through it.
struct {
const char *name;
int value;
} fooMapping[] = {
{"zero",0},
{"at",1}
....
};
int foo2value(const char *name)
{
size_t i;
for(i = 0; i < sizeof fooMapping/sizeof fooMapping[0]; i++) {
if(strcmp(name, fooMapping[i].name) == 0)
return fooMapping[i].value;
}
return -1;
}
In a switch,
switch(number) {
case 1;
case 2;
case 7;
}
you are basically saying, if number = 1, then case 1. If number = 7, case 7. So what you need to do is assign each text value, in your case "zero""at""v0" and "v1", you would need to put these into an array, and in the switch statement, instead of switch(number) you would switch an integer that would correspond with the index number of whichever text you had. So if array[3] was = "v0", you would assign an integer to the index number (3) and then switch(integer). Hope this helped.
Why not use the ? operator like so:
return
strcmp(registerName, "zero")? 00000:
strcmp(registerName, "at") ? 00001:
strcmp(registerName, "v0") ? 00010:
strcmp(registerName, "v1") ? 00011:
...
Since switch-case only works with numbers or single chars, I would use a tool like GNU's gperf to create a perfect hash and switch on that value (followed by a strcmp() to be certain of an exact match). That ought to give you the desired performance improvement.

Resources