用结构测量并搜索最小,最大和平均温度

问题描述 投票:0回答:1

我必须编写一个程序来记录测量的温度,可以输入新的测量值,或显示根据先前测量值计算的统计数据。在打印统计的情况下,有必要找到并显示最低和最高记录温度并计算平均温度。

#include <stdio.h>

int least_in_array(int array[], int n)
{
    int i, least=array[0];
    for(i=0; i<n; i++)
    {
        if(array[i]<least)
        {
            least=array[i];
        }
    }
    return least;
}

int largest_in_array (int array[], int n)
{
    int i, largest=array[0];
    for(i=0; i<n; i++)
    {
        if(array[i]>largest)
        {
            largest=array[i];
        }
    }
    return largest;
}

float average_array(int array[], int n)
{
    int amount=0, i;

    for(i=0; i<n; i++)
    {
        amount+=array[i];
    }
    return (1.0*amount)/n;
}


int main() {

    int choose;

    struct Data1 {
        int dayInMonth;
        int month;
        float temperature;
    } da;

    printf("New measurement(1) or statistic(2)?\n");
    scanf("%d", &choose);

    if(choose==1) {

        printf("Enter the day in month : ");
        scanf("%d", &da.dayInMonth);
        printf("Enter month : ");
        scanf("%d", &da.month);
        printf("Enter temperature (*C) : ");
        scanf("%f", &da.temperature);

        printf("Data saved!");
        printf("-----------\n");

        return 0;
    }

    if(choose==2) {

        //printf("Least temperatures in quarter: %d",   least_in_array(dayInMonth) );

        return 0;
    }

    else {

        printf("----------------\n");
        printf("Wrong choose!\n");

    }

    return 0;
}

在案例2中,我评论了我收到错误的行。任何人都可以给我任何建议来解决这个问题吗?

| 71 |错误:'dayInMonth'未声明(首次使用此功能)

| 71 |错误:函数'least_in_array'的参数太少

c
1个回答
3
投票

从圣诞节前夕开始,让我们帮助那个显然非常需要帮助的人。对于应该将array传递给least_in_arraylargest_in_arrayaverage_array的代码 - 你没有阵列!这有点让你在“Go!”这个词中落后于八球。

