【问题标题】:Need to take existing program and break off calculations into functions需要采用现有程序并将计算分解为函数
【发布时间】:2016-06-24 18:08:50
【问题描述】:

我有一个现有的程序,可以找到用户输入数字的最高、最低和平均值。但是,我不是在尝试进行这些计算并将它们放入单独的函数中。我的问题是我不明白如何将这些共享变量的计算以及其他内容放入它们自己的单独函数中。下面是我的代码,底部的 cmets 是我尝试过但失败的代码。

工作代码:

#include <stdio.h>

int main(){

int grades [100]; /*variables defining the array, the iterator, and input; which lets us take the input and validate before passing to the array*/
int i = 0;
int small, big, input;

printf("Enter a series of grades. When done, enter any number above 100.\n\n");

while (i <= 100) { //while loop to set maximum for array
    printf("Enter grade:");

    if (scanf("%d", &input) == 1) {
        if (input >= 0 && input <=100) {  //validate and impose constraints on grade values
            grades[i] = input; //if good, add to array
            i++;
            }
        else {
            printf("\n\nExiting entry.\n");
            printf("\n\nGrades entered:\n\n");
            break; //exiting loop
            }
        }
    }
int x, y;


big = small = grades[0];
for (y = 0; y < i; y++) {   
    if (grades[y] > big) {  
        big = grades[y];
        }
    else if (grades[y] < small) {   
        small = grades[y];
        }
    }
int sum = 0, avg = 0;
for (y = 0; y < i; y++) {   
    sum += grades[y];
    }
avg = (double) sum / i;     //formula for determining average
printf("Highest number : %d\n", big);
printf("Smallest number: %d\n", small);
printf("Average: %d\n", avg);



return 0;
}

故障代码:

int x, y;

for (x = 0; x < i; x++) {
    printf("Grade: %d\n", grades[x]);  //print array
   }
big = small = grades[0];
for (y = 0; y < i; y++) {   //for loop
    large(grades,y);
    smallest(grades,y);
    }
int sum = 0, avg = 0;
for (y = 0; y < i; y++) {   //for loop for determining sum of grades
    sum += grades[y];
    }
avg = (double) sum / i;     //formula for determining average
printf("Highest number : %d\n", big);
printf("Smallest number: %d\n", small);
printf("Average: %d\n", avg);



    return 0;
}

void large(int grades[], int y);
void smallest(int grades[], int y);

【问题讨论】:

  • 传递的参数类型和有使用不正确,比如gradesint,所以grades[y]会报错。

标签: c function loops average


【解决方案1】:

虽然其他答案建议使用 global 来使 grades 数组在从 main 调用的函数中可用,但使值可用于函数的普遍接受的方式是 将值(或指向值的指针)作为参数传递给函数。您应该避免使用全局变量,除非它们是绝对必要的(当您开始学习 C 时不太可能遇到这种情况)。

当您将参数传递给函数时,该函数将收到一个副本。如果您传递整数或浮点数等值,该函数将对该值的副本进行操作,并且更改将在调用函数中可见,除非该值被返回 和 已分配

当你将一个指针作为参数传递时,函数仍然会收到一个副本,但副本所指向的地址与调用函数中原来的地址完全相同(@ 987654323@ 这里)。因此,对指向的值的任何更改都会立即在调用函数中可见。这是您将听到的按值传递按引用传递的概要(即使两者实际上都是按引用传递)

在您的情况下,您填充了一个整数值数组 (grades),您希望对其进行迭代以找到 max/min 值以及 average。您希望在一个或多个函数中完成此操作。将函数拆分为maxmin 函数和average 函数将提供传递指向值的指针并使更改在main 中可见(在maxmin 的情况下)以及返回和分配一个值(average 的情况下)

首先,让我们看一个简单的函数来查找grades 中的最大值和最小值。您将需要传递数组grades(实际上是传递一个指向成绩的指针),您需要传递grades 数组中的值的数量,然后更改max 和@ 的值987654336@ 在main 中可用,您将把指向maxmin 的指针作为参数传递。例如:

void maxmin (int *arr, int n, int *max, int *min)
{
    int i;

    if (!arr || !max || !min) return;   /* validate pointers  */
    *max = INT_MIN, *min = INT_MAX;     /* initialize max/min */

    for (i = 0; i < n; i++) {           /* update max/min pointers */
        if (arr[i] > *max) *max = arr[i];
        if (arr[i] < *min) *min = arr[i];
    }
}

在上面,您只需要将maxmin 的值初始化为足够低/高,以便记录所有最大值/最小值。 (例如,如果您的值是 -100 to 10 并且您将两者都初始化为 0,那么您的最大值将永远不会改变)

对于您的平均值,您将以相同的方式传递grades 和值的数量,但在这里您将通过函数return 传递average 的值。您必须将返回值分配给 main 中的一个值,该值才能可见。

注意:函数可以返回其类型的值,但它不能返回指向函数内声明的静态对象的指针。为什么?因为这些值驻留在函数堆栈中,函数堆栈在函数返回时被销毁。只有返回 value 被保留给调用者(稍后再担心这个)。对于你的平均水平,你可以这样做:

float average (int *arr, int n)
{
    int i, sum = 0;

    if (!arr) {
        fprintf (stderr, "average() error: invalid array.\n");
        return -1.0;                    /* validate pointer */
    }
    for (i = 0; i < n; i++)            /* compute average  */
        sum += arr[i];

    return (float)sum / n;
}

