2017-04-25 82 views
1

在下面的程序中,長度長於所需

int * accepted_ids = (int *) malloc(sizeof(int)*N); 
    double * accepted_scores = (double *)malloc(sizeof(double)*N); 

    int * unaccepted_ids = (int *) malloc(sizeof(int)*N); 
    double * unaccepted_scores = (double *) malloc(sizeof(double)*N); 

這些內存分配所創建尺寸N陣列爲他們每個人,即使需要的元素的數量比的N低得多。

由於程序使用的是隨機數生成器,因此我們無法預先知道每個人需要多少內存。

我該如何解決這個困境?

(最多5分)
單個維度陣列SCORES商店 Ñ他們在高中獲得大學的候選得分。數組元素 的索引是這些候選人的ID。大學接受 申請,申請人的平均分數大於或等於 至4.0。

編寫一個簡短的程序,會顯示:

•被接受的候選人與他們的身份證號碼和他們的平均得分列表。 •未被接受的候選人名單及其ID號碼和 平均分數 •接受和未接受的候選人人數。 •結果按排序 升序

平均得分應該用範圍< 2,6>使用隨機數發生器計算 。候選人總數 應作爲命令行參數傳遞給程序。 使您的程序對錯誤參數的輸入敏感。

不允許使用struct。

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

// This function tests whether it is possible 
// to convert a string into integer or not. 
// 
// This function is needed to check the 
// input argument otherwise if you type 
//  C:\>myapp.exe abc 
// your program will crash. 
int is_integer(const char * s) 
{ 
    char * endptr; 
    int radix = 10;//decimal number system 

    // try to convert s to integer 
    strtol(s, &endptr, radix); 

    errno = 0; 
    // if this conditions are fullfilled, 
    // that means, s can't be converted 
    // to an integer. 
    if (endptr == s || *endptr != '\0') 
    { 
     // argument must be an integer value   
     return 0; // failure 
    } 
    if (errno == ERANGE) 
    { 
     // int argument out of range   
     return 0; // failure 
    } 

    return 1; //success 
} 

// This function is needed to convert 
// a string to an integer value. 
int string_to_integer(const char * s) 
{ 
    char * endptr; 
    int radix = 10;//decimal number system 

    // convert s to integer 
    return strtol(s, &endptr, radix); 
} 

// Generte a random number between M and N. 
// 
// This function is needed coz rand() can 
// generate only integer values. 
double round_between_m_to_n(double M, double N) 
{ 
    return M + (rand()/(RAND_MAX/(N - M))); 
} 

// This is Bubble sort algorithm 
// This is implemented as a user-defined function, 
// coz, you have to use this twice. 
// First for accepted scores, 
// then for unaccepted scores. 
void sort(int * ids, double * scores, int count) 
{ 
    for (int i = 0; i < count; i++) 
    { 
     for (int j = 0; j < i; j++) 
     { 
      if (scores[i] < scores[j]) 
      { 
       // Swap scores 
       double temp = scores[i]; 
       scores[i] = scores[j]; 
       scores[j] = temp; 

       // Swap ids 
       int temp2 = ids[i]; 
       ids[i] = ids[j]; 
       ids[j] = temp2; 
      } 
     } 
    } 
} 

// This function is to print ids and scores 
// as a table. 
// This is implemented as a user-defined function, 
// coz, you have to use this twice. 
// First for accepted scores, 
// then for unaccepted scores. 
void print(int * ids, double * scores, int count) 
{ 

    printf("id\tavg_score\n"); 
    printf("-------------------\n"); 
    for (int i = 0; i < count; i++) 
    { 
     printf("%i\t%.1f\n", ids[i], scores[i]); 
    } 
} 

