Thread: Simple problem, I hope...

  1. #1
    Registered User
    Join Date
    Feb 2011
    Posts
    5

    Simple problem, I hope...

    Hi, I'm new to programming in general and I'm attempting to write a text based game of black jack for a bit of practice. I've just started the project and run into something weird that I really can't explain. So far all I'm doing is defining a function that creates a data structure database for each individual card and having the main function print the suit and a number value corresponding to how many "cards" are in the deck. I can't figure out why it spits back junk for cards 2 - 7 and then proceeds to print correctly. Any ideas? When it prints, it looks like this:

    Code:
    h deckValue = 1
     deckValue = 1
    \304 deckValue = -1809827132
    \206 deckValue = -1605732986
    \206 deckValue = -1605732986
     deckValue = 2139062143
    h deckValue = 32639
    h deckValue = 8
    h deckValue = 9
    h deckValue = 10
    h deckValue = 11
    h deckValue = 12
    h deckValue = 13
    d deckValue = 14
    d deckValue = 15
    d deckValue = 16
    d deckValue = 17
    d deckValue = 18
    d deckValue = 19
    d deckValue = 20
    d deckValue = 21
    d deckValue = 22
    d deckValue = 23
    d deckValue = 24
    d deckValue = 25
    d deckValue = 26
    c deckValue = 27
    c deckValue = 28
    c deckValue = 29
    c deckValue = 30
    c deckValue = 31
    c deckValue = 32
    c deckValue = 33
    c deckValue = 34
    c deckValue = 35
    c deckValue = 36
    c deckValue = 37
    c deckValue = 38
    c deckValue = 39
    s deckValue = 40
    s deckValue = 41
    s deckValue = 42
    s deckValue = 43
    s deckValue = 44
    s deckValue = 45
    s deckValue = 46
    s deckValue = 47
    s deckValue = 48
    s deckValue = 49
    s deckValue = 50
    s deckValue = 51
    s deckValue = 52
    Last edited by Polaris84; 02-24-2011 at 01:40 AM. Reason: error in print

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    How about putting some code in those code tags?

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by anduril462 View Post
    How about putting some code in those code tags?
    You're hopeless, Anduril!

    You STILL want to see ACTUAL CODE, to debug a C program?

    Must be a slow learner!!

  4. #4
    Novice
    Join Date
    Jul 2009
    Posts
    568
    He's new here, and telepathic abilities take time to develop.
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Polaris84 View Post
    Hi, I'm new to programming in general
    While the others are having their little joke the fact is there's nothing in what you posted that even remotely resembles C programming code.

    If you haven't already, you need to grab a good book on the topic or at least read some of the many tutorials on the web.

    Here's the local one to start with...
    Cprogramming.com - Programming Tutorials: C++ Made Easy and C Made Easy

    There's also a list of book recommendations here...
    C Book Recommendations

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Adak View Post
    You're hopeless, Anduril!

    You STILL want to see ACTUAL CODE, to debug a C program?

    Must be a slow learner!!
    I'd prefer it if they mailed me their punch cards, but I'm trying real hard to adapt to this new-fangled interweb thing.

    @Polaris84
    Do post your code for this so we can help you. My first two guesses would be uninitialized variables or buffer overflow somewhere, but it's really hard to say without seeing your code.

  7. #7
    Registered User
    Join Date
    Feb 2011
    Posts
    5
    Haha, right, code might help you. So I have made a temporary fix that keeps everything printing right, but it seems unnecessary. Here is the code for creating the deck of cards.

    Code:
    #include "deck.h"
    #include "main.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    
    
    void	intializeDeck()
    {
    	struct	Card*	newCard = NULL;
    	int		deckOf52 = 1;	// keeps track of how mand cards are in the deck and gives deckValue its value.
    	int		x = 0;		// gCard array value.
    	int		y = 2;		// used to give numCard face value.
    	int		z = 1;		// used to give card numarical value.
    	
    	while (deckOf52 < 53)
    	{
    		if(deckOf52 < 14)
    		{
    			gCard[ x ].suit = 'h';
    		}
    		if(deckOf52 > 13 && deckOf52 < 27)
    		{
    			gCard[ x ].suit = 'd';
    		}
    		if(deckOf52 > 26 && deckOf52 < 40)
    		{
    			gCard[ x ].suit = 'c';
    		}
    		if(deckOf52 > 39)
    		{
    			gCard[ x ].suit = 's';
    		}
    		if( z == 1 )
    		{
    			gCard[ x ].nonNumCard = 'A';
    		}
    		else 
    		{
    			if( z == 11 )
    
    			{
    				gCard[ x ].nonNumCard = 'J';
    			}
    			else
    			{
    				if( z == 12 )
    				{
    					gCard[ x ].nonNumCard = 'Q';
    				}
    				else
    				{
    					if( z == 13 )
    					{
    						gCard[ x ].nonNumCard = 'K';
    					}
    					else
    					{
    						gCard[ x ].numCard = y;
    					}
    				}
    			}
    		}
    		
    		gCard[ x].cardValue = z;
    		
    		z += 1;
    		if( z == 14 )
    			z = 1;
    		
    		gCard[ x ].deckValue = deckOf52;
    		
    		y += 1;
    		
    		if(gCard[ x ].nonNumCard == 'A' || gCard[ x ].nonNumCard == 'J' || gCard[ x ].nonNumCard == 'Q' || gCard[ x ].nonNumCard == 'K')
    		{
    			y = 2;
    		}
    		if( y == 11 )
    		{
    			y = 2;
    		}
    		
    		deckOf52 += 1;
    		x += 1;
    		
    		newCard = realloc(gCard , 1 + sizeof(struct Card));
    		gCard = newCard;
    	}
    	
    }
    and how I'm printing them now with the fix I mentioned

    Code:
    #include "deck.h"
    #include "main.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    
    struct	Card*	gCard = NULL;
    
    int main ()
    {
    	int		x = 0;
    	
    	gCard = malloc(sizeof(struct Card));
    	
    	printf("Black Jack!\n\n");
    	
    	while(x < 52)
    	{
    		intializeDeck();	// function used to be called before this loop when I was having the problem
    		
    		if(gCard[ x ].nonNumCard == 'A' || gCard[ x ].nonNumCard == 'J' || gCard[ x ].nonNumCard == 'Q' || gCard[ x ].nonNumCard == 'K')
    			printf("%c of %c   deckValue = %d   cardValue = %d\n\n" , gCard[ x ].nonNumCard ,  gCard[ x ].suit , gCard[ x ].deckValue , gCard[ x ].cardValue);
    		else
    			printf("%d of %c   deckValue = %d   cardValue = %d\n\n" , gCard[ x ].numCard ,  gCard[ x ].suit , gCard[ x ].deckValue , gCard[ x ].cardValue);
    		
    		x += 1;
    	}
    	
    	
    	
    	return 0;
    }
    OH, and here is the data struct declaration.

    Code:
    struct	Card
    {
    	int		cardValue;			// Numerical value of card, such as Jack = 11, A = 1 or 11, Queen = 12, etc.
    	int		deckValue;			// deckValue = the numerical value of the card in the deck of 1 - 52, starting from "Ah" being "1", "2h" being "2", etc.
    	char	suit;
    	char	nonNumCard;
    	int		numCard;
    };
    
    struct	Card*	gCard;
    Last edited by Polaris84; 02-24-2011 at 01:47 PM. Reason: forgot to add some code

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    So the big problem seems to be that you call realloc with 1+sizeof(struct Card) bytes. That doesn't grow it by 1 each time, that simply takes gCard, and makes sure it's reallocated to only one more byte than a single card needs. This will mean gCard[x] is out of bounds for any x other than 0. You actually don't need to dynamically allocate space for your deck at all. There will always be 52 cards. Make a constant (something like CARDS_IN_DECK) and an array, like Card deck[CARDS_IN_DECK].

    You really only need to keep track of the suit and face value. You can create an enum for suit and just use 0-12 for the face. Use a functions to get the cards playing value, suit and face. It will mean only one type of printf for displaying a card (instead of the two you have in main). For example:
    Code:
    enum {
        HEARTS,  // this defaults to 0
        DIAMONDS
        ...
    };
    char getSuit(Card *c)
    {
        switch (c->suit) {
            case HEARTS:
                return 'h';
                break;
            ...
        }
    }
    You can use / and % instead of your if (deckOf52 > 26 && deckOf52 < 40) to make assigning suit and face easier:
    Code:
    for (card_num = 0; card_num < CARDS_IN_DECK; card_num++) {
        deck[card_num].suit = card_num / CARDS_IN_SUIT;  // this would be a constant defined as 13
        deck[card_num].face = card_num % CARDS_IN_SUIT;
    I don't really understand what you're using x, y and z for, but I'm pretty sure they're not really necessary (besides, you're assigning y to numCard without actually setting it).

    Some general notes that might clean up your code a bit:
    • Global variables are evil. Declare them in the appropriate function and pass them around.
    • x += 1; can be turned into the more common x++;
    • Replace your while loops with for loops (they're easier to read for array and counting loops). E.g.

    Code:
    x = 0;
    while (x < 42) {
        x++;
    }
    // same as the cleaner, more common:
    for (x = 0; x < 42; x++) {
    }
    That's all I have for now, but it should keep you busy for a while.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Macros are fun.

    #define SUIT(card) ("CDHS"[((card)/13)%4])
    #define FACE(card) ("A23456789TJQK"[(card)%13])


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Feb 2011
    Posts
    5
    Okay, thanks for the tips, this is all stuff I haven't considered. The tutorial I read seemed to discourage the use of switch() statements since there is no real disadvantage to using if() statements and they are "more versatile", but lots of people seem to use switch() over if(). I have been meaning to incorporate the for() loop more often, but I got all nice and cozy with the while() loop that I just don't like to touch them. I can see what you mean about making it easier to read, but only in some cases when the meat of the loop can all be stated in one set of parameters, i.e. when x is the only variable being altered in the loop. x y & z are all just expendable int's that I can use to do calculations when I need to. They're values and purpose can be changed but generally I use them for similar purposes throughout code. In intializeDeck() function, y tracks number cards by resetting back to '2' once it reads z = the value of a char card(1,11,12,&13). z tracks the play value of the card(1 -13).

    Also, how can globals be all that bad? It seems like they can prevent you from doing a lot of work. It seems like you should have all of your most important variables and data that your whole program will be using in one place, that is if it needs to be consistent data passed around in multiple functions in multiple libraries. If something goes wrong, you don't have to potentially sift through several files of code because your only tossing variables into functions and returning them. In this case, the ONLY global I'm truly using is a struct pointer because that struct and its contents will need to be called within other functions in order to obtain info on one card, i.e. in a shuffleDeck() function, or dealDeck() function. Seems way easier to see and know its all in one place.
    Last edited by Polaris84; 02-25-2011 at 12:19 AM. Reason: 1

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    In C, global variables are more of a headache, since C programs tend to use pointers a lot.

    When the structs are prototyped globally, but the variable or struct array itself is local and passed around to other functions as needed, it gives you the best encapsulation of the variables and makes bug hunting, a LOT easier.

    The classic one is where you have a global variable, and accidentally name a local variable with that same name. The local "covers up" the global and although you know everything checks out in the local function, it somehow "dies" when the program returns from that function. WTF??

    In a blackjack program, having the deck of cards global seems intuitively right. It's such a small program, and there is just one deck in play at a time, etc. With larger programs, I'd make everything local if you can.

    I used to use globals heavily, coming from QBASIC. Now it's rare that I use one global variable in a program.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Globals generally hurt more than they help, and it's a practice I think should be discouraged when learning C. There are times when globals are appropriate, but IMO, this is not one of them. To be fair, this is not a horrible use of them, but there's no really good case for this either, other than "I don't want to pass it around".

    Your arguments for globals are common fallacies. The small effort of passing them around greatly outweighs the headaches that come with debugging code that uses globals. You actually have to sift through more code with globals, because anything could have changed the global variable, instead of just a handful of functions. Think of it this way: if you have a tool that others want to use, you can either leave it on your front porch and let whoever use it when they want (globals), or you can only loan it out to individuals who come and ask for it in person (locals). If your tool comes back broken or doesn't come back at all, which scenario makes it easier to determine who's responsible for the loss/damage (bug)?

    The link in my previous post gives a good discussion on the topic, so here it is again: Global Variables Are Bad.

  13. #13
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Polaris84 View Post
    Also, how can globals be all that bad?
    Code:
    #include <stdio.h>
    
    int a = 0; 
    
    int multiply(int q)
      { int x = 1 ;
         for (a = 2; a < 6; a ++)
             x *= q;
         return x; }
    
    int main (void)
      { int z;
         printf("Enter a 3 digit number : ");
         scanf("%d",&a);
         z = multiply( a );
         
         printf (Input = %d  Result = %d\n\n",a,z);
         return 0;
    }
    Now... imagine multiply() is half way down a 10,000 line program... have fun finding it!
    Last edited by CommonTater; 02-25-2011 at 01:03 PM.

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by CommonTater View Post
    Now... imagine multiply() is half way down a 10,000 line program... have fun finding it!
    CTRL+F


    Quzah.
    Hope is the first step on the road to disappointment.

  15. #15
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by quzah View Post
    CTRL+F
    Quzah.
    I meant finding "the bug"... You can search for every instance of a, but that's a lot of searching... and it might not easily lead you to what is changing the value of a.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with piping in my simple UNIX shell
    By Integral Birth in forum C Programming
    Replies: 0
    Last Post: 11-28-2010, 07:37 PM
  2. A simple file I/O problem
    By eecoder in forum C Programming
    Replies: 10
    Last Post: 10-16-2010, 11:00 PM
  3. Simple File I/O problem
    By Ignited in forum C++ Programming
    Replies: 3
    Last Post: 01-07-2006, 10:49 AM
  4. Fairly simple problem
    By fatdunky in forum C Programming
    Replies: 1
    Last Post: 11-14-2005, 11:34 PM
  5. Bob Hope, dead at 100 of being really old
    By Govtcheez in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 07-28-2003, 08:04 AM