2017-04-25 87 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。我同意这一点,但是如何写出最后的声明,暗示了之前的指针应该保留在其他地方。如果对其他人很清楚,好吧。 –