int main(int argc, char ** argv) 
{ 
    // Program can proceed only if 
    // the # of arguments is exactly 2. 
    // The 1st arg is always app-name. 
    if (argc != 2) 
    { 
     printf("insufficient argument\n"); 
     return EXIT_FAILURE; 
    } 

    int N = 0; 
    int accepted_scores_count = 0; 
    int unaccepted_scores_count = 0; 
    double acceptance_threshhold = 4.0; 

    if (!is_integer(argv[1])) 
    { 
     printf("incorrect argument type\n"); 
     return EXIT_FAILURE; 
    } 
    else 
    { 
     N = string_to_integer(argv[1]); 
     printf("Total %d students\n", N); 
    } 

    // Pair of variables are needed to 
    // keep track of student-ids. 
    // Otherwise, you can't tell what id a 
    // student has when data are sorted. 
    int * accepted_ids = (int *)malloc(sizeof(int)*N); 
    double * accepted_scores = (double *)malloc(sizeof(double)*N); 

    int * unaccepted_ids = (int *)malloc(sizeof(int)*N); 
    double * unaccepted_scores = (double *)malloc(sizeof(double)*N); 

    //Initialize random seed. 
    //If you don't use this, rand() will generate 
    //same values each time you run the program. 
    srand(time(NULL)); 

    // Simultaneously generate scores, ids, and 
    // store them is sepaerate arrays. 
    for (int i = 0; i < N; i++) 
    { 
     int id = i; 
     double score = round_between_m_to_n(2, 6); 

     // if the score is greater than or 
     // equal to 4.0... 
     if (score >= acceptance_threshhold) 
     { 
      accepted_ids[accepted_scores_count] = i; 
      accepted_scores[accepted_scores_count] = score; 

      accepted_scores_count++; 
     } 
     // ... otherwise they are unaccepted. 
     else 
     { 
      unaccepted_ids[unaccepted_scores_count] = i; 
      unaccepted_scores[unaccepted_scores_count] = score; 

      unaccepted_scores_count++; 
     } 
    } 

    // sort accepted students 
    sort(accepted_ids, accepted_scores, accepted_scores_count); 
    // sort unaccpeted students 
    sort(unaccepted_ids, unaccepted_scores, unaccepted_scores_count); 

    // print accepted students 
    printf("\naccepted students\n"); 
    print(accepted_ids, accepted_scores, accepted_scores_count); 

    // print unaccepted students 
    printf("\nunaccepted students\n"); 
    print(unaccepted_ids, unaccepted_scores, unaccepted_scores_count); 

    printf("\nEnd of program.\n"); 

    free(accepted_ids); 
    free(accepted_scores); 
    free(unaccepted_ids); 
    free(unaccepted_scores); 


    return EXIT_SUCCESS; 
} 
+1

*「這些內存分配正在爲它們中的每一個創建大小爲N的數組,即使所需元素的數量遠遠低於N的數量。」您告訴程序要分配那麼多。如果你想減少,找出你需要多少,然後分配這個數額。 – InternetAussie

+0

@InternetAussie,是的。那就是問題所在。由於該程序正在使用隨機數生成器,因此我們無法事先告訴每個人需要多少內存。 – anonymous

+2

[不要投出'malloc'的結果](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – UnholySheep

回答

1

因爲你知道的學生爲,您可以使用數據的陣列來所有學生產生的數據的數量:

int * all_ids = (int *)malloc(sizeof(int)*N); 
    double * all_scores = (double *)malloc(sizeof(int)*N); 

然後生成數據正常,保持數,但分配數據到all_*陣列:

for (int i = 0; i < N; i++) 
    { 
     int id = i; 
     double score = round_between_m_to_n(2, 6); 

     all_ids[i] = id; 
     all_scores[i] = score; 

     // if the score is greater than or 
     // equal to 4.0... 
     if (score >= acceptance_threshhold) 
     { 
      accepted_scores_count++; 
     } 
     // ... otherwise they are unaccepted. 
     else 
     { 
      unaccepted_scores_count++; 
     } 
    } 

因爲你知道區分接受學生的閾值,以後可以拆分這些。

現在您擁有了所有的數據以及被接受但未被接受的學生人數。利用這些信息,您可以分配給接受和接受的學生數組:

int * accepted_ids = (int *)malloc(sizeof(int) * accepted_scores_count); 
    double * accepted_scores = (double *)malloc(sizeof(double) * accepted_scores_count); 

    int * unaccepted_ids = (int *)malloc(sizeof(int) * unaccepted_scores_count); 
    double * unaccepted_scores = (double *)malloc(sizeof(double) * unaccepted_scores_count); 

排序數據到接受和接受的數組作爲你原來,與for循環(減去數據生成,因爲這是完成):

for (int i = 0, j = 0; (i+j) < N;) 
    { 
     int id = all_ids[i+j]; 
     double score = all_scores[i+j]; 

     // if the score is greater than or 
     // equal to 4.0... 
     if (score >= acceptance_threshhold) 
     { 
      accepted_ids[i] = id; 
      accepted_scores[i] = score; 

      i++; 
     } 
     // ... otherwise they are unaccepted. 
     else 
     { 
      unaccepted_ids[j] = id; 
      unaccepted_scores[j] = score; 

      j++; 
     } 
    } 

之後,繼續按正常順序排列和打印數據。你必須記得釋放all_*陣列。

2

如果你要結束了分配較少的內存,然後使用realloc。首先重新分配0個項目,然後每次需要分配更多內容時,使用realloc分配更多內存。由於realloc會「複製」現有數據,因此最終只能獲得實際需要的內存。請記住,realloc不是一個很好的功能,它的使用應該小心謹慎,因爲它很容易出錯(確保檢查返回值,並在覆蓋指針之前跟蹤以前的分配)。

+0

Infact舊指針不應該保留,因爲它是通過realloc釋放的。使用舊指針會導致免費使用。 –

+0

@AjayBrahmakshatriya在'realloc'失敗的情況下,舊指針需要保留。如果'realloc'失敗,那麼舊指針仍然有效。丟棄它會泄漏內存。如果'realloc'成功,您只能丟棄舊的指針。 – InternetAussie

+0

@InternetAusie。我同意這一點,但是如何寫出最後的聲明,暗示了之前的指針應該保留在其他地方。如果對其他人很清楚,好吧。 –