#1
  1. Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Location
    Liverpool, UK
    Posts
    0
    Rep Power
    0

    Poping structs into two arrays from a stack?...


    Hi

    I'm creating a program which splits a deck of card into two. The card data is read into a struct which is then pushed onto a stack. This happens for all cards. This bit is done.

    I now need to pop the data on the stack into two one-dimensional arrays. One for each half of the pack, (ie. a straight split).

    Could someone help please.

    Here's the code done so far:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #define CARDS_ARRAY 52
    
    
    /* define struct type */
    struct card_record
            {
                    int value ;
                    char suit ;
                    int position ;
            struct card_record *next ;
            } ;
    typedef struct card_record *LINK ;
    LINK listhead = NULL ;
    
    main ()
    {
    /*
    prepare to proces file and read first card
    WHILE not at end of file
       push record on to stack
       read next name
    */
    
    void push (struct card_record *) ;
    void pop () ;
    FILE *cards = fopen ("cards.dat", "r") ;
    struct card_record card ;
    
    fscanf (cards, "%d%c%d", &card.value, &card.suit, &card.position) ;
    while (feof (cards) == 0)
            {
            push (&card) ;
            fscanf (cards, "%d%c%d", &card.value, &card.suit, &card.position) ;
            }
    
    
    }
    
    
    
    
    
    
    /* function to push struct onto the stack */
    void push (struct card_record * this_card)
    {
    /*
    create new dynamic variable
    assign data and link to list head
    */
    LINK newpointer = malloc (sizeof (struct card_record)) ;
    if (newpointer == NULL)
            {
            printf ("no memory available\n") ;
            exit (1) ;
            }
    else
            {
            newpointer = this_card ;
            newpointer->next = listhead ;
            listhead = newpointer ;
            }
    }
    
    
    /* function to pop struct from the stack */
    void pop ()
    {
    
    
    
    
    
    }
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,642
    Rep Power
    4247
    The code seems to be a mix of C and C++ there :). IIRC, the statement:
    newpointer = this_card ;
    will never work in a pure C compiler (you have to copy each element of the struct individually), but works in a C++ compiler. Anyways, back to your assignment at hand :) If you want to implement a pop() function (which I think this assigment is really about), then you could do something like this:
    Code:
    LIST pop() {
        LIST ptr;
        ptr = listhead;
        listhead = ptr->next;
        return ptr;
    }
    Now, if you only want to split the list in two, you could save some time and write a function that does just that instead of popping and pushing things about. I'm assuming here that the deck has 52 cards. If not, iterate through your linked list and get the actual count. Also, for the purpose of this assignment, I'm declaring global pointer variables cut1 and cut2. Normally, in production code, I'd never declare them globally and instead pass them as params to the functions push() and pop(). That's left as an exercise for you to complete (I noticed you have listhead declared globally as well and decided to go with the flow).
    Code:
    LINK listhead = NULL ;
    LINK cut1 = NULL, cut2 = NULL;
    
    void cut_deck() {
        int max_cards = 52; /* Assuming there are 52 cards. If not, iterate thru list and get the actual count */
        LINK cuttemp;
        int i;
        cut1 = cut2 = listhead;
    
        /* Go down to the middle of the list and get the ptr to the middle card */
        for (i = 0; i < max_cards/2; i++)
            cut2 = cut2->next;
        
        /* Now split the decks into two */
        cuttemp = cut2;
        cut2 = cut2->next;
        cuttemp->next = NULL;
      
        /* Now cut1 and cut2 have the two halves of the deck */
    }

    Hope this helps! Remember you owe me half of that 'A' grade :D
  4. #3
  5. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    Tampa, Florida
    Posts
    31
    Rep Power
    13
    I'm sorry to jump in the middle of something, but I'm confused right out of the gate. Programming in Linux and using C, I create a struct like...

    typedef struct
    {
    /* define stuff */
    } name_of_struct;

    But, in the first example at the top, it's...

    struct
    {
    /* define stuff */
    } ;

    What gives? Is this a difference of compilers? When I try to compile with the second example, I get errors.


    Later on,
    BDKR
  6. #4
  7. /(bb|[^b]{2})/

    Join Date
    Nov 2001
    Location
    Somewhere in the great unknown
    Posts
    5,163
    Rep Power
    792
    This can be done either way, the second example you listed is just missing the struct name.
    i.e.
    Code:
    struct struct_name {
    //body of struct
    };
    That is valid code as long as you give it a name.
  8. #5
  9. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,642
    Rep Power
    4247
    Actually they are not quite the same thing and when you use typedef, then it is typedef struct {...} name_of_typedef; rather than name_of_struct;. There are minor differences that I'm going to describe below
    Code:
    Example 1:
    struct example1 {
      /* Stuff */
    };
    
    Example 2:
    struct {
      /* Stuff */
    } foo, bar;
    
    Example 3:
    typedef struct example3 {
      /* Stuff */
    } type3;
    
    Example 4:
    typedef struct {
       /* Stuff */
    } type4;
    Now these three are valid declarations of structures. So what's the difference, you ask? The difference is shown when you declare the variables for the struct type.
    Code:
    Variable declarations for example1:
    struct example1 foo, bar;
    
    Variable declarations for example 2:
    Don't need any here, as they were already declared with the struct
    
    Variable declarations for example 3:
    struct example3 foo;
    type3 bar;
    
    Variable declarations for example 4:
    type4 foo, bar;
    The key here is the variable declarations for example 3. When you use a typedef with a struct, you're really making a synonym for struct struct_name. So all that the typedef does is create a shorthand for "struct example3" and calls it "type3". So declaring the variables either way are equivalent to the same thing. In example 4, the compiler creates an "anonymous" structure name and makes the typedef for "type4" as a synonym for "struct anonymous_struct_name". You don't know what this "anonymous_struct_name" is and leave the typedef keyword to take care of the details. In example 2, the compiler creates an anonymous struct name as in example 4 and allocates the two variables for it at the same time ---- however you can't declare more variables of type example2 elsewhere in the code because you don't know the anonymous_name of the struct.

    In case of structures that refer to instances of themselves (as in a linked list), you can use both a typedef and a struct as in example 3:
    Code:
    typedef struct card_record
            {
                    int value ;
                    char suit ;
                    int position ;
                    struct card_record *next ;
            } * LINK ;
    LINK foo;
    struct card_record *bar;
    The variables foo and bar are both pointers to the structure and could have been declared either way. Note that you need the name of the struct (card_record) because you can't declare the element "next" as "LINK next", cuz the typedef doesn't get seen until the end of the declaration.

    Hope this helps
  10. #6
  11. Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Location
    Liverpool, UK
    Posts
    0
    Rep Power
    0
    Cheers for the help.

    I'm learing C, but using Borland C++ to compile, so I guess that'll just plough through the mixture of code.

    What's still confusing me is how I get the data off the stack onto two arrays. I'm assuming that I read the data from the stack using the pointers that were created in the new code.

    Thanks again.

    Rob
  12. #7
  13. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Location
    Tampa, Florida
    Posts
    31
    Rep Power
    13
    Hey Scorpions4ever,

    Good stuff. I'm still chewing on it, but thanx for writing it. Structures seem extremely powerful and as a result, I"m very interested.

    Now I just need to get the pointers to structures to work.

    Later on,
    BDKR
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    What makes it a mixture of C and C++? It looks like straight C to me. Also, why would the newpointer = this_card statement not work?
  16. #9
  17. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,642
    Rep Power
    4247
    Originally posted by 3dfxMM
    What makes it a mixture of C and C++? It looks like straight C to me. Also, why would the newpointer = this_card statement not work?
    My bad here, I should have been more clear, and anyways the issue pertains more to K&R C rather than ANSI C (and should no longer hold true for all modern C compilers) -- good catch there! The code below should explain it all:
    Code:
    struct my_struct {
      int a, b;
    };
    
    struct my_struct foo, bar;
    
    /* Initialize foo */
    foo.a = 1;
    foo.b = 2;
    
    /* Copy foo into bar */
    bar = foo; /* Ok in C++ and ANSI C. Illegal in K&R C */
    /* The following is legal in all C and C++ styles */
    bar.a = foo.a;
    bar.b = foo.b;
    It turns out that K&R's C compiler did actually handle the assignment code correctly, even though their own book said that it didn't! However, I'd encountered this same problem on another early C compiler that claimed to be ANSI compliant at that time. See the comp.lang.c FAQ http://www.eskimo.com/~scs/C-faq/q2.7.html for more details. This should no longer be an issue with modern C compilers.

    BTW, the code at hand above (newpointer = this_card;) does appear to have a memory leak, unless I'm suffering from a serious lack of sleep here. The function push() is allocating new memory using malloc() and assigning it to newpointer,. Then, it appears to me that newpointer is pointed to the passed argument (instead of copying the contents of the passed argument into the newly allocated memory)!

    Also, I would typecast the pointer returned by malloc to the proper type something like this (just to avoid warnings from the compiler):
    LINK newpointer = (LINK) malloc(sizeof(struct card_record));
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    Your sample code is attempting to assign structure contents in one shot. The newpointer = this_card line doesn't. It just assigns one pointer to another. Unfortunately, this doesn't accomplish what the author intended. You are right about the memory leak, but the problem goes deeper than that. Every time push( &card ) is called, a new card_record is allocated. The only pointer to that card is then overwritten with the address of the card on the caller's stack. newpointer's next field is assigned a NULL the first time and every time after that it points to the card that was passed in. listHead is then set to point to the card from the caller's stack. The next, and all subsequent times, through the code, newpointer's next field and listHead are set to point to the card passed in. At the end, the caller is left with a linked list of one card, the last one pushed.
  20. #11
  21. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,642
    Rep Power
    4247
    Yep, that's what I meant when I said that he was pointing newpointer to the passed argument (instead of copying the contents over). The only thing that the linked list will point to is the variable 'card'.

IMN logo majestic logo threadwatch logo seochat tools logo