(续三)
再翻翻书,只剩下文件访问了。
以我的观点,文件访问是最“水”的充篇幅的东西,只要写好了输入输出,文件访问就是小菜一碟,一个固定的偷懒流程:
第一步:定义文件指针 FILE *fp;
第二步:使用fopen()打开文件
第三步:把输入输出函数体的printf()和scanf()换成fprintf()和fscanf(),函数实参加上fp
第四步:使用fclose()关闭文件
明白了吧,就是在原来的输入输出函数的基础上,加了个文件的开头和结尾,换汤不换药。本着有始有终的精神,还是写完。
设计5:
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#define MAXSIZE 20
/* 结构体 */
struct compute
{
double a;
double b;
char op;
double r;
}; /* a op b = r */
/* 四则运算 */
double plus(double a, double b)
{
return a+b;
}
double minus(double a, double b)
{
return a-b;
}
double multi(double a, double b)
{
return a*b;
}
double divide(double a, double b)
{
return (b==0?0:a/b);
}
/* 输入两个整数,计算其和 */
void inputData(struct compute *px)
{
printf("请输入表达式:");
scanf("%lf%c%lf", &px->a, &px->op, &px->b);
}
void process(struct compute *px)
{
double (*pf)(double, double);
switch(px->op)
{
case '+': pf=plus; break;
case '-': pf=minus; break;
case '*': pf=multi; break;
case '/': pf=divide; break;
}
px->r = pf(px->a, px->b);
}
void outputData(struct compute x)
{
printf("%.2lf %c %.2lf = %.2lf\n", x.a, x.op, x.b, x.r);
}
/* 随机生成n个整数,计算其和 */
int randomNum(int low, int high)
{
int t;
t=rand();
while(t<0) t=rand();
return low+t%(high-low+1);
}
void inputBatch(int *pn)
{
do {
printf("请输入计算次数(1-%d):", MAXSIZE);
scanf("%d", pn);
}while(*pn<1 || *pn>MAXSIZE);
}
void processBatch(struct compute ax[], int n)
{
int i, t;
for(i=0; i<n; ++i)
{
ax[i].a=randomNum(0,100);
ax[i].b=randomNum(0,100);
t=randomNum(0,3);
switch(t)
{
case 0: ax[i].op='+'; break;
case 1: ax[i].op='-'; break;
case 2: ax[i].op='*'; break;
case 3: ax[i].op='/'; break;
}
process(&ax[i]);
}
}
void outputBatch(struct compute ax[], int n)
{
int i;
for(i=0; i<n; ++i)
outputData(ax[i]);
}
/* 从文件读取表达式,把运算结果写回文件 */
int inputFile(struct compute ax[], int *pn)
{
FILE *fp;
int i=0;
fp=fopen("示例设计.in","r");
if (!fp)
{
printf("无法打开输入文件!\n");
return -1;
}
while(!feof(fp))
{
fscanf(fp, "%lf%c%lf", &ax[i].a, &ax[i].op, &ax[i].b);
i++;
}
*pn=i;
fclose(fp);
return 0;
}
int outputFile(struct compute ax[], int n)
{
FILE *fp;
int i=0;
fp=fopen("示例设计.out","w");
if (!fp)
{
printf("无法打开输出文件!\n");
return -2;
}
for(i=0; i<n; ++i)
{
outputData(ax[i]);
fprintf(fp, "%.2lf %c %.2lf = %.2lf\n", ax[i].a, ax[i].op, ax[i].b, ax[i].r);
}
fclose(fp);
return 0;
}
void showMenu()
{
struct compute xVal, xArr[MAXSIZE];
int i, n;
int in, exitFlag=0;
srand((unsigned)time(NULL)); /* 以当前时间做随机数种子 */
while(1)
{
system("cls");
printf("***************************************\n");
printf("*************** 欢迎使用 **************\n");
printf("***************************************\n");
printf("请选择:\n");
printf(" 1----输入一个表达式,计算结果\n");
printf(" 2----输入多个表达式,批量计算结果\n");
printf(" 3----从文件读取数据,结果写入文件\n");
printf(" 0----结束程序\n");
printf("请输入(1,2,3,0):");
scanf("%d", &in);
switch(in)
{
case 1:
inputData(&xVal);
process(&xVal);
outputData(xVal);
system("pause"); break;
case 2:
inputBatch(&n);
processBatch(xArr,n);
outputBatch(xArr,n);
system("pause"); break;
case 3:
if (!inputFile(xArr,&n))
{
for(i=0; i<n; ++i) process(&xArr[i]);
outputFile(xArr, n);
}
system("pause"); break;
case 0: exitFlag=1; break;
}
if (exitFlag)
{
printf("***************************************\n");
printf("********* 感谢您的使用,再见!*********\n");
printf("***************************************\n");
break;
}
}
system("pause");
}
main()
{
showMenu();
}
OK,到这里所有的课程章节都覆盖到了,剩下的是一些细节调整和边边角角的扫尾工作,这才是一个能够称之为“设计”的程序。
最后,对于“求解两个整数相加”这样的问题,我们一共实现了14个函数(主函数不算),再次比较一下最开始5分钟得到的结果:
#include "stdio.h"
main()
{
int a, b;
printf("请输入两个整数:");
scanf("%d%d", &a, &b);
printf("%d+%d=%d\n", a,b,a+b);
}
是不是觉得它弱爆了?
(未完待续)