Thread: Array of pointers to a struct

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    4

    Array of pointers to a struct

    I am working on an assignment identical to another post from a couple years ago, for reference here is the thread:

    array of pointers to structures sorting addresses by zip code

    They way it is written on that thread is almost identical to the way the teacher implied to have it done (only wrote part of the input block) and that thread helped me understand a lot more what was actually going on. But I am having an error:

    When it gets to the output section it outputs then next name along with the zip code... I tried strncpy and strxfrm but both cause more problems than they did help.

    The last part of the project is to have the output put out in order of least zip code to most zip code (00000<99999), so this is causing me a real problem and I do not see what exactly is making this happen.

    Here is my code (we dont HAVE to use gets but professor suggested using it for this assignment, next lab is to rewrite this using files and fgets rather than I/O redirection):

    header.h
    Code:
    #ifndef lab_6b_7b_Header_h
    #define lab_6b_7b_Header_h
    
    //header file intiating other headers
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct{
        char name[25];
        char street[25];
        char state[25];
        char zip[5];
    }INFORMATION;
    
    typedef INFORMATION *INFOPTR;
    
    //function prototypes
    void INPUT(INFORMATION *work[], int *);
    void OUTPUT(INFORMATION *work[], int *);
    
    #endif

    main.c
    Code:
    #include "header.h"
    
    int main(void)
    {
        //Intiate program
        int count=0;
        INFORMATION *work[50];
    
        //call input function
        INPUT(work, &count);
        
        //sort files
        //call function
        
        //call output function
        OUTPUT(work, &count);
        
        //end program
        return 0;
    }

    input.c
    Code:
    #include "header.h"
    
    void INPUT(INFORMATION *work[], int *count)
    {
        //initiate struct pointer and a blank sting for reading position]
        char location[25];
        *count=0;
        INFOPTR INFO;
    
        //while loop to get persons information and move it into a malloc array via pointers
        while ((gets(location)!=NULL)&&(*count<50)) {
            INFO=(INFOPTR)malloc(sizeof(INFORMATION));
            strcpy(INFO->name,location);
            getchar();
            gets(INFO->street);
            getchar();
            gets(INFO->state);
            getchar();
            gets(INFO->zip);
            getchar();
            //counter for array position
            work[(*count)++]=INFO;
        }
        return;
    }

    output.c
    Code:
    #include "header.h"
    
    void OUTPUT(INFORMATION *work[], int *count)
    {
        int i=0;
        for (i=0;i<(*count);i++) {
            printf("%s\n%s\n%s\n%s\n", work[i]->name, work[i]->street, work[i]->state, work[i]->zip);
        }
    }

    And here is my input:
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    B1, B2
    19831 Henshaw St
    Culver City, CA
    94023
    C1, C2
    5142 Dumont Pl
    Azusa, CA
    91112
    D1, D2
    20636 De Forest St
    Woodland Hills, CA
    91364
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    E1, E2
    4851 Poe Ave
    Woodland Hills, CA
    91364
    F1, F2
    20225 Lorenzana Dr
    Los Angeles, CA
    91111
    G1, G2
    20253 Lorenzana Dr
    Los Angeles, CA
    90005
    H1, H2
    5241 Del Moreno Dr
    Los Angeles, CA
    91110
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    J1, J2
    5135 Quakertown Ave
    Thousand Oaks, CA
    91362
    K1, K2
    720 Eucalyptus Ave 105
    Inglewood, CA
    89030
    L1, L2
    5021 Dumont Pl
    Woodland Hills, CA
    91364
    M1, M2
    4819 Quedo Pl
    Westlake Village, CA
    91362
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    N1, N2
    20044 Wells Dr
    Beverly Hills, CA
    90210
    O1, O2
    7659 Mckinley Ave
    Los Angeles, CA
    90001



    And here is what I get back:

    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364B1, B2
    B1, B2
    19831 Henshaw St
    Culver City, CA
    94023C1, C2
    C1, C2
    5142 Dumont Pl
    Azusa, CA
    91112D1, D2
    D1, D2
    20636 De Forest St
    Woodland Hills, CA
    91364A1, A2
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364E1, E2
    E1, E2
    4851 Poe Ave
    Woodland Hills, CA
    91364F1, F2
    F1, F2
    20225 Lorenzana Dr
    Los Angeles, CA
    91111G1, G2
    G1, G2
    20253 Lorenzana Dr
    Los Angeles, CA
    90005H1, H2
    H1, H2
    5241 Del Moreno Dr
    Los Angeles, CA
    91110I1, I2
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135J1, J2
    J1, J2
    5135 Quakertown Ave
    Thousand Oaks, CA
    91362K1, K2
    K1, K2
    720 Eucalyptus Ave 105
    Inglewood, CA
    89030L1, L2
    L1, L2
    5021 Dumont Pl
    Woodland Hills, CA
    91364M1, M2
    M1, M2
    4819 Quedo Pl
    Westlake Village, CA
    91362I1, I2
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135I1, I2
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135N1, N2
    N1, N2
    20044 Wells Dr
    Beverly Hills, CA
    90210O1, O2
    O1, O2
    7659 Mckinley Ave
    Los Angeles, CA
    90001

    I have not started the sorting code because I cannot get past this, but once I have proper zip codes I am sure I can make a sort function no problem.

    I am using xcode with some breaks to read variables as various points and do not notice anything wrong until it makes it to the output functions, although this page briefly pops up between input and output functions when the breaks are up:

    Array of pointers to a struct-xcode-jpg

    Any help will be much appreciated...

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    typedef struct{
        char name[25];
        char street[25];
        char state[25];
        char zip[5];
    }INFORMATION;
    The first thing to realise is that if you have a 5 character string like "12345", is that you need 6 characters (say your ZIP code) to store it as a string.
    All C-strings are followed by a \0 character to mark the end of the string.

    > typedef INFORMATION *INFOPTR;
    Creating typedef's for just a pointer seldom adds any clarity to the code.
    The only useful exception is typedefs for function pointers.

    Also by convention, uppercase names are used for #defines only, such as
    #ifndef LAB_HEADER_H
    #define LAB_HEADER_H

    > INFO=(INFOPTR)malloc(sizeof(INFORMATION));
    If you're compiling this as a C program, there is no need to cast the return result of malloc.
    There is no positive benefit to the cast, but there is one bug made hard to find by having the cast (which would be obvious without the cast).
    See the FAQ for more details.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Salem View Post
    Creating typedef's for just a pointer seldom adds any clarity to the code. Also by convention, uppercase names are used for #defines only
    This is common in the case of microsoft and windows, (especially when "Hungarian" style was popular), as seen in this example from windows.h:

    Code:
    typedef struct _FILETIME {
        DWORD dwLowDateTime;
        DWORD dwHighDateTime;
    } FILETIME, *PFILETIME, *LPFILETIME;
    If this is for a class, I would recommend using the coding style preferred by the instructor. If this is just for yourself, then it doesn't matter.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by rcgldr View Post
    If this is just for yourself, then it doesn't matter.
    That is only true if you're willing to accept the possibility of causing yourself confusion in future when you read your own code.

    It is a humbling experience to look at some old code, wonder "what idiot wrote this?", and to realise - after looking at comments or documentation - that the author was yourself. Possibly the only experience more humbling is to realise you wrote that code just last week.

    Using sloppy coding style, on the basis that "it is only for myself" is one of the common causes of such an experience.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by rcgldr View Post
    If this is just for yourself, then it doesn't matter.
    Quote Originally Posted by grumpy View Post
    That is only true if you're willing to accept the possibility of causing yourself confusion in future when you read your own code.
    I seriously doubt that whether or not typedefs are in upper or lower case is going to cause confusion. There are already inconsistencies depending on the environment, for example, BYTE and DWORD in upper case while size_t is in lower case. Most Windows functions are mixed case, like CreateFile(), ... while std stuff is lower case, printf(), vector, ... .

  6. #6
    Registered User
    Join Date
    May 2013
    Posts
    4
    Quote Originally Posted by Salem View Post
    Code:
    typedef struct{
        char name[25];
        char street[25];
        char state[25];
        char zip[5];
    }INFORMATION;
    The first thing to realise is that if you have a 5 character string like "12345", is that you need 6 characters (say your ZIP code) to store it as a string.
    All C-strings are followed by a \0 character to mark the end of the string.
    Of course! I, for some reason, convinced myself zip[5] would give me 0,1,2,3,4,5 but to get that I need to put [6], this was causing he next malloc to overwrite the NULL at the end of zip with the name of the next struct so without the NULL i was getting all the information until the next NULL (the one at the end of name). I cant believe I over looked this. Still learning...

    Quote Originally Posted by Salem View Post
    > typedef INFORMATION *INFOPTR;
    Creating typedef's for just a pointer seldom adds any clarity to the code.
    The only useful exception is typedefs for function pointers.
    Professor wants us to throw a typedef in there -_-

    Quote Originally Posted by Salem View Post
    Also by convention, uppercase names are used for #defines only, such as
    #ifndef LAB_HEADER_H
    #define LAB_HEADER_H
    I typically make a habit of trying to make functions and such all capitals to see easier..
    If you mean what you quoted specifically that is there by default in xcode (macs ) so I did not even write it.
    I will keep that in mind though!

    Quote Originally Posted by Salem View Post
    > INFO=(INFOPTR)malloc(sizeof(INFORMATION));
    If you're compiling this as a C program, there is no need to cast the return result of malloc.
    There is no positive benefit to the cast, but there is one bug made hard to find by having the cast (which would be obvious without the cast).
    See the FAQ for more details.
    Will reference the FAQ and such and start reading around the site, I just found this place working on this assignment, I am behind on it (due next week) and kinda rushing thus probably not thinking so clearly (see array mistake at top lol). The malloc was a direct copy of how it was explained in class and it is working so I will probably leave it for the assignment.


    Thank you so much for your help even though it was something so simple. And thanks to everyone discussing uppercase vs lower case too. Im gonna go write my swap function now. Will post it on here I guess to show I am not just trying to mooch information off everyone, heh...

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Carry on here for the coding style thread -> May 2013 coding style discussion thread
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    May 2013
    Posts
    4
    Okay so I used a bubble sort, but it appears to be it is swapping the "work[y]->zip" memory address rather tan the elements value. So my output just reverses the entire list in perfect order (since i want greatest zip to least zip now, the later zips have higher value due to how they are assigned in INPUT. I have been reading a few things on pointer to array vs array of pointer... I think thats what I am trying to fix... Anyway here is the code:

    Code:
    void SWAP(INFORMATION *work[], int count)
    {
        int loop=0, x=0, y=0;
        
        for(x=0;x<(count-1);x++)
        {
            loop=0;
            
            for(y=0;y<(count-1-x);y++)
            {
                if((work[y])->zip < (work[y+1])->zip)
                {
                    void *temp=work[y+1];
                    work[y+1]=work[y];
                    work[y]=temp;
                    
                    loop=1;
                }
            }
            if(!loop)
            {
                return;
            }
        }
    }

    Here is the input:

    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    B1, B2
    19831 Henshaw St
    Culver City, CA
    94023
    C1, C2
    5142 Dumont Pl
    Azusa, CA
    91112
    D1, D2
    20636 De Forest St
    Woodland Hills, CA
    91364
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    E1, E2
    4851 Poe Ave
    Woodland Hills, CA
    91364
    F1, F2
    20225 Lorenzana Dr
    Los Angeles, CA
    91111
    G1, G2
    20253 Lorenzana Dr
    Los Angeles, CA
    90005
    H1, H2
    5241 Del Moreno Dr
    Los Angeles, CA
    91110
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    J1, J2
    5135 Quakertown Ave
    Thousand Oaks, CA
    91362
    K1, K2
    720 Eucalyptus Ave 105
    Inglewood, CA
    89030
    L1, L2
    5021 Dumont Pl
    Woodland Hills, CA
    91364
    M1, M2
    4819 Quedo Pl
    Westlake Village, CA
    91362
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    N1, N2
    20044 Wells Dr
    Beverly Hills, CA
    90210
    O1, O2
    7659 Mckinley Ave
    Los Angeles, CA
    90001
    Output:

    O1, O2
    7659 Mckinley Ave
    Los Angeles, CA
    90001
    N1, N2
    20044 Wells Dr
    Beverly Hills, CA
    90210
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    M1, M2
    4819 Quedo Pl
    Westlake Village, CA
    91362
    L1, L2
    5021 Dumont Pl
    Woodland Hills, CA
    91364
    K1, K2
    720 Eucalyptus Ave 105
    Inglewood, CA
    89030
    J1, J2
    5135 Quakertown Ave
    Thousand Oaks, CA
    91362
    I1, I2
    5332 Felice Pl
    Stevenson Ranch, CA
    94135
    H1, H2
    5241 Del Moreno Dr
    Los Angeles, CA
    91110
    G1, G2
    20253 Lorenzana Dr
    Los Angeles, CA
    90005
    F1, F2
    20225 Lorenzana Dr
    Los Angeles, CA
    91111
    E1, E2
    4851 Poe Ave
    Woodland Hills, CA
    91364
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    D1, D2
    20636 De Forest St
    Woodland Hills, CA
    91364
    C1, C2
    5142 Dumont Pl
    Azusa, CA
    91112
    B1, B2
    19831 Henshaw St
    Culver City, CA
    94023
    A1, A2
    20294 Lorenzana Dr
    Woodland Hills, CA
    91364
    Any help or hints would be appreciated!
    Last edited by turtlegrip; 05-12-2013 at 04:46 PM.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I think the actual swap is ok, because C is designed to let you assign to struct types like that. The problem is probably the comparison, since zip is a string, it needs to be compared lexicographically, which < and other relational operators don't do. They compare by address instead. You will have to call strcmp() or some other function to do the comparison.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array of pointers to a struct
    By Magical in forum C Programming
    Replies: 11
    Last Post: 03-20-2011, 06:03 PM
  2. array of struct pointers
    By simo_mon in forum C Programming
    Replies: 4
    Last Post: 05-11-2009, 08:34 PM
  3. array of pointers in struct
    By cs32 in forum C Programming
    Replies: 9
    Last Post: 04-09-2008, 01:43 PM
  4. array of pointers of a struct
    By paulur in forum C Programming
    Replies: 18
    Last Post: 04-14-2006, 07:17 AM
  5. array of struct pointers
    By jellyKing in forum C Programming
    Replies: 1
    Last Post: 04-12-2003, 12:17 PM