BSP Day31

C语言文件的一些函数和练习

字符存取函数

_CRTIMP int __cdecl fputc(int, FILE *);
_CRTIMP int __cdecl fgetc(FILE *);

 字符读取函数fgetc()可从文件数据流中一次读取一个字符,然后读取光标移动到下一个字符,并逐步将文件的内容读出。

如果字符读取成功,则返回所读取的字符,否则返回EOF(end of file)。EOF是表示数据结尾的常量,真值为-1。另外,要判断文件是否读取完毕,可利用feof()进行检查。未完返回0,已完返回非零值。

利用feof()函数检查文件是否完毕:

#include <stdio.h>

main()
{
    FILE *fp;
    fp = fopen("c:\\temp\\test.txt", "r");
    if(fp != NULL)
    {
        while(!feof(fp))
            printf("%c", fgetc(fp));
    }
    else
        printf("fail to open! \n");
    fclose(fp);

    return 0;
}

 fputs函数的应用

#include <stdio.h>
#include <conio.h>

int main()
{
    char filename[20], ch;
    FILE *fp;
    printf("Enter a filename: ");
    scanf("%s", filename);
    printf("Enter some characters to output to file: ");
    if((fp = fopen(filename, "w")) == NULL)
        printf("fail to open! \n");
    else
    {
        while((ch = getche()) != '\015')
            fputc(ch, fp);
    }
    fclose(fp);

    return 0;
}

格式化存取函数

函数原型为:

_CRTIMP int __cdecl fprintf(FILE *, const char *, ...);
_CRTIMP int __cdecl fscanf(FILE *, const char *, ...);

它们与printf和scanf函数相仿,都是格式化读写函数。不同的是:fprintf和fscanf函数的读写对象不是终端(标准输入输出),而是磁盘文件。printf函数是将内容输出到终端(屏幕),因此,fprintf就是将内容输出到磁盘文件了。

随机存取函数fseek()

函数原型:

_CRTIMP int __cdecl fseek(FILE *, long, int);

对流式文件可以进行顺序读写,也可以进行随机读写。关键在于控制文件的位置指针,如果位置指针是按字节位置顺序移动的,就是顺序读写。如果能将位置指针按需要移动到任意位置,就可以实现随机读写。所谓随机读写,是指读完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读写文件中任意位置上所需要的字符(字节)。该函数的调用形式为:

fseek(fp, offset, start);

start:起始点。用0、1、2代替。0代表文件开始,名字为SEEK_SET,1代表当前位置,名字为SEEK_CUR,2代表文件末尾,名字为SEEK_END。

fseek()函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时往往会发生混乱。

来看看fprintf和fscanf还有fseek函数的应用吧

#include<stdio.h>
typedef struct stu
{
	int id;
	char name[20];
	float score;
	char sex[10];
}Stu;

int main()
{
/*	FILE *fp = fopen("./张学友.txt","a+");
	char name[20] = "张学友";
	float score = 92.3;
	char sex[10] = "男";
	if(fp == NULL)
	{
	perror("fopen");	
	 } 
	 fprintf(fp,"%s %.1f %s",name,score,sex);*/
	 Stu ming[3] = {{1001,"郭富城",90.1,"男"},{1002,"刘德华",99.9,"男"},{1003,"黎明",96.6,"男"}};
	  FILE *fp = fopen("./张学友.txt","r+");
	  if(fp == NULL)
	{
	perror("fopen");	
	 } 
	 int i;
/*	 for(i=0;i<3;i++)
	 {
	 	fprintf(fp,"%d %s %.1f %s\n",ming[i].id,ming[i].name,ming[i].score,ming[i].sex);
	 }*/
	Stu xing[3];
	rewind(fp);
	for(i=0;i<3;i++)
	 {
	 	fscanf(fp,"%d %s %f %s",&xing[i].id,xing[i].name,&xing[i].score,xing[i].sex);
	 }
	
	for(i=0;i<3;i++)
	 {
		printf("%d %s %.1f %s\n",xing[i].id,xing[i].name,xing[i].score,xing[i].sex);
	 }
	 int ret = ftell(fp);
	 printf("%d\n",ret);
	 
	 fseek(fp,-14,2);
	 fputs("辣目洋子",fp);
	 fclose(fp);
	
	return 0;
 } 

ftell函数 

ftell() 函数的作用是 获取文件的 当前指针位置相对于 文件首地址 的 偏移字节数 ;

ftell 使用场景 : 随机方式存取文件时 , 使用 fseek 函数来回移动指针 , 不容易确定当前指针位置 , 通过调用 ftell 函数确定指针位置 ;

#include <stdio.h>

int main()
{
    // 以写文本的方式向文件中写出数据
    FILE *p = fopen("D:/File/number.dat", "w");
    // 写出 10 个字符
    char array[10] = {1,2,3,4,5,6,7,8,9,10};
    // 将 10 个字符写出到文件中
    fwrite(array, 1, sizeof(array), p);
    // 关闭文件
    fclose(p);




    // 跳过 4 字节读取文件 2 字节
    FILE *p2 = fopen("D:/File/number.dat", "r");

    // 使用 ftell 函数获取当前指针位置
    int location = ftell(p2);
    // 刚打开文件 , 还未读取数据 , 指针指向 0 位置 ★★★
    printf("location = %d\n", location);

    // 读取数据缓冲区
    char array2[2];

    // 跳过 4 字节 , 此时当前位置是 0
    fseek(p2, 4, SEEK_CUR);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);
    // 跳过了 4 字节数据 , 偏移了 4 字节 ,
    // 指针指向第 5 字节 , 索引 4 ★★★
    printf("location = %d\n", location);

    // 读取 2 字节
    fread(array2, 1, sizeof(array2), p2);
    // 打印前 2 字节数据
    printf("%d , %d\n", array2[0], array2[1]);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);
    // 跳过了 4 字节数据 , 又向后读取 2 字节 ,
    // 偏移了 6 字节 , 指向第七字节 , 索引 6 ★★★
    printf("location = %d\n", location);

    return 0;
}

 通过ftell函数计算文件大小

