Изо всех сил пытается использовать calloc и realloc для инициализации массивов в C - PullRequest
4 голосов
/ 06 февраля 2010

Я пытаюсь использовать calloc и realloc для инициализации моего массива. Я пытаюсь написать программу, которая вычисляет окончательную сумму из аргументов командной строки, используя fork () с сопутствующей программой.

Если я получаю нечетное множество целых чисел из командной строки, например: ./program 1 2 3 4 5.

Он должен увидеть, что сумма нечетная, и инициализировать мой входной массив до 6 мест и поставить ноль в самом последнем месте. Например: [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 0. Таким образом, моя сопутствующая программа может выполнить вычисление.

Если я получу четное количество целых чисел из командной строки, например: ./program 1 2 3 4. Это будет сделано так же, как указано выше, за исключением того, что без нуля, потому что набор целых чисел четен.

Выходной массив должен быть инициализирован с тем, чтобы количество целых чисел делилось на 2. Так что, если бы у меня было 6 аргументов, он был бы инициализирован на 3. Если бы я получил нечетное количество целых чисел, например 7, он перераспределил бы ввод массив и поставить ноль в конце, таким образом, получая количество целых чисел 8. Таким образом, это разделило бы это на 2 и заставило бы результат инициализировать до 4.

Мой выходной массив в конечном итоге будет содержать суммы каждой пары чисел. Таким образом, выше будет.

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

Тогда выходной массив будет содержать [3], [7], [5]. Затем цикл продолжится с этого и вычислит окончательную сумму из оставшихся аргументов.

Я не могу получить эту точку, потому что мои массивы неправильно инициализируются и добавляют ноль к входному массиву, если число аргументов нечетное.

См. Код ниже:

#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 ]

5 голосов
/ 06 февраля 2010

realloc принимает размеры выделения в байтах, а не элементы массива, поэтому вам нужно умножить на sizeof (int), как это

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

также это не работает

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

Если входная информация выделена для хранения argc дюймов, то наибольшим разрешенным индексом для input будет input[argc-1]. Мне не ясно, выделяете ли вы слишком мало элементов, или что ввод [argc] является ошибочным.


Edit: Могу ли я предложить это в качестве альтернативной формулировки. если мы установим последний слот во входном массиве на 0 до , мы проанализируем входные данные, тогда нам все равно, будет ли количество входов четным или нечетным.

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]);
}
2 голосов
/ 06 февраля 2010

Поскольку это домашнее задание, я сделаю несколько общих замечаний и надеюсь, что это не только поможет вам в решении вашей проблемы, но и улучшит ваш стиль программирования.

Ваш код содержит:

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

Если size равно 1, size % 2 также будет равно 1, и поэтому ваша вторая проверка всегда верна. Эффект двух строк, как если бы вы написали:

if (size == 1)
    size = 2;

Я сомневаюсь, что это то, что вы хотите.

Учитывая постановку задачи, ваша переменная input будет хранить элементы n или n+1, где n - это число чисел, которое вы хотите добавить, и равно argc-1.

В C целочисленное деление усекается, поэтому 1/2 равно 0, 5/2 равно 2 и т. Д. Математически, 5/2 равно 2,5, конечно. В приведенных ниже утверждениях я различаю «С» и истинное математическое видение, написав // для последнего.

Теперь для выходного массива вы хотите n//2 элементов, если n четное, и (n+1)//2 элементов, если n нечетное. Из-за упомянутого выше свойства целочисленного деления вы можете убедиться, что ваш выходной массив всегда будет содержать (n+1)/2 элементов.

Если вы не заботитесь о том, чтобы тратить впустую один элемент, для своего ввода вы всегда можете выделить n+1 элементов, а затем установить n+1 th элемент в ноль, прежде чем начинать читать числа из команды. Строковые аргументы. Это имеет следующие преимущества:

  • Не нужно беспокоиться о четном или нечетном количестве чисел в остальной части вашей программы,
  • Вам не нужно calloc(): вы просто устанавливаете последний элемент на ноль. Остальные элементы будут записаны, и последний элемент, который вы установили на ноль, будет перезаписан, если у вас будет четное количество элементов.

Теперь о вашем realloc() звонке:

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

У этого есть следующие "проблемы":

  • realloc(NULL, size) эквивалентно malloc(size), поэтому вы должны заменить realloc() на malloc().
  • Вам не нужно приводить возвращаемое значение из malloc(), calloc() и realloc(). На самом деле, приведение может скрыть ошибки от невозможности включения stdlib.h.
  • Вам нужно argc раз sizeof(int) байт, а не argc. Два будут равны, только если sizeof(int) равно 1.
  • Учитывая указатель T *p;, мне проще написать malloc() вызовов как p = malloc(n * sizeof *p); - это проще для написания, проще для чтения и не зависит от типа p.

Итак, внеся вышеуказанные изменения, вы получите:

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

atoi() не проверяет ошибки: если вы узнали о strtol(), вы должны использовать это.

Когда вы складываете числа вместе, вы можете сделать:

count := 0
while count < n:
    output[count/2] := input[count] + input[count+1]
    count := count + 2
1 голос
/ 06 февраля 2010

Остерегайтесь размеров в malloc, calloc и realloc. Вам нужно умножить на размер указанной вещи, так что

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

Этот код превосходит альтернативы двумя способами:

  1. Расчет размера остается корректным, даже если тип input или output изменяется (скажем, с int на long на 64-битном компьютере).

  2. Нет приведений. Приведения не нужны, и вы хотите избегать приведения везде, где это возможно, потому что когда вы пишете приведение, компилятор вам неявно доверяет . Если вы допустили ошибку при приведении, компилятору будет очень трудно ее привести.

    Функции выделения памяти предназначены для возврата void * по причине: вы можете присвоить результат любому типу указателя без приведения.

Я бы также порекомендовал вам продолжить с

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

на случай, если на вашей машине не хватит памяти. В этом случае это позволит избежать сегментации.

0 голосов
/ 06 февраля 2010

почему вам выделена только половина номера. У вас есть n целых чисел, поэтому вам нужен массив целых чисел n + 1 (при условии, что вам нужен нулевой страж в конце)

и для чего нужен вывод, вы никогда не используете его

+ 1 за точку о realloc (от Джона К)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...