Как вернуть массив realloc в функции C - PullRequest
0 голосов
/ 10 мая 2018

Я хочу добавить числа в пустой массив, и количество этих чисел неизвестно в начале. Например, генерирование чисел от 1 до 10 и добавление один за другим.

generateFromOneToTen сохранит мой результат в output, а count должно быть 10 после выполнения. Все в порядке, если я напечатаю результат в этой функции.

int generateFromOneToTen(int *output, int count)
{
    for (int i = 0; i < 10; i++) {
        output = arrayAppendInt(output, i + 1, count);
        count++;
    }

    // Print result of `output` is 1,2,3...10 here

    return count;
}

И я реализовал arrayAppendInt для динамического увеличения длины массива и добавления нового значения после старых.

int *arrayAppendInt(int *array, int value, int size) 
{
    int newSize = size + 1;
    int *newArray = (int*) realloc(array, newSize * sizeof(int));

    if (newArray == NULL) {
        printf("ERROR: unable to realloc memory \n");
        return NULL;
    }

    newArray[size] = value;

    return newArray;
}

Здесь возникает вопрос. При вызове функции генерации numbers всегда будет NULL. Как я могу вернуть сгенерированные числа в переменную numbers?

int *numbers = NULL;
int count = 0;
count = generateFromOneToTen(numbers, 0);
                             ^^^^^^^

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Самое чистое решение (на мой взгляд) - упаковать массив + бухгалтерию (размер, использованный) в структуру и использовать (указатель на) эту структуру в качестве аргумента.


#include <stdlib.h>

struct dopedarray {
        unsigned size;
        unsigned used;
        int *array;
        };

Теперь вы можете поместить все свои ресурсы для распределения и учета в одну функцию (которая может быть встроена):


int array_resize(struct dopedarray *ap, unsigned newsize)
{
int *newp;

if(!ap) return -1;

newp = realloc (ap->array, newsize*sizeof*ap->array);
  // check return value here...
if (!newp) return -1;

free(ap->array);
ap->array = newp;
ap->size = newsize;

  // bookkeeping sanity
if(ap->size > ap->used ) { ap->used > ap->size; }

return 0;
}

Необходимо изменить функцию add_element aбит тоже:


int array_add_element(struct dopedarray *ap, int value)
{
if(ap->used >= ap->size){
        unsigned newsz;
        newsz= ap->used ? 2*ap->used: 4;
        array_resize(ap, newsz);
        // check return value here...
        }

ap->array[ap->used++] = val;
return 0;
}
0 голосов
/ 10 мая 2018

Полный код моего вопроса:

int generateFromOneToTen(int **output, int count) // +
{
    for (int i = 0; i < 10; i++) {
        *output = arrayAppendInt(*output, i + 1, count); // ++
        count++;
    }

    return count;
}

int *arrayAppendInt(int *array, int value, int size) 
{
    int newSize = size + 1;
    int *newArray = (int*) realloc(array, newSize * sizeof(int));

    if (newArray == NULL) {
        printf("ERROR: unable to realloc memory \n");
        return NULL;
    }

    newArray[size] = value;

    return newArray;
}

int *numbers = NULL;
int count = 0;
count = generateFromOneToTen(&numbers, 0); // +

Этот ответ также стоит прочитать: https://stackoverflow.com/a/9459803/1951254

0 голосов
/ 10 мая 2018

Вы можете использовать указатель на целочисленный указатель (int **):

int generateFromOneToTen(int **output, int count)
{
    for (int i = 0; i < 10; i++) {
        *output = arrayAppendInt(*output, i + 1, count);
        count++;
    }
    // `*output` is 1,2,3...10 here
    return count;
}

Вы можете переписать функцию arrayAppendInt следующим образом:

int *arrayAppendInt(int *array, int value, int size) 
{
    int newSize = size + 1;
    int *newArray;
    if (array==NULL)
      newArray = (int*) malloc ((1+size) * sizeof(int));
    else
      newArray = (int*) realloc(array, newSize * sizeof(int));

    if (newArray == NULL) {
        printf("ERROR: unable to realloc memory \n");
        return NULL;
    }

    newArray[size] = value;

    return newArray;
}

И назови это так *output = arrayAppendInt(*output, i + 1, i);.

...