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)
}
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]);
}
Since this is homework, I will make some general comments, and I hope that will not only help you in solving your problem, but also improve your programming style.
Your code contains:
if(size == 1 && size % 2 != 0)
size++;
If size
is 1, size % 2
is going to be 1 too, and therefore your second check is always true. The effect of the two lines is as if you had written:
if (size == 1)
size = 2;
I doubt if that is what you want.
Given the problem statement, your input
variable will store n
or n+1
elements, where n
is the number of numbers you want to add, and is equal to argc-1
.
In C, integer division truncates, so 1/2
is 0
, 5/2
is 2
, etc. Mathematically, 5/2
is 2.5 of course. In the statements below, I distinguish between "C" and true mathematical dvision by writing //
for the latter.
Now, for your output array, you want n//2
elements if n
is even, and (n+1)//2
elements if n
is odd. Because of integer division property mentioned above, you can verify that your output array will always contain (n+1)/2
elements.
If you don't care about wasting one element worth of space, for your input, you can always allocate n+1
elements, and then set the n+1
th element to zero before you start reading numbers from the command-line arguments. This has the following advantages:
calloc()
: you just set the last element to zero. The rest of the elements are going to be written to, and the last element that you set to zero will be overwritten if you have even number of elements.Now, about your realloc()
call:
input = (int*)realloc(NULL,(argc));
This has the following "problems":
realloc(NULL, size)
is equivalent to malloc(size)
, so you should replace your realloc()
with malloc()
.malloc()
, calloc()
, and realloc()
. In fact, casting may hide errors from failing to include stdlib.h
.argc
times sizeof(int)
bytes, not argc
. The two are going to be equal only if sizeof(int)
is 1.T *p;
, I find it easier to write malloc()
calls as p = malloc(n * sizeof *p);
—this is simpler to write, easier to read, and does not depend on the type of p
.So, making the above changes, you get:
size_t n = argc - 1; /* number of inputs */
input = malloc((n+1) * sizeof *input);
atoi()
does no error checking: if you have learned about strtol()
, you should use that.
When you are adding the numbers together, you can do:
count := 0
while count < n:
output[count/2] := input[count] + input[count+1]
count := count + 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With