使用结构进行测量并搜索最小、最大和平均温度

  • 本文关键字:温度 搜索 结构 测量 c
  • 更新时间 :
  • 英文 :


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

#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">

既然是平安夜,那就让我们帮助一下同胞吧......他们显然急需帮助。对于应该将array传递给least_in_arraylargest_in_arrayaverage_array的代码 - 您没有数组!这有点让你落后于"去!"这个词的八球。

你的想法是用stuct来捕捉和协调dayInMonthmonthtemperature是100%正确的。(但请注意:C 样式通常避免camelCase变量名称,而支持所有小写)。此外,在main()中定义struct Data1会阻止该点以上的函数知道struct Data1是什么,因此您需要将结构定义移动到文件顶部。(或提供前向声明,但我们会将其保存以备后用)现在,让我们将您的Data1移到顶部(我使用了一个typedef来减轻每次使用前缀stuct并重命名Data1data

#define NDAYS 365
typedef struct {
int day,
month;
double temperature;
} data;

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

现在,在我们进一步讨论之前,让我们考虑一下我们的数组。如果我们要使用struct来保存相关的日期和温度测量值,那么我们将需要一个数组...什么??struct数组。并且使用常量NDAYS,我们将在数组中声明最多365个元素。那么这将如何工作呢?我们有我们的结构类型定义到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(或Ctrl+z在 windoze 上)的结果)来测试用户取消输入。

您必须验证预期的转换次数是否确实发生了,或者您必须处理错误,最重要的是,您必须考虑输入缓冲区中剩余的任何字符(例如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 measurementn"
"  (2) Statisticsn"
"  (3) Exitnn"
"  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] savedn"
"  ----------------------------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 : %.2fn"
"  maximum temp : %.2fn"
"  average temp : %.2fn"
"  ----------------------------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

看看事情,如果你有任何其他问题,请告诉我(虽然考虑到晚上,我不会在这里待太久......

最新更新