c语言fprintf后fp->curp自动后移,利用C语言操作文件

1、C文件概述C语言把文件看作一个字符的序列,即由一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件有称为文本(text)文件,它的每个字节存放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出。如果一个数10000,在内存中占2个字节。如果按照ASCII存储则占5个字节,如按二进制存储则占2字节。如下:二进制形式内存中样式ASCII形式

00100111 000100000100111 000100000110001 ----> 1

00110000 ----> 0

00110000 ----> 0

00110000 ----> 0

00110000 ----> 0

由前述,一个C文件是一个字符流或二进制流。在C语言中文件的存取以字符(字节)为单位。输入输出的数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制。也就是说,在输出时不会增加回车换行符作为记录结束的标志,输入时不以回车换行符作为间隔。这种文件称为流式文件。

在过去使用C版本有两种对文件的处理方式:a、缓冲文件系统 b、非缓冲文件系统。缓冲文件系统在每次向文件读写时都进过缓冲区。

2、文件类型指针缓冲文件系统中,关键的概念是“文件指针”。每个被使用的文件在内存中开辟一个区,用来存放文件的有关信息。这些信息保存在一个结构体变量中。该结构体有系统定义的,取名为FILE。在Turbo C中stdio.h对文件定义如下:typedef struct

{

short                  level;               /* 缓冲区“满”或“空”的程度 */

unsigned               flags;               /* 文件状态标志 */

char                   fd;                  /* 文件描述符 */

unsigned    char       hold;                /* 如无缓冲区不读去字符 */

short                  bsize;               /* 缓冲区的大小  */

unsigned    char       *buffer;             /* 数据缓冲区的位置 */

unsigned    ar         *curp;               /* 指针,当前的指向 */

unsigned               istemp;              /* 临时文件,指示器 */

short                  token;               /* 用于有效性检查 */

} FILE;

有了文件FILE结构体类型后,就可以定义文件类型的变量和指针变量。如:

FILE f[5]  定义一个文件数组

FILE *fp 定义一个文件指针

3、文件的打开和关闭ANSI C规定了标准输入输出函数库,用fopen()函数来实现打开文件。fopen函数调用方式通常为:FILE * fp;

fp = fopen(文件名, 使用文件方式);文件使用方式含义

“r”(只读)为输入打开一个文本文件

“w”(只写)为输出打开一个文本文件

“a”(追加)向文本文件尾添加数据

“rb”(只读)为输入打开一个二进制文件

“wb”(只写)为输出打开一个二进制文件

“ab”(追加)向二进制文件末尾添加数据

“r+”(读写)为读写打开一个文本文件

“w+”(读写)为读写建立一个新的文本文件

“a+”(读写)为读写打开一个文本文件

“rb+”(读写)为读写打开一个二进制文件

“wb+”(读写)为读写建立一个新的二进制文件

“ab+”(读写)为读写打开一个二进制文件

说明:

(1)用"r"打开的文件只能用于向计算机输入文件,而且该文件已经存在。不能打开不存在的文件,否则会报错。

(2)用"w"打开的文件只能用于输出文件。如果不存在文件,则在打开是新建一个以指定名称的文件。如果存在,则删除存在的文件,然后重新建立一个新文件。

(3)如果使用"a"方式打开则可以向文件末尾追加数据,但是该文件必须已经存在。打开时,位置指针移动到文件末尾。

(4)使用"r+"、"w+"、"a+"方式打开的文件仅可以读也可以写。用“r+”打开的文件必须存在,用"w+"删除旧文件,重新建立新文件。用"a+"方式打开不会删除文件。

(5)如果打开文件失败,fopen()函数返回一个NULL(NULL在stdio.h文件中定义为0)。如:if((fp = fopen("file1", "r")) == NULL)

{

printf("不能打开这个文件\n");

exit(0);

}

(6)在向计算机输入文本文件时,回车换行符被替换成一个换行符,输出时转换成回车换行符。二进制文件,则原样保存。

(7)在程序开始运行时,系统自动打开3个标准输入输出。stdin标准输入、stdout标准输出、stderr标准出错输出。

常用函数简介:

1、fclose(文件指针)函数用于关闭文件,关闭成功返回0。否则返回EOF(-1)。如:fclose(fp);

2、fputc(输出字符,文件指针)函数把一个字符写到磁盘上去。如:fputc(ch,fp)表示将ch字符输出到fp指向的文件中去。输出成功返回输出的字符,否则返回EOF