现在将所有部分放在一个简短的示例中(并注意输入的结束通常由手动生成的EOF 表示,即 Linux 上的 ctrl+dctrl+z onwindoze)你可以做如下的事情(同时仍然允许任何超过 100 的值导致返回)

#include <stdio.h>
#include <limits.h>

enum { MAXG = 100 };

void maxmin (int *arr, int n, int *max, int *min);
float average (int *arr, int n);

int main (void) {

    int grades[MAXG] = {0}, i, idx = 0, input, max, min;
    float avg = 0.0;

    printf ("Enter a series of grades. [ctrl+d] when done:\n\n");

    while (idx < MAXG && printf ("grade[%3d]: ", idx) && 
        scanf ("%d", &input) == 1 && 0 <= input && input <= 100)
        grades[idx++] = input;

    maxmin (grades, idx, &max, &min);       /* compute max/min */
    if ((avg = average (grades, idx)) < 0)  /* compute average */
        return 1;

    printf ("\nThe grades entered were:\n\n");
    for (i = 0; i < idx; i++)
        printf (" grades[%3d] : %d\n", i, grades[i]);

    printf ("\n  maximum : %d\n  minimum : %d\n  average : %.2f\n\n",
            max, min, avg);

    return 0;
}

void maxmin (int *arr, int n, int *max, int *min)
{
    int i;

    if (!arr || !max || !min) return;   /* validate pointers  */
    *max = INT_MIN, *min = INT_MAX;     /* initialize max/min */

    for (i = 0; i < n; i++) {           /* update max/min pointers */
        if (arr[i] > *max) *max = arr[i];
        if (arr[i] < *min) *min = arr[i];
    }
}

float average (int *arr, int n)
{
    int i, sum = 0;

    if (!arr) {
        fprintf (stderr, "average() error: invalid array.\n");
        return -1.0;                    /* validate pointer */
    }
    for (i = 0; i < n; i++)            /* compute average  */
        sum += arr[i];

    return (float)sum / n;
}

使用/输出示例

$ ./bin/grades1 <dat/grades.txt
Enter a series of grades. [ctrl+d] when done:

<snip entry>

The grades entered were:

 grades[  0] : 80
 grades[  1] : 97
 grades[  2] : 72
 grades[  3] : 78
 grades[  4] : 94
 grades[  5] : 91
 grades[  6] : 78
 grades[  7] : 94
 grades[  8] : 89
 grades[  9] : 72

  maximum : 97
  minimum : 72
  average : 84.50

如果您有任何问题,请查看并告诉我,并且作为一般规则,仅在绝对必要时记住全局

【讨论】:

    【解决方案2】:

    这里有多个问题 您没有将调用函数语法与函数原型对齐 并且您没有将等级数组作为函数参数正确传递 试试

    for (y = 0; y < i; y++) {   //for loop
    largest(grades, y);
    smallest(grades, y);
    }
    

    定义函数:

    void largest(int grades[], int y);
    void smallest(int grades[], int y)
    

    因此,就性能而言,您可以即时计算最小值、最大值和平均值以避免多重循环

    【讨论】:

    • 测试它会给我各种警告和错误。警告:large 的类型冲突,small 的错误相同。此外,未定义引用 large 的错误,同样适用于 small。然后给出退出状态错误。我确定我在做一些愚蠢的事情,我修改了上面的代码以匹配我为你解释的内容。
    • 这可能是因为您使用的是 2 个不同的文件,不是吗?在这种情况下,您需要确保您的第二个文件可以看到变量(在第一个文件中声明为全局,通过添加 extern int small、large 等
    【解决方案3】:

    正如@Cherubim Anand 已经说过的:问题是grades 的范围,您可以将变量设为全局,正如@Cherubim Anand 已经提出的那样,或者将其作为参数发送给函数。

    int largest(int *grades)
    {
       int i,big;
       big = grades[0];
       for (i = 1;grades[i] != -1;i++) {
          if(grades[i] > big){
              big = grades[i];
          }
       }
       return big;
    }
    

    然后通过调用它

    big = largest(grades);
    

    另一个问题:如果输入不是数字,while 循环将不再停止,因为i 仅在输入为数字时才会递增。

    确切的方法或多或少取决于口味,这是我的:

      puts("Enter a series of grades between 0 (zero) and 100 (one hundred).");
      puts("When done, enter 'done'.");
      while (i <= 100) {
        printf("Enter grade:");
        if (scanf("%d", &input) == 1) {
          // if the number is in the right range: keep it
          if (input >= 0 && input <= 100) {
             grades[i] = input;
             i++;
          } else {
          // if not: print a hint
             printf("\nGrades are between 0 (zero) and 100 (one hundred).\n");
          }
        } else { 
            // anything else, including the string "done", ends the sampling
            grades[i] = -1;
            printf("\n\nExiting entry.\n");
            printf("\n\nGrades entered:\n\n");
            break;
        }
      }
    

    顺便说一句:您应该养成以exit(EXIT_SUCCESS) 结束main() 的习惯,而不是只返回0(零)和exit(EXIT_FAILURE),以防出现致命错误。像您的示例这样简单的事情没有必要,但以后很有用。您可以查看exit(3) 了解更多详情。

    【讨论】:

      猜你喜欢
      • 2019-08-23
      • 2021-03-22
      • 1970-01-01
      • 2020-01-27
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-06-24
      • 1970-01-01
      相关资源
      最近更新 更多