我必须编写一个程序来记录测量的温度,可以输入新的测量值,或显示根据先前测量值计算的统计数据。在打印统计的情况下,有必要找到并显示最低和最高记录温度并计算平均温度。
#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_array
,largest_in_array
和average_array
的代码 - 你没有阵列!这有点让你在“Go!”这个词中落后于八球。
您使用stuct
捕获和协调dayInMonth
,month
和temperature
的想法是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_array
,largest_in_array
和average_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_array
,largest_in_array
和average_array
的每个数量都是指temperature
值,因此需要返回类型float
。)
将largest_in_array
和average_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();
}
要询问用户int
或float
,只需验证返回,检查成功转换的次数(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
看看事情,如果你有任何进一步的问题,请告诉我(虽然晚上,我不会再在这里......)