#include <stdio.h>

int main()
{
    // 以写文本的方式向文件中写出数据
    FILE *p = fopen("D:/File/number.dat", "w");
    // 写出 10 个字符
    char array[10] = {1,2,3,4,5,6,7,8,9,10};
    // 将 10 个字符写出到文件中
    fwrite(array, 1, sizeof(array), p);
    // 关闭文件
    fclose(p);




    // 先打开文件
    FILE *p2 = fopen("D:/File/number.dat", "r");

    // 将文件指针移动到文件末尾
    fseek(p2, 0, SEEK_END);

    // 使用 ftell 函数获取当前指针位置
    int location = ftell(p2);

    // 通过读取当前文件指针位置, 即可获取文件大小 ★★★
    printf("filesize = %d\n", location);

    // 将文件指针恢复
    fseek(p2, 0, SEEK_SET);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);

    // 查看指针是否恢复 ★★★
    printf("location = %d\n", location);

    return 0;
}

 接下来分享俩个练习题

1.有俩个磁盘文件“A”,和“B”,各自存放一行字母,要求把俩个文件中的信息合并(按字母顺序排列),输出到一个新文件“C”中

#include <stdio.h>
#include <string.h>
int main()
{
	FILE *fp1 = NULL;
	FILE *fp2 = NULL;
	FILE *fp3 = NULL;
	char buf1[100] = {0};
	char buf2[100] = {0};
	char buf3[200] = {0};
	int i;
	int j;
	int length;
	char temp;
	fp1 = fopen("A.txt", "r");
	fp2 = fopen("B.txt", "r");
	fp3 = fopen("C.txt", "w");
	fgets(buf1, 99, fp1);
	fgets(buf2, 99, fp2);
	strcpy(buf3, buf1);
	strcat(buf3, buf2);
	length = strlen(buf3);
	for(i=0;i<length-1;i++)
	{
	for(j=i+1;j<length;j++)
	{
	if(buf3[i]>buf3[j])
	{
	temp = buf3[i];
	buf3[i] = buf3[j];
	buf3[j] = temp;
	}
	}
	}
	fputs(buf3, fp3);
	fclose(fp3);
	fclose(fp2);
	fclose(fp1);
return 0;
}

2.定义一个结构体数组,保存员工的姓名,工号,工资,用fseek函数修改员工的姓名和工资。

例:4个员工信息 2208 zhangsan 10000

2107 lisi 12000

2109 wangwu 13000

2003 xiaoming 15000

#include<stdio.h>
typedef struct stu
{
	int id;
	char name[20];
	int score;
 }Stu;
int main()
{
	Stu yuan[4] = {{2208,"zhangsan",10000},{2107,"lisi",12000},{2019,"wangwu",13000},{2003,"xiaoming",15000}};
	FILE *fp = fopen("./1.txt","w+");
	if(fp == NULL)
	{
		perror("fopen");
	}
	int i;
	for(i=0;i<4;i++)
	{
		fprintf(fp,"%d %s %d\n",yuan[i].id,yuan[i].name,yuan[i].score);
	}
	rewind(fp);
	for(i=0;i<4;i++)
	{
		fscanf(fp,"%d %s %d",&yuan[i].id,yuan[i].name,&yuan[i].score);
	}
	for(i=0;i<4;i++)
	{
		printf("%d %s %d\n",yuan[i].id,yuan[i].name,yuan[i].score);
	}
	fseek(fp,-28,2);
	fputs("15000",fp);
	fseek(fp,-16,2);
	fputs("wangming",fp);
	printf("\n");
	rewind(fp);
	for(i=0;i<4;i++)
	{
		fscanf(fp,"%d %s %d",&yuan[i].id,yuan[i].name,&yuan[i].score);
	}
	for(i=0;i<4;i++)
	{
		printf("%d %s %d\n",yuan[i].id,yuan[i].name,yuan[i].score);
	}
	fclose(fp);
	return 0;
	}

 重定向

函数名:freopen

函数定义:FILE *freopen( const char *path, const char *mode, FILE *stream ); 

 它的返回值是一个文件指针

功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。

stdin           标准输入文件(一般指键盘scanf(),getchar()等函数默认从stdin获取输入)

stdout         标准输出文件(一般指显示器printf(),putchar()等函数默认向stdout输出数据)

stderr          标准错误文件(一般指显示器perror()等函数默认向stderr输出数据)

stdprn         标准打印文件,一般指打印机

#include<stdio.h>

int main()
{
/*	FILE *fp = freopen("stdout.txt","w",stdout);
	 if(fp == NULL)
	 {
	 	perror("freopen");
	 }
	 puts("a");
	 puts("b");
	 fclose(fp);
	freopen("CON","w",stdout);
	puts("c");*/
	FILE *fp = freopen("stdout.txt","r+",stdin);
	if(fp == NULL)
	 {
	 	perror("freopen");
	 }
	 char arr[20];
	 fgets(arr,10,fp);
	 printf("%s",arr); 
	
	return 0;
}

CON是关闭重定向。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixiaxiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值