您现在的位置是:首页 >学无止境 >c modern approach 中的chapter22中的一些问题网站首页学无止境
c modern approach 中的chapter22中的一些问题
//一定要先关闭流,再释放缓存器,特别是具有自动存储期限的缓存器,一定要在函数返回之前要关闭流
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char buffer1[L_tmpnam];
char buffer2[L_tmpnam * 2];
char fileName[L_tmpnam];
FILE * fp1 = tmpfile();
if(fp1 == NULL)
{
printf("create file error");
exit(EXIT_FAILURE);
}
setbuf(fp1,buffer1);
printf("create file success.");
printf("
tmpnam :%s",tmpnam(NULL));
printf("
tmpname len is %u
",L_tmpnam);
tmpnam(fileName);
FILE * fp2 = fopen(fileName,"w");
if(fp2 == NULL)
{
printf("file %s cannot opened.
",fileName);
setvbuf(fp2,NULL,_IOLBF,sizeof(buffer2) / sizeof(buffer2[0]));
}
else
printf("%s is created success.",fileName);
fflush(stdin);
fflush(stdout);
fflush(stderr);
fflush(fp1);
fflush(fp2);
fflush(NULL);
return 0;
}
下面的代码是fscanf的应用的一个例子:
#include <stdio.h>
int main(void)
{
char line[50];
FILE *fp = fopen("data.txt","r");
fscanf(fp,"%s",line);
printf("line is:%s",line);
return 0;
}
注:scanf和fscanf都返回读入的数据项的数量,如果读入失败(可能有如下三种情况)
1.输入的数据不匹配
2.没有数据可以读
3.(c99 only)编码错误:我们试图按照多字节字符读入,但是我们的读入的字符不是有效的多字节字符。
下面利用fscanf的返回值来编写程序:
数据文件data1.txt如下:
1 23 45 6 789
99
888
main.c
#include <stdio.h>
int main(void)
{
char line[50];
FILE *fp = fopen("data1.txt","r");
int num;
while(fscanf(fp,"%i",&num) == 1) //如果成功读入,那么一定返回1,如果不成功,会提前返回EOF
{
printf("%d
",num);
}
return 0;
}
代码输出如下:
1
23
45
6
789
99
888
因为scanf和fscanf执行失败会返回EOF,所以程序中的循环部分可以如下书写:
while(fscanf(fp,"%i",&num) != EOF)
scanf会有3个规则
(1)会跳过开始的空白,但是不会跳过末尾的空白。
(2)scanf中的一个或者多个空白字符,匹配实际输入中的0个或者多个空白字符。
(3)scanf中的每个非空白字符会匹配实际中的非空白字符。
当读取文件的时候,如果读取的数据项的数量不是正确的,那么可能会有以下3种情况:
(1)流发生错误。ferror(fp) 不为0 ,fp是流的名称
(2)流到达了文件末尾,feof(fp)不为0,fp是流的名称。
(3)匹配错误。此时feof和ferror均不会置位(也就是函数调用都不会返回1)。此时不会读入任何字符。以下程序是上述结论的一个简单应用:
#include <stdio.h>
#include <stdlib.h>
#define fileName "data.txt"
int main()
{
FILE *fp = fopen(fileName,"r");
int n;
if(fp == NULL)
{
printf("can't open %s",fileName); //can't open file
return -1;
}
while(fscanf(fp,"%d",&n) != 1)
{
if(ferror(fp))
{
printf("error:ferror."); //integer not found
fclose(fp);
return -2;
}
else if(feof(fp))
{
printf("error:feof.");
fclose(fp);
return -3;
}
fscanf(fp,"%*[^
]"); /*skip the rest of line */
}
fclose(fp);
printf("first num:%d
",n);
return 0;
}
asdfsadf adfgasjf asf
eof
asdf
ka
eof
123
asdf
asdf
asdf
运行结果:
first num:123
每个文本文件都有一个文件结束符,这个文件结束符在C中可以表示为EOF(具体是什么根据操作系统而异)。
#include <stdio.h>
int main()
{
char *filename = "data.txt";
FILE * fp = fopen(filename,"r");
int ch; //字符类型用int表示,因为int可以表示EOF,char(可能是unsigned char)不一定可以
//为了万无一失,写成int类型
while((ch = getc(fp)) != EOF) //文件结束符号用EOF表示
{
printf("%c",ch);
}
return 0;
}
上述方法可以打印一个文本文件(文件中的每个字符)到标准输出中。
下面看一个文件复制的例子,来练习下fget、fput这两个函数
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char ** argv)
{
int ch;
FILE *source_fp, *dest_fp;
if((source_fp = fopen(argv[1],"rb")) == NULL)
{
printf("usage:source_fp can't be opened.
");
exit(EXIT_FAILURE);
}
if((dest_fp = fopen(argv[2],"wb")) == NULL) {
printf("usage:dest_fp can't be opened.
");
fclose(dest_fp);
exit(EXIT_FAILURE);
}
while((ch = fgetc(source_fp)) != EOF) //这句可能会出问题,因为如果二进制文件,那么EOF不可作为文件结束符
{
fputc(ch,dest_fp);
}
fclose(source_fp):
fclose(dest_fp);
return 0;
}
注意以下几点:
(1)文件打开方式,都是二进制打开方式,rb,wb。不用二进制打开文件,可能会引发错误。
(2) 一定要及时地关闭不用的文件。
(3)二进制文件也可以用EOF判断文件末尾?答案肯定是否定的。所以,自己重新编写了循环部分代码:
while(!feof(source_fp))
{
ch = getc(source_fp);
fputc(ch,dest_fp);
}
c语言现代方法第二版,405页代码错误。上面是自己的个改正思路。