Thread: Returning a char?

  1. #1
    Registered User Ascend's Avatar
    Join Date
    Jan 2016
    Posts
    5

    Returning a char?

    Hello All!
    I was trying to create a random card, like from a deck of cards, and I've been having some trouble. If there was a way to return a char, I feel the problem would be much easier. (I realize I could do the same thing assigning a global variable)

    I'm VERY new to coding, so take it easy on me!

    Code:
    int card (void) {
        //Draws a random card
        srand(time(NULL));
    
    
        int cardNum = rand()%13;
        int tag = rand()%4;
    
    
        //Assigns rank of card, and returns it
        if (cardNum >= 10) {
            if (cardNum == 10)
                char rank = 'J';
            else if (cardNum == 11)
                char rank = 'Q';
            else if (cardNum == 12)
                char rank = 'K';
            else if (cardNum == 13)
                char rank = 'A';
        }
        else int rank = cardNum +2;
    
    
        //Assigns suit of card, and modifies a global character
        if (tag == 0)
            suit = 'D';
        else if (tag == 1)
            suit = 'C';
        else if (tag == 2)
            suit = 'H';
        else suit = 'C';
    
    
        return rank;
    }
    I want to return the rank variable, which is either an int or a char, depending on it's original value.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You should either return a struct object representing a card with both rank and suit, or return a single number that uniquely identifies rank and suit.

    By the way, move this:
    Code:
    srand(time(NULL));
    to near the start of your main function. srand should only be called once in your program to seed the pseudorandom number generator, whereas rand would be called whenever you want to generate a pseudorandom number.
    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

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    srand() should only be called once in your program. Put it early in main.

    cardNum is rand() % 13, so it will be 0 to 12, inclusive. So cardNum == 13 will never be true. Your numbers in this section should go from 9 to 12 (Jack is 9).

    "rank variable, which is either an int or a char"
    Not in C. You need to pick one or the other. Make it a char and set it like so:
    Code:
    char rank = "23456789TJQKA"[cardNum];
    I'm not sure what you mean by "a way to return a char".
    If you want to return a char, return a char. Or have you made a double typo and meant "return a card"? I.e., you'd like to return both the rank and suit.
    Code:
    typedef struct Card {
        char rank;
        char suit;
    } Card;
    
    Card rnd_card(void) {
      Card c;
      c.rank = 'T';
      c.suit = 'H';
      return c;
    }
    Alternatively, you can represent a card as a random int from 0 to 51, inclusive. When you need the suit, just use (ncard / 13), when you want the value use (ncard % 13) (possibly + 2, depending on your purpose).
    Code:
    #include <stdio.h>
    
    #define CARD_STRING "23456789TJQKA"
    #define SUIT_STRING "CDHS"
    
    int print_card(int card) {
        printf("%c%c ", CARD_STRING[card % 13], SUIT_STRING[card / 13]);
    }
    int main(void) {
        for (int i = 0; i < 52; i++)
            print_card(i);
        putchar('\n');
        return 0;
    }

  4. #4
    Registered User Ascend's Avatar
    Join Date
    Jan 2016
    Posts
    5
    Hey guys, thanks for the help. I managed to get it working by just creating global variables and modifying them.

    As for the srand(), I used to think that it needed to be put in each one of the functions it's used in, so thanks for the update! Clearly I have much to learn...

  5. #5
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by Ascend View Post
    I managed to get it working by just creating global variables and modifying them.
    Global variables should be avoided. You should become familiar with passing values to (and returning values from) functions.

  6. #6
    Registered User
    Join Date
    Dec 2015
    Posts
    68
    Return a unsigned char
    the lower 4bits is: 1(ace) to 13 (king) value
    the next 2 bits is family: (0-3)

    char getcard(void){
    return ((rand()%13 +1) | ((rand()%4) <<4));
    }
    Last edited by tonyp12; 03-01-2016 at 08:18 PM.

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Return a unsigned char
    the lower 4bits is: 1(ace) to 13 (king) value
    the next 2 bits is family: (0-3)
    Code:
    char getcard(void){
    return ((rand()%13 +1) | ((rand()%4) <<4));
    }
    Not that different from using base-10 numbers in a similar fashion (ie suit and rank are incorporated into a unique ID number). I have a strong dislike for solutions that use bitwise operations for no apparent reason than "just because." Hardware prefers to work in larger segments of memory.

    Also, you're not special, post with code tags.

  8. #8
    Registered User
    Join Date
    Dec 2015
    Posts
    68
    Could always spilt it up on byte boundry
    Code:
    typedef union cardTag{
      unsigned int card;
      struct{
        char value;
        char family;
        };
    }cardunion; 
    
    int getcard(void){
    return ((rand()%13 +1) | ((rand()%4) <<8)); // little endian int
    }
    Last edited by tonyp12; 03-02-2016 at 12:56 PM.

  9. #9
    Registered User Ascend's Avatar
    Join Date
    Jan 2016
    Posts
    5
    Quote Originally Posted by Matticus View Post
    Global variables should be avoided. You should become familiar with passing values to (and returning values from) functions.
    Why should global variables be avoided? Is it just bad practice or do they make for a more intensive program?

  10. #10
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by Ascend View Post
    Why should global variables be avoided? Is it just bad practice or do they make for a more intensive program?
    Global variables are generally considered bad practice, especially during the learning phase.

    As programs become larger, it becomes more difficult to keep track of where global variables are updated, as their value can be changed by any functions in the same scope. This also makes reading the code more difficult, since it's not immediately obvious who might be changing their value. Additionally, this makes troubleshooting a lot more difficult for the same reason.

    Global variables also threaten modularity, which is a goal for writing clean, maintainable, and testable code. Functions should receive the data they need to work with, and return a value if necessary. Once functions start reaching outside themselves to interact with data, it becomes easier for the code to become tangled. Functions should be used to reduce coupling between pieces of code - otherwise, changing one function might accidentally break something else that relies on the same global data. This makes the program a lot more fragile, which may come back to bite you when you have to make changes later on. Functions utilizing global data also inhibit their reuse, since they become tied to that specific task.

    There are other potential problems, as well, such as conflicts if the same variable name is accidentally used elsewhere in the program, which could lead to confusing bugs.

    Most of these problems will not be encountered when you're still writing small "practice" programs, but it's still good to avoid globals. If you use them too much as a "quick fix" in the early stages, then you might come to rely on them as the size of your programs start to grow, which will eventually lead to the problems above. Also, by properly passing information to/from functions, you will develop good coding habits and cleaner logic as your experience develops over time.

  11. #11
    Registered User Ascend's Avatar
    Join Date
    Jan 2016
    Posts
    5
    Yea, that makes sense.

    Thanks Matticus!

  12. #12
    Registered User
    Join Date
    Nov 2012
    Posts
    157
    Quote Originally Posted by whiteflags View Post
    Hardware prefers to work in larger segments
    Care to explain?

  13. #13
    Registered User
    Join Date
    Dec 2015
    Posts
    68
    Some MCU/CPU don't have good bit access or they have limited like ARM's bitfield shadow memory trick that it's only good for one bit at a time.
    TI's MSP430 have BitTest,BitClear and BitSet instructions so it handles bits pretty good.
    But copy bit-pair's from one bitfield to another bitfield you need 4-6 instructions, so that should be avoided.

  14. #14
    Registered User
    Join Date
    Nov 2012
    Posts
    157
    I see. Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. returning char *
    By Abda92 in forum C Programming
    Replies: 14
    Last Post: 12-03-2007, 02:19 PM
  2. Returning char *
    By MacNilly in forum C++ Programming
    Replies: 4
    Last Post: 09-28-2007, 03:03 AM
  3. Help Returning char*
    By Deb in forum C Programming
    Replies: 14
    Last Post: 04-17-2007, 05:02 PM
  4. returning a value with char
    By kashifk in forum C++ Programming
    Replies: 5
    Last Post: 07-14-2003, 07:28 AM
  5. Returning char*
    By knutso in forum C++ Programming
    Replies: 7
    Last Post: 01-13-2003, 12:29 PM