您使用stuct捕获和协调dayInMonthmonthtemperature的想法是100%正确的。 (但请注意:C风格通常避免camelCase变量名称支持全部小写)。此外,在struct Data1中定义main()可以防止你的函数高于该点,因为你知道struct Data1是什么,所以你需要将你的struct定义移动到文件的顶部。 (或提供前瞻性声明,但我们将保存以供日后使用)现在,让我们将你的Data1移到顶部(我使用typedef来减轻每次使用前缀stuct并重命名为Data1 data

#define NDAYS 365

typedef struct {
    int day,
        month;
    double temperature;
} data;

注意定义的常量NDAYS。由于您将需要一个数组,并且由于动态分配和重新分配的方法似乎远远超出了您的需求,因此我们只需为数组中的元素数量定义一个常量,即最大值。

现在,在我们走得更远之前,让我们考虑一下我们的阵列。如果我们要使用struct来保持相关的日期和温度测量,那么我们将需要一个......数组?一系列的struct。使用我们的常量NDAYS,我们将在数组中声明最大的365元素。那怎么会这样呢?我们有我们的stuct typedeffed到data,所以如果我们想要一个data阵列,我们需要:

    data da[NDAYS] = {{0, 0, 0.0}};

注意:使用初始化每个字段的较旧的初始化程序格式,因为不清楚您是否可以使用C89编译器。 C99和更高版本添加了命名的初始值,例如{{.day = 0}}和任何未初始化的元素被隐式初始化为零。

现在我们有一个data阵列,可以捕获测量值。当然,您负责跟踪您填写的索引。一个简单的计数器,每次输入成功的测量值都会增加(下面使用ndx

我们如何使least_in_arraylargest_in_arrayaverage_array与一系列data一起工作?回想一下,我们将结构的定义移动到源文件的开头,所以现在每个函数都知道data是什么。我们只需要传递我们的data数组作为参数,例如

float least_in_array (data *array, int n)
{
    int i;
    float least = INT_MAX;   /* sufficiently high temp */

    for (i = 0; i < n; i++)
        if (array[i].temperature < least)
            least = array[i].temperature;

    return least;
}

(注意,least_in_arraylargest_in_arrayaverage_array的每个数量都是指temperature值,因此需要返回类型float。)

largest_in_arrayaverage_array放在一起的其余部分遵循相同的模式。

您剩下的问题的关键在于处理用户输入,以及与使用scanf获取用户输入相关的特定陷阱。它可以完成,但你必须始终验证返回,并通过测试EOF测试用户取消输入(用户按Ctrl + d的结果(或在windoze上按Ctrl + z))。

您必须验证实际发生的预期转换次数,或者您必须处理错误,最重要的是,您必须考虑输入缓冲区中剩余的任何字符(例如stdin),否则,如果输入的条目无效并且你不会从stdin中删除它,你将永远循环...(如果发生匹配或输入失败,则使用scanf - 不处理其他字符 - 将它们留在哪里?(哦,在stdin中)

如果你声明一些帮助函数来清空stdin,你可以自己做这个很容易,并使得从用户获得整数或浮点数的正常过程相对安全。例如,要清空stdin,您只需读取所有剩余的字符,直到遇到'\n'EOF,例如

/** simple function to empty all characters that remain
 *  in stdin. Needed when using scanf for user input.
 */
void empty_stdin()
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

要询问用户intfloat,只需验证返回,检查成功转换的次数(scanf返回的内容),检查EOF是否由用户生成,如果给出了无效输入并且empty_stdin为最后,则最终处理错误需要。您通常希望循环,直到用户提供有效输入或取消。 (无效的输入你没有好处)。

例如,获取整数输入可以按如下方式处理。 (注意:我把它放在一个函数中,以防止在代码主体中为每个输入重复这段代码...

/** abbreviated function to read integer value from user.
 *  returns value on success, exits if user cancels.
 *  empties stdin after call to scanf.
 */
int getint ()
{
    int n = 0;

    for (;;) {              /* loop until valid input or EOF */
        int rtn = 0;        /* variable to capture return of scanf */
        rtn = scanf ("%d", &n);
        if (rtn == 1) {     /* we got an integer */
            empty_stdin();
            break;
        }
        else if (rtn == EOF) {  /* if user cancels, exit */
            fprintf (stderr, "user canceled input.\n");
            exit (EXIT_FAILURE);
        }
        if (rtn == 0)       /* handle error */
            fprintf (stderr, "getint() error: invalid integer input.\n");

        empty_stdin();      /* empty all chars remaining in stdin */
    }

    return n;
}

(获取浮点数的输入以相同的方式工作)。

最后,您通常希望避免在大多数情况下使用float,而不是使用double,只是由于精度损失和使用23-bit尾数表示浮点数的限制。但是,这里我们正在考虑温度,float就足够了。

完全放在一起,你可以做类似下面的事情。注意,我已经在main()之前离开了你的函数,并在main()之后添加了辅助函数定义,但在main()之前提供了声明,因此它们对main()可见:

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

#define NDAYS 365

typedef struct {
    int day,
        month;
    double temperature;
} data;

float least_in_array (data *array, int n)
{
    int i;
    float least = INT_MAX;   /* sufficiently high temp */

    for (i = 0; i < n; i++)
        if (array[i].temperature < least)
            least = array[i].temperature;

    return least;
}

float largest_in_array (data *array, int n)
{
    int i;
    float largest = INT_MIN; /* sufficiently low temp */

    for (i = 0; i < n; i++)
        if (array[i].temperature > largest)
            largest = array[i].temperature;

    return largest;
}

float average_array (data *array, int n)
{
    int i;
    float sum = 0.0;

    for (i = 0; i < n; i++)
        sum += array[i].temperature;

    return sum / (float)n;
}

void empty_stdin();
int getint();
float getfloat();

int main (void) {

    int ndx = 0;
    float max = 0.0, min = 0.0, avg = 0.0;
    data da[NDAYS] = {{0, 0, 0.0}};

    for (;;) {

        int choose = 0;

        printf ("\n  (1) New measurement\n"
                "  (2) Statistics\n"
                "  (3) Exit\n\n"
                "  choice: ");
        choose = getint();
        putchar ('\n');

        switch (choose) {
            case 1: if (ndx == NDAYS) {
                        fprintf (stderr, "error: array full.\n");
                        break;
                    }
                    printf ("    Enter day in month : ");
                    da[ndx].day = getint();
                    printf ("    Enter month        : ");
                    da[ndx].month = getint();
                    printf ("    Enter temperature  : ");
                    da[ndx].temperature = getfloat();
                    printf ("  da[%3d] saved\n"
                            "  ----------------------------\n", ndx++);
                    break;
            case 2: if (ndx == 0) {
                        fprintf (stderr, "error: no measurements taken.\n");
                        break;
                    }
                    min = least_in_array (da, ndx);
                    max = largest_in_array (da, ndx);
                    avg = average_array (da, ndx);
                    printf ("  minimum temp : %.2f\n"
                            "  maximum temp : %.2f\n"
                            "  average temp : %.2f\n"
                            "  ----------------------------\n",
                            min, max, avg);
                    break;
            case 3:
                    goto done;
                    break;
            default:
                    fprintf (stderr, "error: invalid choice.\n");
                    empty_stdin();
                    break;
        }
    }
    done:;

    return 0;
}

/** simple function to empty all characters that remain
 *  in stdin. Needed when using scanf for user input.
 */
void empty_stdin()
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

/** abbreviated function to read integer value from user.
 *  returns value on success, exits if user cancels.
 *  empties stdin after call to scanf.
 */
int getint ()
{
    int n = 0;

    for (;;) {              /* loop until valid input or EOF */
        int rtn = 0;        /* variable to capture return of scanf */
        rtn = scanf ("%d", &n);
        if (rtn == 1) {     /* we got an integer */
            empty_stdin();
            break;
        }
        else if (rtn == EOF) {  /* if user cancels, exit */
            fprintf (stderr, "user canceled input.\n");
            exit (EXIT_FAILURE);
        }
        if (rtn == 0)       /* handle error */
            fprintf (stderr, "getint() error: invalid integer input.\n");

        empty_stdin();      /* empty all chars remaining in stdin */
    }

    return n;
}

/** abbreviated function to read float value from user.
 *  returns value on success, exits if user cancels.
 *  empties stdin after call to scanf.
 */
float getfloat ()
{
    float v = 0.0;

    for (;;) {              /* loop until valid input or EOF */
        int rtn = 0;        /* variable to capture return of scanf */
        rtn = scanf ("%f", &v);
        if (rtn == 1) {     /* we got an float */
            empty_stdin();
            break;
        }
        else if (rtn == EOF) {  /* if user cancels, exit */
            fprintf (stderr, "user canceled input.\n");
            exit (EXIT_FAILURE);
        }
        if (rtn == 0)       /* handle error */
            fprintf (stderr, "getint() error: invalid float input.\n");

        empty_stdin();      /* empty all chars remaining in stdin */
    }

    return v;
}

注意:在代码的测量部分中,数组边界如何限制为365或更少,以及如何检查在提供任何统计数据之前至少存在一个测量值。您始终需要验证流程的每个步骤。寻找角落情况,想想输入可能出现什么问题(如果猫踩到键盘怎么办),然后提供验证和检查来处理每个案例。上面的验证只是最低限度,总有更多可以添加到更完整的报告和处理每个错误条件。

示例使用/输出

$ ./bin/tempmxmnavg

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 2

error: no measurements taken.

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 1

    Enter day in month : 8
    Enter month        : 2
    Enter temperature  : 20.0
  da[  0] saved
  ----------------------------

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 1

    Enter day in month : 9
    Enter month        : 2
    Enter temperature  : 30.0
  da[  1] saved
  ----------------------------

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 1

    Enter day in month : 10
    Enter month        : 2
    Enter temperature  : 70.0
  da[  2] saved
  ----------------------------

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 2

  minimum temp : 20.00
  maximum temp : 70.00
  average temp : 40.00
  ----------------------------

  (1) New measurement
  (2) Statistics
  (3) Exit

  choice: 3

看看事情,如果你有任何进一步的问题,请告诉我(虽然晚上,我不会再在这里......)

© www.soinside.com 2019 - 2024. All rights reserved.