3、putchar函数是从fputc函数派生而来。#define putchar(c) fputc(c, stdout)

4、fgetc(文件指针)函数从指定的文件中读取一个字符,该文件必须以读或读写方式打开的。如:ch = fgetc(fp);从fp指定的文件中取出一个字符,赋给ch变量。ch = fgetc(fp);

while( ch != EOF)

{

putchar( ch );

ch = fgetc( fp);

}

以上是将一个文件以顺序显示在屏幕上。

注意:

EOF不是可输出字符,因为ASCII码不可能出现-1。当读取文件等于-1(EOF)时,表示读入的已不是正常字符而是文件结束符。但是值适合于文本文件。当读取二进制文件时,读取的数据可能为-1,因此ANSI C提供了feof(文件指针)函数来判断文件是否已经结束。如果结束,feof(文件指针)返回值为1(真),否则为0(假);

如:while( !feof(fp) )

{

c = fgetc( fp );

}

可以顺利的读取一个二进制文件

【实例】从键盘输入一个字符串,逐个把他们写到磁盘文件上,知道输入‘#’为止。#include 

#include 

void main()

{

FILE * fp;

char ch, filename[10];

scanf("%s", filename); // 提示用户输入文件名

if((fp = fopen(filename, "w")) == NULL)

{

printf("不能打开文件\n");

exit(0); // 终止程序

}

ch = getchar(); // 用来接收在执行scanf语句时最后输入的回车符

ch = getchar(); // 接受输入的第一个字符

while(ch != '#')

{

fputc(ch, fp); // 写入到文件中去

putchar(ch);

ch = getchar();

}

putchar(10); // 向屏幕输出一个换行符

fclose(fp);

}

【实例】将文件中的数据输出到屏幕上#include 

#include 

void main()

{

FILE *in;

char ch, infile[10];

printf("请输入文件名:\n");

scanf("%s", infile);

if( (in = fopen(infile, "r")) == NULL)

{

printf("打开输入文件失败\n");

exit(0);

}

// 将文件中的数据输出到屏幕上

while( !feof(in))

{

putchar(fgetc(in));

}

// 关闭文件

close(in);

}

【实例】将一个文件的数据写入到另一个文件中去。#include 

#include 

void main()

{

FILE *in, *out;

char ch, infile[10], outfile[10];

printf("请输入被拷贝文件名:\n");

scanf("%s", infile);

printf("请输入拷贝文件名:\n");

scanf("%s", outfile);

// 打开输入文件

if( (in = fopen(infile, "r")) == NULL)

{

printf("打开输入文件失败\n");

exit(0);

}

// 打开输出文件

if( (out = fopen(outfile, "w")) == NULL)

{

printf("打开输出文件失败\n");

exit(0);

}

// 将输入文件的数据写入到输出文件中去

while( !feof(in))

{

fputc(fgetc(in), out);

}

// 关闭文件

close(in);

close(out);

}

对文件之间拷贝的改进:#include 

#include 

void main(int argc, char * argv[]) // argc-表示参数argv数组的长度 argv-表示参数

{

FILE *in, *out;

char ch;

if(argc != 3)     // argv[0]-可执行文件名 argv[0]-输入文件名 argv[0]-输出文件名

{

printf("你忘记输入文件名");

exit(0);

}

if( (in = fopen(argv[1], "r")) == NULL)

{

printf("打开输入文件失败\n");

exit(0);

}

if( (out = fopen(argv[2], "w")) == NULL)

{

printf("打开输出文件失败\n");

exit(0);

}

// 将文件中的数据输出到屏幕上

while( !feof(in))

{

fputc(fgetc(in), out);

}

// 关闭文件

close(in);

}

运行方式:

C:\> fileExe text.txt new.txt

5、fread(buffer, size, count, fp) 和 fwrite(buffer、size、count、fp)

参数介绍:

buffer   要读入/写出存放数据的地址(起始地址)

size      要去读的字节数

count    要读写多少个size字节的数据

fp          文件指针

如:fread(f,4,2,fp)表示从fp中读取2个4字节的数据到数组f中

如果存在一下学生信息结构体:struct student_type

(

char     name[20];    -- 学生姓名

int        num;            --    学号

int        age;             --    年龄

char     addr[30];     -- 居住地址

)stud[40];

