您现在的位置是:首页 >学无止境 >c modern approach 中的chapter22中的一些问题网站首页学无止境

c modern approach 中的chapter22中的一些问题

发狂的蜗牛 2024-07-04 11:18:06
简介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页代码错误。上面是自己的个改正思路。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。