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是关闭重定向。