我们可以使用一下语句读取和写出数据。for(i = 0; i 

{

fread(&stud[i], sizeof(struct student_type), 1, fp);

}

for(i = 0; i 

{

fwrite(&stud[i], sizeof(struct student_type), 1, fp);

}

如果调用成功放回count的值。

【实例】从键盘输入4个学生的有关数据,然后将他们存到磁盘文件上。#include 

#include 

#define SIZE 4

struct student_type

{

char name[20];       // 姓名

int    num;          // 学号

int    age;          // 年龄

char addr[15];       // 地址

} stud[SIZE];

void save()

{

FILE *fp;

int i;

if((fp = fopen("student_list","wb")) == NULL)

{

printf("打开student_list文件失败\n");

return;

}

for(i=0; i

{

if(fwrite(&stud[i], sizeof(struct student_type), 1 , fp) != 1)

{

printf("写入错误\n");

}

}

fclose(fp);

}

void main( )

{

int i;

for(i = 0; i 

{

scanf("%s%d%d%s", stud[i].name, &stud[i].num, &stud[i].age, stud[i].addr);

}

save();

}

【实例】将上面写入的数据读取到屏幕上面#include 

#include 

#define SIZE 4

struct student_type

{

char name[20];

int num;

int age;

char addr[15];

} stud[SIZE];

void main()

{

int i;

FILE *fp;

fp = fopen("student_list", "rb");

for(i = 0; i 

{

fread(&stud[i], sizeof(struct student_type), 1, fp);

printf("%-10s%4d%4d%-15s\n", stud[i].name, stud[i].num, stud[i].age, stud[i].addr);

}

fclose(fp);

}

注意:fread()和fwrite()一般用于二进制文件的输入输出。因为他们是按照数据块的长度来处理输入输出的,在字符串发生转换的情况下很有可能出现与原设想不同的情况。

【实例】将一个已经存在学生基本信息的文件加载到内存,然后写入到新的文件中去。#include 

#include 

#define SIZE 4

struct student_type

{

char name[20];

int  num;

int  age;

char addr[15];

} stud[SIZE];

/**

* 将student_list文件中保存的学生信息加载到内存中

*/

void load()

{

FILE *fp;

int i;

if((fp = fopen("student_list","rb")) == NULL)

{

printf("打开student_list文件失败\n");

exit(0);

}

for(i=0; i

{

if(fread(&stud[i], sizeof(struct student_type), 1, fp) != 1)

{

if(feof(fp))

{

fclose(fp);

return;

}

printf("\n");

}

}

}

/**

* 将加载到内存的数据保存到new_student_list文件中

*/

void save()

{

FILE *fp;

int i;

if((fp=fopen("new_student_list", "wb")) == NULL)

{

printf("打开new_student_list文件失败\n");

exit(0);

}

for(i=0; i

{

if(fwrite(&stud[i], sizeof(struct student_type), 1, fp) != 1)

{

printf("向new_student_list文件写入数据失败\n");

}

}

fclose(fp);

}

void main()

{

load();

save();

}

6、fprintf( )和fscanf( )函数

这两个函数与printf和scanf函数作用相仿,都是格式化读写函数。只有一点不同:fprintf和fscanf函数的读写对象不是终端而是磁盘文件。它们的一般格式为:

fprintf(文件指针、格式化字符串、输出列表)

fscanf(文件指针、格式化字符串、输入列表)

如:fprintf(fp, "%d,%6.2f", i, c) 写到磁盘文件

fscanf(fp, "%d,%f", &i, &t) 磁盘文件上存在:3,4.5

【实例】将0~9十个数字写入到number.txt文件中#include 

#include 

void main()

{

FILE *fp;

int i;

if((fp = fopen("number.txt", "w")) == NULL)

{

printf("不能打开文件\n");

exit(0);

}

// 向number.txt文件循环写入0~9数字

for(i=0; i<10; i++){

fprintf(fp, "%d", i);

}

fclose(fp);

}

【实例】从磁盘文件读取数据,存到变量中,然后将变量输出到屏幕上。#include 

#include 

void main()

{

FILE *fp;

int a;

float b;

if((fp = fopen("number.txt", "r")) == NULL)

{

printf("不能打开文件\n");

exit(0);

}

fscanf(fp, "%d,%f", &a, &b); // 20,25.4

printf("a=%d, b=%f\n", a, b); // a=20, b=25.4

fclose(fp);

}

用fprintf或fscanf对磁盘文件进行读写,使用方便,容易理解。但由于在输入时要将ASCII码转换成二进制格式,在输出时要将二进制转换成字符,花费时间较多。因而,在内存与磁盘交换频繁时,最好不要用fprintf和fscanf函数,而用fread和fwrite函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值