C语言学习笔记13-文件

C语言-文件操作基础

格式化输入输出

printf 与 scanf 函数的格式占位符详细说明——

(1)printf格式占位符:%[flags][width][.prec][hlL]type
[flags] 包含4类功能符号: - 左对齐 、 + 带符号 、 (space) 留空 、 0 左侧空位补零
  【补充说明】
  (1)可以同时用多个,如±表示带符号且左对齐;
  (2)用了左对齐后,留空、补零就没用了;
  (3)不配合 [width] 使用时就只有 (space) 和 + 有效果,所以一般配合width一起用。
[width] 数据占位宽度(至少),可以用 * 表示下一个参数是占位宽度,输出超过宽度时按实际输出。
[.perc] 数据小数点后保留位数,体现精度,也可以用 * 表示下一个参数是小数点后位数。其值一般小于(width - 1),不然没有实际意义,小数点也是算1位的。
[hlL] 类型修饰分5种: hh 单个字节(地址低位) 、 h short型 、 l long 、 ll long long 、 L long double

type

符号			用于
i 或 d		int
u			unsigned int
o			八进制
x 或 X		十六进制(小写、大写)
f 或 F		float (有效精度6)
e 或 E		指数 (科学计数法)
g 或 G		float
a 或 A		十六进制浮点数
c			char
s			字符串
p			指针/地址
n			读入/写出的个数

在这里插入图片描述
在这里插入图片描述

(2)scanf格式占位符:%[flag]type
[flag]符号种类:

符号		含义
*		跳过一个当前类型
数字		最大字符数,输入超过时截断
hh		char
h		short
l		long、double
ll		long long
L		long double

type

符号			用于
d			int
i			整数,默认十进制(0或0x开头表示八进制或十六进制)
u			unsigned int
o			八进制
x			十六进制
a e f g		float
c			char
s			字符串
p			指针/地址
[...]		所允许的字符,如 %[^,],

(3)printf和scanf的返回值
printf函数的返回值是输出的字符数(\n等符号也计入计算);
scanf函数的返回值是读入的变量数。
要求严格的程序中应判断每次调用scanf和printf的返回值是否发生异常,采取相应动作及时处理。

文件输入输出

文本文件读写
(1)特殊的方式
格式化输入输出配合 符号 > 和 < 重定向功能实现文件的读写 —— linux系统或者dos系统编译文件时,通过符号 > 可以将程序输出写入指定文件,通过符号 < 可以从指定文件将数据读入程序。
linux文本操作命令:打开:more 、 od 或 tail 打开写入:cat 实现完整文件操作:vi

(2)一般的方式 借助 <stdio.h> FILE
函数: fopen fclose fscanf读取 fprintf写入

二进制读写
函数: fread fwrite 一般用于对n个结构变量操作,指针参数在最后,函数返回成功读写的字节数
ftell fseek 文件中定位
SEEK_SET从头开始 SEEK_CUR从当前位置开始 SEEK_END从尾开始(倒过来)

其实所有类型的文件最终都是二进制文件(转码),二进制文件需要专门的程序读写。
交互式终端使人们喜欢使用文本和计算机交谈(UNIX的shell提供读写文本的小程序,常用文本文件做数据存储和程序配置,windows常用二进制文件:PC开始时能力有限,DOS能力更有限,使用更接近底层的二进制文件做系统配置(注册表是一个超大的二进制文件)等等)。文本的优势是方便人读写且可跨平台,缺点是程序开销大;二进制文件可读差,不跨平台,大小端问题,int大小不一致,然而其效率很高,程序读写快。

配置文件一般是文本文件或二进制文件;
数据量稍大时都由数据库处理;
媒体文件只能是二进制的;
现实中程序通过第三方库来读写文件,很少直接读写二进制文件了。
以可移植性而言,二进制文件不具备可移植性,解决方案是使用typedef具有明确大小的类型或用文本文件。

文件操作例子

打开文件的代码样板

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>

int main() {
	/*
	* r		打开只读
	* r+	打开读写,从文件头开始
	* w		打开只写。不存在则新建,存在则清空
	* w+	打开写,并且可读。不存在则新建,存在则清空
	* a		打开追加。不存在则新建,存在则从文件尾开始
	* 另外,w和a后面可以加x:表示只新建,如果文件存在则不能打开
	*/
	FILE *fp = NULL;
	fp = fopen("fltest.in", "r"); //第一个参数是文件名,第二个参数是打开方式
	//判断文件是否正确打开了
	if ( fp ) {
		int num = 0;
		fscanf(fp, "%d", &num); //从文件读入
		printf("num = %d\n", num);
		//文件使用完毕记得关闭文件
		fclose(fp);
	}
	else {
		printf("打开文件失败\n");
	}
	
	return 0;
}

在这里插入图片描述
补充:fscanf遇到空格结束一次读操作(字符串读入需要注意位置),将fp设为stdin时可以实现scanf相同的效果。

文件写入(保存)与读取的例子 ——

#include <stdio.h>

#define STR_LEN 20
//const int STR_LEN = 20;

typedef struct _person {
	char name[STR_LEN];
	int gender;
	int age;
} Person;

void getList(Person arr[], int length);
int save(Person arr[], int length);
void read(FILE *fp, int index);

int main() {
	int number = 0;
	printf("输入人员信息记录数量:");
	scanf("%d", &number);
	Person person_Array[number];
	
	getList(person_Array, number);
	if ( save(person_Array, number) ) {
		printf("保存成功\n");
	}
	else {
		printf("保存失败\n");
	}
	
	//查看文件内容
	FILE *fp = NULL;
	fp = fopen("person.data", "r");
	if ( fp ) {
		fseek(fp, 0L, SEEK_END); //指针从文件末尾移动0,就是指针在文件末尾不动
		long size = ftell(fp); //获取当前所在位置-末尾,就是文件大小
		int number = size / sizeof(Person);
		int index = 0;
		printf("有%d个数据,你要看第几个:", number);
		scanf("%d", &index);
		read(fp, index-1);
		fclose(fp);
	}
	
	return 0;
}

void getList(Person arr[], int length) {
	char format[STR_LEN];
	sprintf(format, "%%%ds", STR_LEN-1); //"%19s"
		
	int i;
	for ( i = 0; i < length; i++ ) {
		printf("第%d个人员:\n", i+1);
		printf("\t姓名:");
		scanf(format, arr[i].name);
		printf("\t性别(0-女,1-男):");
		scanf("%d", &arr[i].gender);
		printf("\t年龄:");
		scanf("%d", &arr[i].age);
	}
}

int save(Person arr[], int length) {
	int ret = -1;
	FILE *fp = NULL;
	
	fp = fopen("person.data", "w");
	if ( fp ) {
		ret = fwrite(arr, sizeof(Person), length, fp);
		fclose(fp);
	}
	else {
		printf("打开文件失败\n");
	}
	
	return ret == length;
}

void read(FILE *fp, int index) {
	fseek(fp, index * sizeof(Person), SEEK_SET);
	Person person;
	if ( fread(&person, sizeof(Person), 1, fp) == 1) {
		printf("第%d个人员:", index+1);
		printf("\t姓名:%s\n", person.name);
		printf("\t性别:");
		switch ( person.gender ) {
			case 0: printf("女\n"); break;
			case 1: printf("男\n"); break;
		}
		printf("\t年龄:%d\n", person.age);
	}
}

在这里插入图片描述
fclose和fopen函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值