views:

352

answers:

4

Hello, I'm struggling to use calloc and realloc for my array initializations. I'm trying to write a program which calculates a final sum from the command line arguments using fork() with a companion program.

If I receive a odd set of integers from the command line such as: ./program 1 2 3 4 5.

It should see that amount is odd and initialize my input array to 6 spots and put a zero in the very last spot. Such as this: [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 0. So that my companion program is able to do the computation.

If I receive a even of amount of integers from the command line such as: ./program 1 2 3 4. It would do the same as above, except without the zero because the set of integers is even.

The output array should be initialized to whatever the amount of integers is divided by 2. So if I had 6 arguments, it would be initialized to 3. If I receive an odd amount of integers such as 7, it would reallocate input array and put the zero at the end, thus making the amount of integers 8. So it would divide that by 2 and make the output initialize to 4.

My output array would eventually hold the sums of each pair of numbers. So the above would be.

1+2=3, 3+4=7, 5+0=5.

Then it the output array would hold [3],[7],[5]. Then the loop would continue from that and calculate the final sum from the remaining arguments.

I can't get that point though because my arrays aren't initializing correctly and adding the zero to the input array if the # of arguments is odd.

Refer to the code below:

#include <stdio.h>   /* printf, stderr, fprintf */
#include <unistd.h>  /* _exit, fork */
#include <stdlib.h>  /* exit */
#include <errno.h>   /* errno */
#include <sys/wait.h>
int main(int argc, char** argv)
{
 int size = argc - 1;
 int* input;
 int* output;
 int calc; 

 if(size == 1 && size % 2 != 0)
  size++;
 if(size % 2 != 0)
 {
   calc = (size+1)/2;  
   input = (int*)realloc(NULL,(argc)); 
   output = (int*)calloc(calc, sizeof(int));
   int j;
   for(j = 1; j < argc; j++)
   {
   input[j-1] = atoi(argv[j]);
   }
   input[argc] = 0;
  }
 else 
 {  
  calc = (size)/2;
  input = (int*)realloc(NULL,(size));
  output = (int*)calloc(calc, sizeof(int));
  int j;
  for(j = 1; j < argc; j++)
  {
   input[j-1] = atoi(argv[j]);
  }

 }

 int i;
 for(i = 0; i < argc; i++)
 printf("input[%d]: %d\n",i,input[i]);

 free(input);
 free(output);
        exit(0)
    }
+5  A: 

realloc takes allocations sizes in bytes, not array elements, so you need to multiply by sizeof(int) like this

input = (int*)realloc(NULL,(argc) * sizeof(int)); 
output = (int*)calloc(calc, sizeof(int));

also this doesnt work

input = (int*)realloc(NULL,(argc) * sizeof(int)); 
...
input[argc] = 0;

If input is allocated to hold argc ints, then the largest permitted index into input is input[argc-1]. It isn't clear to me whether you are allocating too few items, or that input[argc] is in error.


Edit: Might I suggest this as an alternate formulation. if we set the last slot in the input array to 0 before we parse the inputs, then we don't care whether the number of inputs is even or odd.

int   calc = argc/2; // actually (argc-1+1)/2

int * input = (int *)realloc(NULL, (calc*2) * sizeof(int));
int * ouput = (int *)calloc(calc, sizeof(int));

input[calc*2 - 1] = 0; // in case we run out of inputs
for (int j = 1; j < argc; ++j)
{
   input[j-1] = atoi(argv[j]);
}
John Knoeller
A: 

why are you only allocated half the number. You have n integers so you need an n+1 integer array (assuming you need a null sentinel on the end)

and what is output for, you never seem to use it

+1 for the point about realloc (from john k)

pm100
I haven't finished writing the program yet, output takes the sums from the input array after I send them to the companion program when it does the computations. Then I will just repeat this process until I'm at one final sum.
+1  A: 

Beware of sizes in malloc, calloc, and realloc. You need to multiply by the size of the thing pointed to, so

  input  = realloc(NULL, argc * sizeof(*input)); 
  output = calloc(calc, sizeof(*output));

This code is superior to alternatives in two ways:

  1. The size computation remains correct even if the type of input or output changes (say from int to long on a 64-bit machine).

  2. There are no casts. The casts are not necessary, and you want to avoid casting wherever possible, because when you write a cast, the compiler trusts you implicitly. If you make a mistake when casting, it is very hard for the compiler to cast it.

    Memory-allocation functions are designed to return void * for a reason: you can assign the result to any pointer type without a cast.

I'd also recommend you follow up with

assert(input != NULL && output != NULL);

just in case your machine runs out of memory. This would avoid a segfault in that case.

Norman Ramsey
I finally got it working the way I wanted. Now I can proceed with my assignment. Thank you everyone.
+2  A: 
Alok
Thank you Alvok, your very last comment is interesting though. What will N be in that case? The number of calculations from the previous tier of numbers, so for instance. If I received, 1 2 3 4, N = 2 for the amount of calculations that I had to do? I'm not sure on that part.
@ray2k, you have either `n` or `n+1` elements allocated. `n` is the number of inputs provided on the command line, i.e. `argc-1`. For `1 2 3 4`, `n` is 4.
Alok