2013-12-20 4 views
-3

Я хочу создать функцию, которая возвращает все возможные числа, по которым число можно разделить. Также я хочу использовать эти возвращенные результаты в другой функции, которая ищет все простые числа в этих результатах и, в свою очередь, возвращает их.«Динамические (указательные) массивы» по функциям

Короче говоря, я хочу иметь возможность возвращать «динамические массивы» и использовать их снова в другой функции.

То, что я до сих пор:

int *division (long a) { 
    int i; 
    int *divResult = malloc(a * sizeof(long)); //Ultimately I want to allocate space dynamically instead of reserving too much space 

    if (naturalNumber(a)) { //What it basically does is "fmod(a, 1)" (returns boolean) 
    divLength = 0; //A global int set to trace the length of division() 
     for (i = 0; i < a + 1; i++) { 
      if (divisor(i, a)) { //Checks wether the division of a by i returns a whole number (returns boolean) 
       //divResult = realloc(divResult, sizeof(long)); //This gives seg faults and errors durning runtime; To be clear I am not exactly using it like this. What I do is I adjust the "malloc(a*sizeof(long))" to "malloc(sizeof(long))" 
       divResult[i] = i; //If i is a divisor add it to the pointer 
       divLength += 1; //track how long the current division is 
      } 
     } 
    } 

    free(divResult); //I was hoping this to remove the divResult from the memory, sadly it is still there and doesnt give me an error of me trying to return a NULL value 
    //printf("Mem: %p\n", (void *)divResult); 
    return divResult; //Return a "dynamic array" so that another function can use it 
} 

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

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

int *primes (long a) { //I'm trying to reuse the same tactic as before: 
    int i; 
    int *primeResult = malloc(a * sizeof(long)); //Allocating it again... 

    if (naturalNumber(a)) { //See previous codeblock 
     for (i = 0; i < a + 1; i++) { 
      division(i); //Calling the function here to divide each number from 1 to "a" so I am able to see which one is of size 2 (in other words the division of number *1 to a* and check wether it is a prime number (it has in total only 2 divisors)) 
      printf("len = %d\n", divLength); //prints the current length of division() 
      if (divLength == 2) { //If the division() "length" is 2 
       primeResult[i] = i; //add i to primes 
      } 
     } 
    } 

    free(primeResult); //Same as above 
    return primeResult; 
} 

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

Использование:

int *div; 
div = division(a) + 1; 
for (i = 0; i < a; i++) { 
    if (*(div + i) != 0) 
     printf("*(div + %d) : %d\n", i, *(div + i)); 
} 

int *prime; 
prime = primes(a) + 1; 
for (i = 0; i < a; i++) { 
    if (*(prime + i) != 0) 
     printf("*(prime + %d) : %d\n", i, *(prime + i)); 
} 

я получаю:

len = 6 
len = 1 
len = 2 
len = 2 
len = 3 
len = 2 
len = 4 
len = 2 
len = 4 
len = 3 
len = 4 
len = 2 
len = 6 
*(prime + 1) : 2 
*(prime + 2) : 3 
*(prime + 3) : 4 
*(prime + 4) : 5 
*(prime + 5) : 6 
*(prime + 6) : 7 
*(prime + 10) : 11 
*(prime + 11) : 12 

Я могу заверить вас, что если я закомментировать все следы, кроме тех, для разделения() и будем называть простыми числами() Я все еще получаю в результате:

*(div + 1) : 2 
*(div + 2) : 3 
*(div + 3) : 4 
*(div + 5) : 6 
*(div + 11) : 12 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
len = 0 
*(prime + 1) : 2 
*(prime + 2) : 3 
*(prime + 3) : 4 
*(prime + 5) : 6 
*(prime + 11) : 12 

Итак, я знаю, что мой код плох; Вот почему я прошу сейчас (я все еще учусь), я спрашиваю вас:

  • Почему до сих пор возвращается значение деления(), даже если я «освободил» память divResult?
  • Как я могу заставить realloc() работать?
  • Есть ли более простой способ сделать все это в отдельно функции?

И последнее, но не менее важное: кто-нибудь действительно понял, что я прошу?

+1

Больно читать длинные вопросы. :) – haccks

+5

ИМХО это не спасает. Чтобы решить ваши проблемы, вы должны действительно изучить язык C. Объяснение того, что не так в этом коде, будет * много *. –

+3

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

ответ

1
#include <stdio.h> 
#include <stdlib.h> 

long *division(long n){ 
    int i, len = 1;//for 1 
    long *result; 

    if(n < 1) return NULL; 
    result = malloc(n * sizeof(long)); 
    if(result){ 
     for (i = 2; i <= n; ++i)//skip 1 
      if(n % i == 0) 
       result[len++] = i; 
     result[0] = len;//put a length instead of 1 
     result=realloc(result, len*sizeof(long)); 
    } 
    return result; 
} 

