C语言(十四)文件

本文详细探讨了C语言中的printf和scanf函数,包括占位符%d的使用、格式标志、宽度和精度等细节。此外,还介绍了文件输入输出操作,如重定向、使用fopen、fscanf和fprintf进行文件读写,并讲解了二进制文件的处理方法,如fwrite和fread函数。最后讨论了二进制文件在不同平台间的可移植性问题及其解决方案。
摘要由CSDN通过智能技术生成

13.1.1 格式化输入输出

从第一天学c语言就接触到了printf和scanf.下面彻底研究下占位符%d有多少细节。
printf: %[flags][width][.prec][hIL]type
flag:标志,有以下几种

flag含义
-左对齐(和width一起用)
+输出前面带正负号
(space)正数留空
0空格用0填充(不能和-同时使用)

width(宽度)或prec

width或prec含义
number最小字符数(包括小数点)
*下一个读入的参数是字符数
.number小数点后面的位数
.*下一个参数是小数点后的位数

hIL:类型修饰符

类型修饰含义
hh单个字节
hshort
llong
lllong long
Llong double

type:类型

type用于
i或dint
uunsigned int
o八进制
x十六进制
X大写字母的十六进制
f或Ffloat, 6
e或E指数
gfloat
Gfloat
a或A十六进制浮点
cchar
s字符串
p指针
n读入/写出的个数

在这里插入图片描述
%n是当操作做到这里时,已经输出了多少个字符,并且填到指针所指的变量里。
scanf: %[flag]type

flag含义
*跳过
数字最大字符数
hhchar
hshort
llong, double
lllong long
Llong double
type用于
dint
i整数,可能是十六进制或八进制
uunsigned int
o八进制
x十六进制
a, e, f, gfloat
cchar
s字符串(单词)
[…]所允许的字符
p指针

%i会根据输入(如0x12、012)来判断是十六进制还是八进制还是十进制。
[…]举例
GPS中会读到一串字符,用逗号分隔
在这里插入图片描述
占位符%[^,]表示读入逗号前的所有字符
printf和scanf是有返回值的。scanf是返回几个item,即这次读入了几个变量;而printf则是这次输出了多少个字符。因此当我们面对要求严格的程序,比如长期运行的大程序,就需要判断每次调用scanf和printf的返回值来了解程序运行中是否会存在问题。

13.1.2 文件输入输出

我们之前运行程序的时候在命令行里输入./test(test是文件名)即可。
对文件做输入输出:./test > 12.out,然后再输入scanf标准输入的内容,但是程序没有printf标准输出了。但是打开12.out文件(输入more 12.out),会输出标准输入和标准输出。
同样,当我们输入 cat >12.in ,输入标准输入,然后再Ctrl D结束程序,再查看12.in文件(输入more 12.in)会输出标准输入。
然后运行test文件的时候这样写:./test < 12.in,12.in的内容会输入给./test,然后我们会得到其输出。
(当然还可以./test < 12.in > 12.out,输入是文件,输出也是文件。12.out里也有我们所期望的结果。)
以上是程序运行中的重定向。我们用<来指定一个文件的输入,用>来指定输出到一个文件中。
然而这并不是一般的文件输入输出方式,一般的方式需要做一个FILE,在stdlib.h中已经声明好过。
在这里插入图片描述
用fopen打开文件打开后用fscanf和fprintf函数来读写。

FILE* fp=fopen("file","r");//file是文件名,r表示读
if(fp){//如果没打开,会返回NULL
	fscanf(fp,...);//读文件。省略号的东西和正常的scanf一样了。后面还可以printf
	fclose(fp);
}else{}//无法打开的反馈。如:输出 无法打开文件

直接./test运行即可,会打开12.in然后正常输出。
如果删掉12.in(rm 12.in)就无法打开文件。
fopen第一个参数是文件名的字符串,第二个参数字符串用途如下:

r打开只读
r+打开读写,从文件头开始读/写
w打开只写,如果不存在则新建,如果存在则清空
w+打开读写,如果不存在则新建,如果存在则清空
a打开追加,如果不存在则新建,如果存在不清空,从文件尾开始
在结尾加x只新建,如果文件已存在则不能打开

13.1.3 二进制文件

所有文件最终都是二进制的。文本文件,只是用一种简单的方式可以进行读写的文件。如more, tail 可以打开文件,cat 打开文件或定向到其他文件,vi 做完整的编辑,etc。但是二进制没这么简单。
选择文本还是二进制?
UNIX(和windows一样都是操作系统。)喜欢用文本文件储存数据、配置程序。交互式终端的出现(类似windows的cmd窗口)使得人们喜欢用文本和计算机“交流”。因此,UNIX的shell就提供了一些读写文本的小程序。
windows(更准确要说DOS),个人计算机的制作者并不继承、熟悉UNIX文化(宛如在围墙之外,不熟悉围墙内)全凭自己的理解做出草根文化的DOS,更喜欢用二进制文件。
PC和DOS刚开始的时候能力有限,二进制更加接近底层。
文本、二进制各有优劣。
文本方便人类读写,而且跨平台;缺点是程序的输入输出要经过格式化,开销大。
二进制的缺点是人类读写困难而且不跨平台;(如不同计算机int大小不一致)优点是读写快。
在这里,我们要回顾下为什么程序要使用文件。

  1. 有配置(比如窗口大小、字体颜色)UNIX用文本文件就能编辑,Windows是用一个大文件:注册表编辑。
  2. 数据:保存数据,如学生成绩。稍微大一些的数据都放数据库那了。
  3. 媒体:如图片音频,这些不能是文本文件,只能是二进制文件。
    其实现在程序通过第三方库来读写文件,很少直接读写二进制文件了。
    对二进制的读写
    在这里插入图片描述
    第一个参数是指针,要读写的内存;第二个参数是那块内存(一个结构)的大小;第三个参数是有几个这样的内存,第四个参数是文件指针。返回成功读写的字节数。
    因为二进制文件的读写一半是通过对一个结构变量的操作来进行的,所以nitem就是用来说明这次读写了几个结构变量。
    这里老师做了一个非常有意思的东西,建议去看看(我懒了)
    fwrite可以把数据以二进制形式写到文件中,fread类似。
    定位:找出现在处在文件中的位置,或跳到指定位置。
long ftell(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
/*whence:SEEK_SET 从头开始
SEEK_CUR 从当前位置开始
SEEK_END 从末尾开始*/

如:fseek(fp, 0L, SEEK_END);当前位置就在结尾了。这时如果我们令long size=ftell(fp);得到的就是文件大小。
我们可以先这样获得文件大小,然后除以sizeof来得知内部储存了多少个数据;然后用户说我想看第几个数据,我们再利用fseek函数跳到那个位置,输出每一项。
这样的二进制文件不具备可移植性;即在int为32位的机器上写出的数据文件不能在int为64位的机器上正确读出。解决方案1是放弃int,使用typedef具有明确大小的类型;2是用文本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

灰海宽松

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

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

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

打赏作者

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

抵扣说明:

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

余额充值