Сохранение результатов цикла while с неизвестным числом итераций в C - PullRequest
0 голосов
/ 21 октября 2019

У меня есть цикл while, который завершается при достижении if(condition){break;} после неизвестного числа итераций. Внутри цикла while вызывается функция, которая будет возвращать массив переменного размера на каждой итерации. Я знаю, что в python я мог бы просто добавлять массивы друг к другу, и, в конце концов, у меня был бы массив массивов переменного размера. Как правильно сделать это в C?

Вот соответствующая часть моего кода (я знаю, что это не MWE, многие части отсутствуют, но я надеюсь, что это все еще понятно):

int find_zeros(double *kappa, double *zeros){

    // reset the counter "z"
    int z = 0;

    // do some calculations and compute the zeros
    // update the value of z for every zero found

    // "zeros" now contains "z" elements
    return z;
}

double *foo(){

    // allocate memory for the "zeros" array (I know that N>z)
    double *zeros = (double *) malloc (sizeof(double) *N);

    // variable to count the elements of the "zeros" array
    int z;

    while (1){

        z = find_zeros(kappa, zeros);

        // if no zeros where found, exit the while loop
        if (z==0){ break; }

        // now we know how many zeros we have (z has been updated 
        // by find_zeros()), so we can reallocate the memory
        zeros = (double *) realloc(zeros, sizeof(double) *z);

        // append the zeros somewhere (how?!)
        // in python I would do: zeros_list.append(zeros)
    }

    // free the memory for the "zeros" array
    free(zeros);

    // return all the zeros found 
    // in python I would do: return zeros_list
}

int main(){

    double *zeros_list = what?? 
    // how do I allocate memory of a thing that I don't
    // know how big it is going to be?

    zeros_list = foo();
}

Ответы [ 2 ]

2 голосов
/ 21 октября 2019

Вам нужно хранить нули в foo независимо от значений, возвращаемых find_zeros, как в Python, где у вас будут отдельные переменные zeros_list и zeros.

* 1006. * Python list.append метод реализуется в два этапа: сначала массив перераспределяется на новую емкость с realloc (у вас уже есть эта часть), а затем новое значение присваивается вновь доступному пространству. Поскольку вы создаете массив массивов, вам также необходимо скопировать значения из их временного местоположения в новое с помощью memcpy(). Например (непроверенный, в отсутствие MWE):
struct floatvec {
    double *values;
    int length;
}

struct floatvec *foo(int *howmany) {
    struct floatvec *zeros_list = NULL;
    int zeros_cnt = 0;
    static double zeros[N];

    while (1) {
        int z = find_zeros(kappa, zeros);
        if (z == 0)
            break;

        struct floatvec new = {
            .values = malloc(z * sizeof(double)),
            .length = z
        };
        if (!new.values)
            return NULL;
        memcpy(new.values, zeros, sizeof(double) * z);

        zeros_list = realloc(zeros_list, sizeof(struct floatvec) * (zeros_cnt + 1));
        if (!zeros_list)
            return NULL;
        zeros_list[zeros_cnt++] = new;
    }

    *howmany = zeros_cnt;
    return zeros_list;
}

Пример использования:

int cnt;
struct floatvec *all_zeros = foo(&cnt);
for (int i = 0; i < cnt; i++) {
    struct floatvec *curr = all_zeros[i];
    for (int j = 0; j < curr->length; j++)
        printf("%lf\n", curr->values[j]);
}

Пара несвязанных примечаний:

  • don 't приведите результат malloc и realloc.
  • , проверьте, вернул ли malloc NULL, и прервите вашу программу или сделайте ошибку, возвращающуюся к вызывающей стороне.

РЕДАКТИРОВАТЬ : обновлен ответ в соответствии с отредактированным вопросом.

0 голосов
/ 22 октября 2019

относительно вашего вопроса:

// куда-нибудь добавить нули (как?!)

самый простой способ - это вызов memcpy() похож на:

memcpy( &zeros[ last used offset ], newXeros, sizeof( newzeros ) );
...