这个程序把一个文件中的数据有选择的复制到另一个文件中。它同时打开两个文件,对其中一个使用"r"模式打开,对另一个使用“w”模式打开。程序清单13.2通过只保留每3个字符中的第3个来压缩第1个文件中的内容。最后,它把压缩后的文本写入到第二个文件中。第二个文件的名称就是第一个文件名后加.red(代表reduced)而得到的。
使用命令行参数,同时打开多个文件,以及对文件名进行追加操作,这些通常都是相当有用的技术。
程序清单13.2 reducto.c程序
//reducto.c--把您的文件压缩为原来的三分之一!
#include <stdio.h>
#include <stdlib.h> //调用exit()
#include <string.h> //为strcpy()和strcat()函数提供原型
#define LEN 40
int main(int argc,char * argv[])
{
FILE * in,* out; // 声明两个FILE指针
int ch;
char name[LEN]; //用于存储输入的文件名
int count=0;
//检查命令行参数
if(argc<2)
{
fprintf(stderr,"usage:%s filename\n",argv[0]);
exit(1);
}
//实现输入
if((in=fopen(argv[1],"r"))==NULL)
{
fprintf(stderr,"I couldn't open the file \"%s\"\n",argv[1]);
exit(2);
}
//实现输出
strcpy(name,argv[1]); //把文件名复制到数组中
strcat(name,".red"); //在文件名后添加.red
if((out=fopen(name,"w"))==NULL)
{
fprintf(stderr,"Can't create output file.\n");
exit(3);
}
//复制数据
while((ch=getc(in))!=EOF)
if(count++ % 3 ==0)
putc(ch,out); //打印每3个字符中的1个
//收尾工作
if(fclose(in)!=0 || fclose(out)!=0)
fprintf(stderr,"Error in closing files\n");
return 0;
}
可执行文件名为reducto。我们用它对包含下面这行内容的文件eddy进行操作:
So enen Eddy came oven ready.
命令如下:
erducto eddy
输出结果被写入文件名为eddy.red的文件中。程序不产生任何屏幕输出,但打开文件eddy.red会显示如下内容:
Send money
这个例子演示了多项编程技术,下面我们来看看其中一些。
除了需要一个文件指针作为第一个参数以外,fprintf()和printf()函数基本一致。我们使用stderr指针把错误消息发送到标准错误文件,这是一个标准的C惯例。
为了给输出文件构建一个新的文件名,程序使用strncpy()函数把名字edd复制到数组name中。参数LEN-5为.red后缀名和最后一个空字符保留下空间。如果argv[2]字符串比LEN-5还长,就不会有空字符被复制了,因此程序只有在这种情况下添加一个空字符。调用strncpy()后name中的第一个空字符在strcat()函数附加上.red的时候,被其中的句号(.)给覆盖了,从而产生了eddy.red。我们还检查程序是否成功打开了文件名为eddy.red的文件。这在某此环境下尤为重要,因为像strange.c.red这们的文件名是非法的。例如,在DOS环境下不能再为文件后缀添加后缀(适用于DOS的方法是用后缀.red替换任何已有的后缀,这样压缩版本strange.c变成strange.red。例如,可以使用strchr()函数来定位文件名中的句号,然后只复制字符串中句号前的部分)。
这个程序同时打开两个文件,因此我们声明了两个FILE指针。注意每个文件的打开和关闭都是独立的。同时可以打开的文件数目是有限的。这个限制取决于系统和实现;范围通常是10-20之间。可以使用同一个文件指针指向不同的文件,但前提是不能同时打开这些文件。