Thread: CS assignment with dynamic structs and memory allocation

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    3

    CS assignment with dynamic structs and memory allocation

    Hello everyone,

    This is my first post here but this forum has helped out so much when googling answers to common or otherwise very uncommon and abstract programming problems. Well let's get down to it shall we.

    I must create dynamic "records" (structs) using typedef and pointers. I understand this may make things a little more difficult but the layout of the structs you see below is how my professor wants things done. I am stuck at allocating memory for my structure and anytime I try to add anything into a field the actual field points to NULL. Please let me know what I am doing wrong with allocation and also if you can explain somewhat what is going on in memory with the solution you see. We are able to use the books library to complete this (which would make things so much simpler since all I would have to do is "pRoll = new(payrollT);") however I want to learn what's going on and how to do this myself. thank you in advance for all your help.

    Code:
     #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    typedef struct{
       char *name;
       char *title;
       char *snum;
       double salary;
       int withhold;
    } *employeeT;
    
    typedef struct{
       employeeT *employ;
       int numberOfEmp;
    } *payrollT;
    
    int main(){
    printf("How many employees: ");
    fflush(stdout);
    int userNum = 0, index = 0;
    scanf("%d", &userNum);
    payrollT pRoll;
    /*
    * pRoll is a pointer to payRoll struct
    * it dereferences numberOfEmp 
    *
    */
    //not really understanding the cast to NULL underneath
    pRoll = (payrollT) malloc(sizeof *((payrollT) NULL)); 
    pRoll->numberOfEmp = userNum;
    //array of pointers
    pRoll->employ = (employeeT *) malloc(userNum * sizeof(employeeT));
    for(index = 0; index < userNum; index++){
       pRoll->employ[index] = (employeeT) malloc(sizeof(employeeT));
    }
    // pRoll->employ = (employeeT *) malloc(userNum * sizeof *((employeeT) NULL));
    /*
    index = 0;
    while(index < userNum){ 
       //Have to malloc each record i think????
       // pRoll->employ[index] = (employeeT) malloc(sizeof *(employeeT) NULL);
       char temp[256];
       printf("Employee #1:\n");
       printf("Name: ");
       fflush(stdout);
       scanf("%s", temp);
       strcpy(pRoll->employ[index]->name, temp);
       //This beneath will be deleted later
       index = userNum;
    }
    */
    // printf("\nString is: %s\n", pRoll->employ[0]->name);
    return 0;
    }
    
    I assigned userNum to index to exit loop and test if name was in fact still NULL or not.

    Attached is a picture of the diagram of how these structs should look. First struct has number of employees and a pointer to an array of pointers which would point to each individual record.
    Attached Images Attached Images CS assignment with dynamic structs and memory allocation-work-jpg 

  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
    > //not really understanding the cast to NULL underneath
    > pRoll = (payrollT) malloc(sizeof *((payrollT) NULL));
    If it helps, neither do I.

    Perhaps this will clarify.
    Until you're confident with the whole malloc deal, you can start simply with just arrays.
    Code:
    #include <stdio.h>
    
    typedef struct {
       char name[100];
    } employeeT;
    
    typedef struct{
       employeeT employ[50];
       int numberOfEmp;
    } payrollT;
    
    int main()
    {
        payrollT    payroll;
        int         numberOfEmp, i;
        printf("How many employees?");
        scanf("%d",&numberOfEmp);
        for ( i = 0 ; i < numberOfEmp ; i++ ) {
            scanf("%s",payroll.employ[i].name);
        }
        return 0;
    }
    When this works, the transition to a pointer and malloc is very simple.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct {
       char name[100];
    } employeeT;
    
    typedef struct{
       employeeT *employ;  //!! [N] becomes *
       int numberOfEmp;
    } payrollT;
    
    int main()
    {
        payrollT    payroll;
        int         numberOfEmp, i;
        printf("How many employees?");
        scanf("%d",&numberOfEmp);
        //!! make payroll.employ[numberOfEmp];
        payroll.employ = malloc( numberOfEmp * sizeof(*payroll.employ) );
        for ( i = 0 ; i < numberOfEmp ; i++ ) {
            scanf("%s",payroll.employ[i].name);
        }
        return 0;
    }
    Calling malloc is easy (though often done wrong).
    Each array you make into a pointer needs a corresponding malloc.

    Notice in particular that the code which uses the array (or it's pointer replacement) is entirely unchanged.

    The general form should be
    p = malloc( num * sizeof(*p) );
    The advantage being you don't have to go scrolling back through the code trying to find the actual type-name.
    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
    Oct 2012
    Posts
    3
    Thanks Salem. I do understand most of what is going on but the issue is my structs MUST be created like:

    Code:
    typedef struct{
       int a;
       int b;
    } *example;   //With the pointer notation
    I have used malloc a lot and understand it (mostly). But when trying to access the element pRoll->employ[0]->name that field points to NULL and I can't seem to allocate space for it. I know that allocating individual space for each field cannot be the correct answer. There has got to be some way to allocate space for the entire struct.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, imagine if you are working without the pointer typedef to create a dynamic array of 100 objects:
    Code:
    typedef struct {
        int a;
        int b;
    } example_type1;
    
    /* ... */
    
    example_type1 *examples = malloc(sizeof(*examples) * 100);
    Now if you are working with the pointer typedef, there is only a small change:
    Code:
    typedef struct{
       int a;
       int b;
    } *example_type;
    
    /* ... */
    
    example_type examples = malloc(sizeof(*examples) * 100);
    It is less intuitive because you don't have that * after the type name to remind you that you're working with a pointer, yet the sizeof(*examples) remains. Notice that I do not cast the return value of malloc as it is not required.
    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

  5. #5
    Registered User
    Join Date
    Oct 2012
    Posts
    3
    Ok I finally figured it out. I guess I can close the thread now but I'll keep it open for a few hours just in case someone wants to point out better practices. Only issue is two small errors in valgrind but all memory was freed.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define MAX_NAME_SZ 256
    
    typedef struct{
        char *name;
        char *title;
        char ........num;
        double salary;
        int withhold;
    } *employeeT;
    
    typedef struct{
        employeeT employ;
        int numberOfEmp;
    } *payrollT;
    
    payrollT getPayRoll();
    void weeklyPay(payrollT pRoll);
    double calTax(double gross, int deduction);
    double calNet(double gross, int deduction);
    char *retNew(char *str1, char *str2, int space);
    void memfree(payrollT pRoll);
    
    int main(){
        payrollT test = getPayRoll();
        weeklyPay(test);
        memfree(test);
        return 0;
    }
    
    payrollT getPayRoll(){
        printf("How many employees: ");
        fflush(stdout);
        int userNum = 0, index = 0;
        scanf("%d", &userNum);
        payrollT pRoll;
        pRoll = (payrollT) malloc(sizeof *((payrollT) NULL)); //creates single malloced space for 2 var
        pRoll->numberOfEmp = userNum;
        pRoll->employ = (employeeT) malloc(userNum * sizeof*((employeeT) NULL));
        index = 0;
        while(index < userNum){
            char temp[MAX_NAME_SZ];
            char temp2[MAX_NAME_SZ];
            printf("Employee #%d:\n", (index+1));
            printf("Name: ");
            fflush(stdout);
            scanf("%s %s", temp, temp2);
            char *here = retNew(temp, temp2, 1);
            pRoll->employ[index].name = strdup(here);
            free(here);
            printf("Title: ");
            fflush(stdout);
            scanf("%s", temp);
            pRoll->employ[index].title = strdup(temp);
            printf("Social Security Number: ");
            fflush(stdout);
            scanf("%s", temp);
            pRoll->employ[index].ssnum = strdup(temp);
            printf("Enter Salary: ");
            fflush(stdout);
            scanf("%lf", &pRoll->employ[index].salary);
            printf("Withholding Exemptions: ");
            scanf("%d", &pRoll->employ[index].withhold);
            index++;
        }
        return pRoll;
    }
    
    
    double calNet(double gross, int deduction){
        double x = gross - (deduction * 1);
        double cal = x * .25;
        return (gross - cal);
    }
    
    double calTax(double gross, int deduction){
        double x = gross - (deduction * 1);
        double cal = x * .25;
        return cal;
    }
    
    void weeklyPay(payrollT pRoll){
        int track = pRoll->numberOfEmp, index;
        printf("%s\t\t\t\t\t%s\t\t%s\t\t%s\n","Name","Gross","Tax","Net");
        printf("-----------------------------------------------------------------------------\n");
        for(index = 0; index < track; index++){
            if(strlen(pRoll->employ[index].name) > 7){
                printf("%s\t\t\t\t%.2lf\t-\t%.2lf\t\t%.2lf\n", (pRoll->employ[index].name), (pRoll->employ[index].salary), (calTax(pRoll->employ[index].salary, pRoll->employ[index].withhold)), (calNet(pRoll->employ[index].salary, pRoll->employ[index].withhold)));
                fflush(stdout);
            }    else {
                printf("%s\t\t\t\t\t%.2lf\t-\t%.2lf\t\t%.2lf\n", (pRoll->employ[index].name), (pRoll->employ[index].salary), (calTax(pRoll->employ[index].salary, pRoll->employ[index].withhold)), (calNet(pRoll->employ[index].salary, pRoll->employ[index].withhold)));
                fflush(stdout);
            }
        }
    }
    
    char *retNew(char *str1, char *str2, int space){
        char *strNew = malloc(strlen(str1) + strlen(str2) + 1 * sizeof(char));
        strNew = strcpy(strNew, str1);
        if(space == 0){
            strNew = strcat(strNew, str2);
            return strNew;
        } else {
            char *sp = " ";
            strNew = strcat(strNew, sp);
            strNew = strcat(strNew, str2);
            return strNew;
        }
    }
    
    void memfree(payrollT pRoll){
        int track = pRoll->numberOfEmp, index;
        for(index = 0; index < track; index++){
            free(pRoll->employ[index].name);
            free(pRoll->employ[index].title);
            free(pRoll->employ[index].ssnum);
        }
        free(pRoll->employ);
        free(pRoll);
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic char array allocation and assignment
    By mnml in forum C Programming
    Replies: 8
    Last Post: 11-17-2011, 09:12 AM
  2. Dynamic memory allocation for structs passed to function
    By eXcellion in forum C Programming
    Replies: 18
    Last Post: 03-30-2011, 03:30 PM
  3. Structs and dynamic memory allocation
    By PaulCocaine in forum C Programming
    Replies: 3
    Last Post: 11-22-2010, 10:14 AM
  4. Replies: 7
    Last Post: 06-04-2008, 10:39 PM
  5. Replies: 7
    Last Post: 05-06-2002, 11:40 AM

Tags for this Thread