/**
c primer plus 6th Ch13
4.编写一个程序,不接受任何命令行参数或接受一个命令行参数。如果
有一个参数,将其解释为文件名;如果没有参数,使用标准输入(stdin)作
为输入。假设输入完全是浮点数。该程序要计算和报告输入数字的算术平均
值。
**/
#include <stdio.h>
#include <stdlib.h> // 提供 exit()的原型
int main(int argc, char* argv[]) //命令行参数存储在指针数组中
{
FILE* fp = stdin; //FILE可以看成是一个类
double num;
int count = 0;
double sum = 0.0;
if(argc >= 2)
{
if((fp = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "can`t open file %s.\n", argv[1]);
exit(EXIT_FAILURE);
}
}
//while(1 == fread(&num, sizeof(double), 1, fp)) //num = 0.0000, why? And can`t loop out if fp = stdin
while(fscanf(fp, "%lf", &num) == 1)//fscanf()读到非"%lf"格式的输入时,返回0
{
//printf("DEBUG: num = %lf\n", num);
count++;
sum += num;
}
if(ferror(fp)) //因为读到文件结尾或者读写错误时,I/O函数都会返回EOF。区分方法:foef()返回非空表示读到文件结尾,ferror()返回非空表示读写出错。
{
printf("read file %s error.\n", argv[1]);
exit(EXIT_FAILURE);
}
if(fclose(fp))
{
fprintf(stderr, "can`t close file %s.\n", argv[2]);
exit(EXIT_FAILURE);
}
if(0 == count)
{
printf("No valid values.\n");
return 0;
}
printf("%f\n", sum/count);
return 0; //exit()和return的区别:前者会退出整个程序,后者只是将控制权交给上级代码。
}
本书给的参考答案:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv [])
{
FILE * fp;
double n;
double sum = 0.0;
int ct = 0;
if (argc == 1)
fp = stdin;
else if (argc == 2)
{
if ((fp = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
else
{
fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
exit(EXIT_FAILURE);
}
while (fscanf(fp, "%lf", &n) == 1)
{
sum += n;
++ct;
}
if (ct > 0)
printf("Average of %d values = %f\n", ct, sum / ct);
else
printf("No valid data.\n");
return 0;
}