long *factor(long n){ 
    int i=2, sqi=4, len = 1; 
    long *result; 

    if(n < 1) return NULL; 
    result = malloc((n/2+1)*sizeof(long)); 
    if(result){ 
     while(sqi <= n){ 
      int flag = 0; 
      while(n % i == 0 && (flag = 1)) 
       n /= i; 
      if(flag) 
       result[len++] = i; 
      sqi += 2*(i++) + 1; 
     } 
     if(n != 1)result[len++] = n; 
     result[0] = len; 
     result=realloc(result, len*sizeof(long)); 
    } 
    return result; 
} 

long *primes(long n) {Quite verbose 
    int i, len = 1; 
    long *result; 

    if(n < 1) return NULL; 
    result = malloc((n/2+2) * sizeof(long)); 
    if(result){ 
     for (i = 2; i <= n; ++i) { 
      long *div=factor(i); 
      if(div[1] == i) { 
       result[len++] = i; 
      } 
      free(div); 
     } 
     result[0] = len; 
     result=realloc(result, len*sizeof(long)); 
    } 
    return result; 
} 

int main(){ 
    long *div = division(1234); 
    int i, len = div[0]; 
    for(i=1;i<len;++i){ 
     printf("%ld\n", div[i]); 
    } 
    free(div); 
    printf("\n"); 
    long *fact = factor(123456); 
    len = fact[0]; 
    for(i=1;i<len;++i){ 
     printf("%ld\n", fact[i]); 
    } 
    free(fact); 
    printf("\n"); 
    long *prime = primes(123); 
    len = prime[0]; 
    for(i=1;i<len;++i){ 
     printf("%ld ", prime[i]); 
    } 
    free(prime); 
    printf("\n"); 
    return 0; 
} 
+0

Спасибо за ваши усилия по написанию этого кода, это помогло мне! – pepi55

3

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

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

void* realloc (void* ptr, size_t size) скопирует память, выделенную по адресу ptr, и скопируйте ее в новую область памяти размером size. Но что вы можете достичь с помощью realloc?

Есть ли более простой способ сделать все это в отдельных функциях? Вы можете быть более конкретными в этом вопросе?

UPDATE (на комментарии): вы можете реорганизовать свои две функции имеют один и тот же тип интерфейса, но, чтобы быть полезной в различных контекстах со следующими прототипами:

// the functions take as a parameter an array of integers, an a pointer to an integer. It returns an array of transformed data and through the second parameter, the length of the output. 
int* findDividers(int input, int* output_length) { 
    int* dividers = malloc(input * sizeof(int)); 
    int found_dividers = 0; 
    // do things 
    int* tmp = realloc(dividers, found_dividers); 
    free(dividers); 

    *output_length = found_dividers; 
    return tmp; 
} 

int* primeFilter(int* input, int input_length, int* output_length) { /* same structure as before */ } 

// you can then use it as follow 
int integer_to_process = 0xdeadbeef; 

int dividers_count = 0; 
int* dividers = findDividers(integer_to_process, &dividers_count); 

int primes_count = 0; 
int* primes = primeFilter(dividers, dividers_count, &prime_count); 

// now feel free to use the two arrays, with a minimal length, as you want. 
+0

Я хочу использовать realloc(), чтобы добавить еще одну «длину» в * divResult, поэтому мне не нужно будет выделять * sizeof (int) (что в этом случае не требует большого выделения памяти). Также я хочу функция деления() и функция primes() являются отдельными функциями. Я видел случаи, когда деление() и primes() помещаются в одну функцию, чего я не хочу. – pepi55

+0

подробнее – pepi55

2
  • Почему он все еще возвращает значения div(), хотя я «освободил» память divResult? Доступ к содержимому освобожденного блока памяти - Неопределенное поведение - все может случиться. В большинстве реализаций, если память не была повторно использована ни для чего другого, вы сможете увидеть старые значения. Но вы не можете зависеть от этого, потому что вы не знаете, когда память будет переназначена.

  • Как я могу заставить realloc() работать? Не освобождайте память, если она вам еще нужна. Пока выделена память, вы можете использовать realloc() для сокращения или расширения. Но убедитесь, что вы обновили все указатели в памяти, так как realloc() может перемещать память.

  • Есть ли более простой способ сделать это в отдельных функциях? Это очень широкий вопрос.

+0

Как я уже говорил в предыдущем комментарии, я хочу иметь возможность рассчитать номера деления числа и числа _to_ числа в отдельных функциях – pepi55

+0

Почему бы вам не передать 'divResult' на' простых аргументов? – Barmar

+0

Или 'primes' может называть' division'. Кстати, слово, которое вы ищете, это «факторы», а не «номера деления». – Barmar

Смежные вопросы