-1

Possible Duplicate:
Using Dynamic Memory allocation for arrays

I originally had this program store prices with a quantity size of ten and realized that I wanted to make the program more dynamic because I may need to store more than ten items at some given point. I'm having difficulties understanding on how to reallocate additional memory so that I can store any amount of items I would need. Is this the correct way of handling this task?

main function:

double *purchases = (double*)malloc(QUANTITY_SIZE);

outside function

double startShopping(double *purchases, double *taxAmount, double *subTotal, double *totalPrice)
{
    double itemPrice = 0.00;
    double* storeMoreItems;

    for(int i = 0; i < QUANTITY_SIZE; *subTotal +=purchases[i++])
    {
        while(itemPrice != -1)
        {
            printf("Enter the price of the item :");
            scanf("%lf", &itemPrice); 

            storeMoreItems = (double*)realloc(storeMoreItems, i * sizeof(int));

            if(storeMoreItems != NULL)
            {
                storeMoreItems = purchases;
                purchases[i-1] = itemPrice;
            }

           else
           {
               free(purchases);
           }
       }
  }

  displayCart(purchases);

  *taxAmount = *subTotal * TAX_AMOUNT;

  *totalPrice = *taxAmount + *subTotal;

  printf("\nTotal comes to : $%.2lf\n", *totalPrice);

  return *totalPrice;
}
Community
  • 1
  • 1
theGrayFox
  • 921
  • 1
  • 10
  • 22

4 Answers4

1

double* purchases = (double*)malloc(sizeof(double)*QUANTITY_SIZE);

What is more:

storeMoreItems = (double*)realloc(storeMoreItems, i * sizeof(double));

You tried to allocate the i*sizeof(int) and then casted it to double*. When double and int have different sizes your code would have a difficult to find bug.

The next thing:

When i is equal to 0 you allocate memory with initial size 0 bytes (i*sizeof(int)) and then try to use it. It won't work. Try to change your loop in this way: for (int i = 1, i <= QUANTITY_SIZE;... and keep purchases[i-1].

Adam Sznajder
  • 9,108
  • 4
  • 39
  • 60
  • Thank you for pointing that out, I've just corrected that. Thanks for the explanation as well. – theGrayFox Dec 27 '12 at 19:29
  • Look also at Daniel's answer. His notice is very important as well. Remember to +1 him ;) – Adam Sznajder Dec 27 '12 at 19:30
  • So remove purchases[i-1] with purchase[i]? – theGrayFox Dec 27 '12 at 19:39
  • I had that originally, I just wasn't sure why I kept seeing that in most of the examples that were demonstrating the setup for reallocating memory. I'm running the program and it's giving me a run-time error saying "Thread 1: EXC_BAD_ACCESS(code=1, address=0x1)" and it's highlighting where my for loop starts. What could this mean? – theGrayFox Dec 27 '12 at 19:53
1

This is wrong:

        if(storeMoreItems != NULL)
        {
            storeMoreItems = purchases;
            purchases[i-1] = itemPrice;
        }

First, you overwrite the just realloced pointer, you meant to have

purchases = storeMoreItems;

there instead of the other way round. But that would not influence the value the passed-in purchases pointer has in the calling function.

For that, you'd need to pass the address of purchases from main to

double startShopping(double **purchases_ptr, double *taxAmount, double *subTotal, double *totalPrice)

and assign

*purchases_ptr = storeMoreItems;

The reallocation itself,

storeMoreItems = (double*)realloc(storeMoreItems, i * sizeof(int));

uses the wrong type for the calculation of the size to allocate, that is almost certainly very wrong too.


In main:

size_t purchase_count = QUANTITY_SIZE;
double *purchases = malloc(purchase_count * sizeof *purchases);
// ...
startShopping(&purchases, &purchase_count, taxAmount, subTotal, totalPrice);
// ...

and startShopping would look something like

double startShopping(double **purchases_ptr, size_t *purchase_count,
                     double *taxAmount, double *subTotal, double *totalPrice)
{
    double itemPrice = 0.00;
    double* purchases = *purchases_ptr;
    size_t i;

    for(i = 0; ; *subTotal += purchases[i++])
    {
        printf("Enter the price of the item :");
        scanf("%lf", &itemPrice);

        // I'm assuming you don't really want to add the -1
        // entered for termination
        if (itemPrice == -1) {
            break;
        }

        if (i == *purchase_count) {
            // array filled, let's get more space
            // double it, or add a fixed amount,
            // but rather not just one element each round
            *purchase_count *= 2;

            // we have the address saved in another variable, so here we can
            // store the pointer returned by realloc in purchases without losing
            // the handle if realloc fails
            purchases = realloc(purchases, *purchase_count * sizeof *purchases);

            if (purchases == NULL) {
                // reallocation failed, now what?

                // throw a tantrum?
                free(*purchases_ptr);
                exit(EXIT_FAILURE);

                // or can something less drastic be done?
            } else {
                // Okay, got the needed space, let's record the address
                *purchases_ptr = purchases;
            }
        }
        purchases[i] = itemPrice;
    }

    // store the number of items actually read in?
    *purchases_count = i;

    // That should probably also get passed the number of items stored
    displayCart(purchases);

    *taxAmount = *subTotal * TAX_AMOUNT;

    *totalPrice = *taxAmount + *subTotal;

    printf("\nTotal comes to : $%.2lf\n", *totalPrice);

    return *totalPrice;
}
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • I really appreciate the feedback, especially with on addressing purchases back into the main function. I figured I would need a two-dimensional pointer, would you mind on how that works? – theGrayFox Dec 27 '12 at 19:41
  • I'm not entirely sure I understand what you're trying to do correctly, but I'll give it a shot. Will take a few minutes. – Daniel Fischer Dec 27 '12 at 19:51
  • Not a problem, no hurry. I'm trying to add as many item prices into the array as needed by the user, instead of limiting it to 10 items. – theGrayFox Dec 27 '12 at 19:57
0

The first thing you want to do is make sure you're allocating the right number of bytes. Malloc doesn't know that you want to use the memory for doubles so you need to multiply by sizeof(double):

double *purchases = (double*)malloc(QUANTITY_SIZE * sizeof(double));
Foggzie
  • 9,691
  • 1
  • 31
  • 48
0

Check out realloc.

void * realloc ( void * ptr, size_t size );

Reallocate memory block Changes the size of the memory block pointed to by ptr.

Get more details from here http://www.cplusplus.com/reference/cstdlib/realloc/

Khalefa
  • 2,294
  • 3
  • 14
  • 12