Fighting using calloc and realloc to initialize arrays in C

I am trying to use calloc and realloc to initialize an array. I am trying to write a program that computes the final amount from command line arguments using fork () with a companion program.

If I get an odd set of integers from the command line, for example: ./ program 1 2 3 4 5.

He should see that the sum is odd and initializes my input array to 6 points and puts zero in the last place. For example: [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 0. So my companion program is able to perform the calculation.

If I get an even number of integers from the command line, for example: ./ program 1 2 3 4. It will do the same as above, except without zero, because the set of integers is equal.

The output array must be initialized before the number of integers is divisible by 2. Therefore, if I had 6 arguments, it would be initialized to 3. If I get an odd number of integers like 7, it redistributes the input to the array and put zero at the end, so the number of integers is 8. Thus, it will divide it by 2 and make the initialization of the output equal to 4.

My output array will eventually contain the sums of each pair of numbers. So the higher would be.

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

Then it will have an output array [3], [7], [5]. Then the cycle will continue from this and calculate the final amount from the remaining arguments.

I cannot get this point because my arrays are not initialized correctly and add zero to the input array if # arguments are 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) } 
+4
source share
4 answers

Since this is homework, I will make some general comments, and I hope this helps not only solve your problem, but also improve your programming style.

The code contains:

  if(size == 1 && size % 2 != 0) size++; 

If size is 1, then size % 2 will also be 1, so your second check is always true. The effect of the two lines looks as if you wrote:

 if (size == 1) size = 2; 

I doubt that this is what you want.

Given the problem operator, your input variable will store the elements n or n+1 , 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 , of course, 2.5. In the statements below, I distinguish between "C" and the true mathematical mapping, writing // for the latter.

Now for your output array you need elements n//2 if n is equal, and (n+1)//2 if n is odd. Due to the property of integer division mentioned above, you can make sure that your output array will always contain (n+1)/2 elements.

If you do not need to spend one element on a space, you can always select n+1 elements for your input, and then set n+1 th element to zero, before you start reading numbers from the command line, linear arguments. This has the following advantages:

  • No need to worry about even or odd numbers in the rest of your program,
  • You do not need calloc() : you just set the last element to zero. The rest of the elements will be written, and the last element that you set to zero will be overwritten if you even have the number of elements.

Now about your call to realloc() :

 input = (int*)realloc(NULL,(argc)); 

This has the following "problems":

  • realloc(NULL, size) equivalent to malloc(size) , so you should replace realloc() with malloc() .
  • You do not need to specify the return value from malloc() , calloc() and realloc() . In fact, casting can hide errors from refusing to include stdlib.h .
  • You need argc times sizeof(int) bytes, not argc . These two will be equal only if sizeof(int) is 1.
  • Given the pointer T *p; , it’s easier for me to write malloc() calls as p = malloc(n * sizeof *p); - it's easier to write, easier to read and independent of type p .

So, making the above changes, you will receive:

 size_t n = argc - 1; /* number of inputs */ input = malloc((n+1) * sizeof *input); 

atoi() does not check errors: if you find out about strtol() , you should use this.

When you add numbers together, you can:

 count := 0 while count < n: output[count/2] := input[count] + input[count+1] count := count + 2 
+2
source

realloc accepts distribution 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 does not work

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

If the input is assigned to store argc ints, then the largest allowed index in input is input[argc-1] . It’s not clear to me if you select too few elements or that the input [argc] is wrong.


Edit: May I suggest this as an alternative wording. if we set the last interval of the input array to 0 before we analyze 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]); } 
+5
source

Beware of sizes in malloc , calloc and realloc . You need to multiply by the size of the pointer that it points to, therefore

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

This code outperforms alternatives in two ways:

  • The size calculation remains true even if the input or output type changes (say from int to long on a 64-bit machine).

  • No castings. Throws are not needed, and you want to avoid casting where possible, because when you write a cast, the compiler trusts you implicitly . If you made a mistake when casting, the compiler threw it very much.

    The memory allocation functions are designed to return void * for any reason: you can assign the result to any type of pointer without translation.

I also recommend that you follow

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

just in case your computer runs out of memory. This would avoid segfault in this case.

+1
source

why do you allocate only half the number. You have n integers, so you need an array of integers n + 1 (assuming you need a zero control signal at the end)

and for output, you never use it

+1 for a point relative to realloc (from john k)

0
source

Source: https://habr.com/ru/post/1300487/


All Articles