Thread: help with switch statement

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    67

    help with switch statement

    can this chuck of if-else if statements can be converted into switch statement format? thanks
    Code:
    int search_opcode (char opcode[LENGTH])
    {
        if (( strcmp ("add", opcode) == 0) || (strcmp ("sub", opcode) == 0)
            || (strcmp ("mul", opcode) == 0) || (strcmp ("and", opcode) == 0)
            || (strcmp ("or", opcode) == 0) || (strcmp ("xor", opcode) == 0)
            || (strcmp ("nor", opcode) == 0) || (strcmp ("sllv", opcode) == 0)
            || (strcmp ("srlv", opcode) == 0)){
                return 1;
            }else if ((strcmp ("lw", opcode) == 0) || (strcmp ("sw", opcode) == 0)){
                return 2;
            }else if ((strcmp ("addi", opcode) == 0)){
                return 3;
            }else if ((strcmp ("mfhi",opcode) == 0) || (strcmp ("mflo", opcode) == 0)
            || (strcmp ("mthi", opcode) == 0) || (strcmp ("mtlo", opcode) == 0)
            || (strcmp ("jr", opcode) == 0)){
                return 4;
            }else if ((strcmp ("beq", opcode) == 0) || (strcmp ("bne", opcode) == 0)){
                return 5;
            }else if ((strcmp ("bltz", opcode) == 0) || (strcmp ("blez", opcode) == 0)
            || (strcmp ("bgtz", opcode) == 0) || (strcmp ("bgez", opcode) == 0)){
                return 6;
            }else if ((strcmp ("b", opcode) == 0) || (strcmp ("j", opcode) == 0)
            || (strcmp ("jal", opcode) == 0)){
                return 7;
            }else if (strcmp ("nop", opcode) == 0){
                return 8;
            }else if ((strcmp ("break", opcode) == 0) || (strcmp ("syscall", opcode) == 0)){
                return 9;
            }else{
                return -1;
        }
    }

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, it's not possible, because a switch statements needs a constant expression, something that can be evaluated at compile time, and a function call cannot.
    Or consequently, it may be possible with things such as hash tables, but that may be somewhat advanced.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, it is possible, but personally I do not like it:
    Code:
    switch (1)
    {
    case a == 0 || x == 0:
        return 1;
    case b == 0 || y == 0:
        return 2;
    case z == 0:
        return 3;
    default:
        return -1;
    }
    EDIT:
    hmm... decided to check, and I am wrong. It is indeed true that the label must evaluate to a constant, so this trick does not work in C. That is good to hear, in my opinion
    Last edited by laserlight; 07-02-2008 at 11:51 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Here's one way to do it. Without a switch, but still, much more readable than what you have.
    Code:
    int search_opcode (char opcode[LENGTH])
    {
        const char *one[] = {"add", "sub", /* ... */};
        const char *two[] = {"lw", "sw"};
        const char *three[] = {"addi"};
        struct {
            const char **data;
            size_t n;
        } data[] = {
            {one, sizeof one},
            {two, sizeof two},
            {three, sizeof three}
        };
        size_t x, y;
        
        for(x = 0; x < sizeof(data) / sizeof(*data); x ++) {
            for(y = 0; y < data[x].n; y ++) {
                if(!strcmp(opcode, data[x].data[y])) return x + 1;
            }
        }
        
        return -1;
    }
    I'm sure you could do it without naming the "one", "two", etc. arrays, but then you'd likely have to hard-code how many strings there were for each one. This way, all of the counting is done for you. If you want to add a string, just do it; you don't have to change any numbers or anything.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    67
    Hi. I know this is an old post but I have been unsuccessful at trying to implement the above code by dwks. At first I tried it out and it seemed only to work when I passed it a string that was present in the const char *one[] array. For everything else it gave me a Bus Error. However, upon further inspection I discovered that substituting
    Code:
    return x + 1;
    with
    Code:
    return x;
    revealed that the function actually returned 0.
    I tried fixing the code but I cannot do much since I do not fully understand what goes on in the following loop:
    Code:
    for (x = 0; x < sizeof (data) / sizeof (*data); x++){
            for (y = 0; y < data[x].n; y++){
                if (!strcmp (opcode, data[x].data[y]))
                    return x + 1;
            }
        }
    Can someone please explain what exactly goes on in that loop and where the code can be fixed in general so it would achieve its goal of replacing the clunky code I had in the beginning of this post?
    Thanks a lot.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The x+1 represents the value you return - which is 1..9 in your original code.

    Since arrays start at zero, the index (x) that you find the instruction at will be zero for the first lot of values - but you return one.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Try this:
    Code:
    int search_opcode (const char *opcode)
    {
       const char *one[] = {"add", "sub"};
       const char *two[] = {"lw", "sw"};
       const char *three[] = {"addi"};
       struct {
          const char **data;
          size_t n;
       } data[] = {
          {one, sizeof one / sizeof *one },
          {two, sizeof two / sizeof *two },
          {three, sizeof three / sizeof *three}
       };
       size_t x, y;
    
       for(x = 0; x < sizeof(data) / sizeof(*data); x ++) {
          for(y = 0; y < data[x].n; y ++) {
             if(!strcmp(opcode, data[x].data[y])) return x + 1;
          }
       }
    
       return -1;
    }
    
    int main()
    {
       printf("Opcode for &#37;s: %d\n", "add", search_opcode("add"));
       printf("Opcode for %s: %d\n", "addi", search_opcode("addi"));
    
       return 0;
    }
    Last edited by rags_to_riches; 08-25-2008 at 01:21 PM.

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    67
    Ok now I understand that bit, but how do I solve the bus error problem?? Whenever, I pass it something like "lw" or "addi", which are both not in the first array I keep getting Bus Error and I don't know where this code goes wrong in order to fix it.
    Thanks

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    67
    Thanks rag_to_riches. It all seems to work now!! I will add more string arrays and test it.
    Thanks a lot!!!

  10. #10
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    I'll usually just format my code to make it easier to read / maintain:

    Code:
    int search_opcode (char opcode[LENGTH])
    {
    	if  (
    		(strcmp ("add" , opcode) == 0) || 
    		(strcmp ("sub" , opcode) == 0) || 
    		(strcmp ("mul" , opcode) == 0) || 
    		(strcmp ("and" , opcode) == 0) || 
    		(strcmp ("or"  , opcode) == 0) || 
    		(strcmp ("xor" , opcode) == 0) || 
    		(strcmp ("nor" , opcode) == 0) || 
    		(strcmp ("sllv", opcode) == 0) || 
    		(strcmp ("srlv", opcode) == 0) 
    		) {
        		return 1;
            }
    	else if (
    		(strcmp ("lw", opcode) == 0) || 
    		(strcmp ("sw", opcode) == 0)
    		) {
    			return 2;
    		}
    	else if (
    		(strcmp ("addi", opcode) == 0)
    		) {
    			return 3;
    		}
    	else if (
    		(strcmp ("mfhi", opcode) == 0) || 
    		(strcmp ("mflo", opcode) == 0) || 
    		(strcmp ("mthi", opcode) == 0) || 
    		(strcmp ("mtlo", opcode) == 0) || 
    		(strcmp ("jr"  , opcode) == 0) 
    		) {
    			return 4;
    		}
    	else if (
    		(strcmp ("beq", opcode) == 0) || 
    		(strcmp ("bne", opcode) == 0)
    		) {
    			return 5;
    		}
    	else if (
    		(strcmp ("bltz", opcode) == 0) || 
    		(strcmp ("blez", opcode) == 0) || 
    		(strcmp ("bgtz", opcode) == 0) || 
    		(strcmp ("bgez", opcode) == 0) 
    		){
    			return 6;
    		}
    	else if ( 
    		(strcmp ("b"  , opcode) == 0) || 
    		(strcmp ("j"  , opcode) == 0) || 
    		(strcmp ("jal", opcode) == 0)
    		){
    			return 7;
    		}
    	else if (strcmp ("nop", opcode) == 0) { 
    		return 8;
    	}
    	else if ( 
    		(strcmp ("break"  , opcode) == 0) || 
    		(strcmp ("syscall", opcode) == 0)
    		){
    			return 9;
    		}
    	else{
    		return -1;
    	}
    }
    Mainframe assembler programmer by trade. C coder when I can.

  11. #11
    Registered User
    Join Date
    Aug 2008
    Location
    PA, USA
    Posts
    11
    I can even use the following also (Though not switch statement)

    Code:
    #include <stdio.h>
    struct {
            char opcode[5];
            int ret_val;
           } my_struct[] = {{"add", 1},
                            {"sub", 1},
                            {"lw",  2},
                            {"sw",  2},
                            {"addi",3}};
    
    main()
    {
        printf("Returned value %d\n", search_opcode("addi"));
    }
    int search_opcode(char *opcode)
    {
        int i = 0;
        int val = 0;
        val = sizeof(my_struct)/sizeof(my_struct[0]);
        for (i=0; i <= val; i++)
        {
            if (!strcmp(opcode, my_struct[i].opcode))
            {
                return my_struct[i].ret_val;
            }
        }
        return 99;
    }

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    for (i=0; i <= val; i++)
    I think by using <= instead of <, you've created a buffer overrun there.

    Oh, and returning 99 probably isn't a good idea. int is signed, so go with a negative number or INT_MAX or something.

    That's a good way of doing it, though. I hadn't thought of that.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mutli Switch statement help
    By elwad in forum C Programming
    Replies: 9
    Last Post: 05-09-2009, 03:19 AM
  2. Switch statement / default:
    By kcpilot in forum C Programming
    Replies: 4
    Last Post: 12-02-2008, 03:14 PM
  3. switch statement
    By guillermoh in forum C Programming
    Replies: 5
    Last Post: 03-10-2008, 02:17 PM
  4. char switch statement
    By jmarsh56 in forum C++ Programming
    Replies: 7
    Last Post: 05-03-2006, 05:04 PM
  5. Efficiency with the switch() statement...
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 10-14-2001, 02:47 PM