2015-10-08 1 views
1

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

Вот код, который работает, когда я выделяю массив внутри main.

#include <stdio.h> 
#include <stdlib.h> 
#include <windows.h> 
#include <time.h> 

#define ESC_KEY 27 
#define NUM_1_KEY 49 
#define NUM_2_KEY 50 

void find_two_largest(int a[], int n, int *largest, int *second_largest); 
void arrayInit(int *,int *, int, int); 
void randGenArray(int [], int); 
void inputArray(int[], int); 
void result(int, int); 
void loading(void); 
int menu(void); 

int main(void) 
{ 
    system("color f5"); 
    int n,i,largest,largest_2, *a; 

    arrayInit(a,&n, 2, 10); 

    if(menu()) 
     randGenArray(a,n); 
    else 
     inputArray(a,n); 

    find_two_largest(a,n,&largest,&largest_2); 
    result(largest,largest_2); 
    return 0; 
} 


void find_two_largest(int a[], int n, int *largest, int *second_largest) 
{ 
    int i=0,j=0; 
    system("cls"); 
    loading(); 
    *largest = 0; 
    *second_largest = *largest; 
    for (i=1;i<n;i++){ 
     if(*largest<a[i]) 
      *largest=a[i]; 
    } 
    for(j=1;j<n;j++){ 
     if(*largest==a[j]) 
      continue; 
     else{ 
      if(*second_largest<a[j]) 
       *second_largest=a[j]; 
     } 
    } 
    return; 
} 

void randGenArray(int a[], int n) 
{ 
    srand(time(NULL)); 
    int i; 
    for(i=0; i<n; i++){ 
     a[i]=rand()%100; 
     Sleep(10); 
     printf("\n>> Integer %d: %d", i+1, a[i]); 
    } 
    printf("\n\n\nPress any key to continue..."); 
    getch(); 
    return; 
} 

void inputArray(int a[], int n) 
{ 
    int i; 
    for(i=0; i<n; i++){ 
     printf("\n Please enter integer %d: ", i+1); 
     scanf("%d",&a[i]); 
    } 
    return; 
} 

int menu(void) 
{ 
    char _char; 

    printf("\n Please choose one of the following options:\n 1.Fill array manually\n 2.Fill array by random numbers\n\n "); 

    while(1) 
    { 
     _char = getch(); 
     switch(_char) 
     { 
      case ESC_KEY: 
       printf("\n\n Thank you for using our software!\n\n"); 
       exit(0); 

      case NUM_1_KEY: 
       system("cls"); 
       return 0; 

      case NUM_2_KEY: 
       system("cls"); 
       return 1; 

      default: 
       break; 
     } 
    } 
} 

void arrayInit(int *a,int *n, int min, int max) 
{ 
    printf("\n Please enter a length of the array: "); 

    do{ 
    scanf("%d", n); 
    if (*n<min||*n>max) 
     printf("\nThe ranged is limited. Please enter the value between %d and %d.\n", min, max); 
    } while(*n<min||*n>max); 

    a = (int*)calloc(*n,sizeof(int)); 

    return; 
} 

void loading(void) 
{ 
    printf("\n Loading"); 
    printf("."); 
    Sleep(300); 
    printf("."); 
    Sleep(300); 
    printf("."); 
    Sleep(300); 
    system("cls"); 
    return; 
} 

void result(int l, int l2) 
{ 
    system("cls"); 
    printf("\n Largest = %d  Second Largest = %d",l,l2); 
    Sleep(500); 
    printf("\n\n\n Thank you using our software! ;D\n\n"); 
    return; 
} 

Но если вы вырезаете и вставляете эту строку из arrayInit в main и меняете * n на n - это сработает!

a = (int *) calloc (* n, sizeof (int));

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

+1

'a' является локальным вариантом который выйдет из области действия, когда вы вернетесь, то есть сразу после того, как вы выделили ему память. Вам нужно либо передать указатель на указатель на int, либо, может быть, проще, вернуть вновь выделенную память. –

+0

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

+1

Мне нравится функция 'loading', кстати. –

ответ

1

Вот простая программа, которая покажет вам, как сделать это -

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

void create(int **p,int n); // function taking arguments as int ** and n is number of elements 

int main(void) { 
    int *a;  
    int n=5,i;      // declare and initialize n 
    create(&a,n);    // pass address of a to function 
    for(i=0;i<n;i++){ 
     a[i]=i;     // store value of i in a[i] 
     printf("%d\n",i);   // print a[i] 
    } 
    free(a);      // free the allocated memory 
    return 0; 
} 

void create(int **p, int n){ 
     *p=calloc(n,sizeof(int));   // allocate memory to *p (type- is int *) 
    } 

Working Code

+0

Отлично! это то, о чем я думал. Но почему вы передали адрес указателя адреса. Если «а» технически является адресом массива? –

+0

@ KasparSiricenko Я передал адрес 'int *', чтобы он не выходил за пределы области после завершения функции. Как описал М.Ohem в своем комментарии «a» - это локальная переменная, поэтому после возврата она выйдет за пределы области, так как функция завершается – ameyCU

+0

@KasparSiricenko 'a' в вашем коде - это просто указатель, который не указывает ни на что, как ваш код показывает. – ameyCU

0

Вы должны изменить функцию тип возвращаемого

void * arrayInit(int *n, int min, int max) 
{ 
    printf("\n Please enter a length of the array: "); 

    do{ 
    scanf("%d", n); 
    if (*n<min||*n>max) 
     printf("\nThe ranged is limited. Please enter the value between %d and %d.\n", min, max); 
    } while(*n<min||*n>max); 

    return calloc(*n,sizeof(int)); 
} 

И вызвать его из main в таким образом: a = arrayInit(&n, 2, 10);

+0

Спасибо. но я не хочу ничего возвращать. –

+0

@ KasparSiricenko Возврат - это способ присвоить выделенную кучей памяти вашей основной локальной переменной a: вы должны вернуть ее. – LPs