C语言学习笔记(九)文件

一、文件

(1)格式化输入输出

  • printf
    • %[flags][width][.prec][hlL]type
Flag含义
-左对齐
+在前面放+或-
(space)正数留空
00填充
width或prec含义
number最小字符数
*下一个参数是字符数
.number小数点后位数
.*下一个参数是小数点后的位数
类型修饰含义
hh单个字节
hshort
llong
lllong long
Llong double
type用于
i或dint
uunsigned int
o八进制
x十六进制
X字母大写的十六进制
f或Ffloat,6
e或E指数
gfloat
Gfloat
a或A十六进制浮点
cchar
s字符串
p指针
n读入/写出的个数
#include<stdio.h>
int main(int argc,char const *argv[])
{
	//Flag测试
	printf("%9d\n",123);	//输出123
	printf("%-9d\n",123);	//输出123并且左对齐
	printf("%+9d\n",123);	//输出+123
	printf("%+-9d\n",123);	输出+123并且左对齐
	printf("%-09d\n",123);	输出123000000并且左对齐
	printf("%09d\n",123);	输出000000123
	//width和prec测试
	printf("%9.2f\n",123.0);	//输出123
	printf("%*d\n",6,123);	//输出   123
	//width和prec测试
	int num;
	printf("%d%n\n",123,&num);	//输出123
	printf("%d\n",num);	//输出3
  • 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指针
#include<stdio.h>
int main(int argc,char const *argv[])
{
	int num;
	scanf("%*d%d",&num);
	printf("%d\n",num);
	scanf("%*[^,]%[^,]",&num);//如果输入ashd,1234则num=1234
	return 0;
}

(2)printf和scanf的返回值

  • 读入的项目数
  • 输出的字符数
  • 在要求严格的程序中,应该判断每次调用printf或scanf的返回值,从而了解程序运行中是否存在问题

(3)文件输入输出

  • 用>和<做重定向
    • 用<指定用一个文件作为它的输入
    • 用>指定用一个文件作为它的输出
  • FILE
    • FILEfopen(const char restrict path,const char* restrict mode);
    • int fclose(FILE *stream);
    • fscanf(FILE*,…)
    • fprintf(FILE*,…)
  • fopen
mode含义
r打开只读
r+打开读写,从文件头开始
w打开只写。如果不存在则新建,如果存在则清空
w+打开读写。如果不存在则新建,如果存在则清空
a打开追加。如果不存在则新建,如果存在则从文件尾开始
…x只新建,如果文件已存在则不能打开
  • 打开文件的标准代码
	FILE* fp=fopen("file","r");
	if(fp){
		fscanf(fp,...);
		fclose(fp;
	}else{
		...
	}

(3)二进制文件

  • 二进制文件
    • 其实所有的文件最终都是二进制的
    • 文本文件无非是用最简单的方式可以读写的文件
      • more、tail
      • cat
      • vi
    • 而二进制文件是需要专门的程序来读写的文件
    • 文本文件的输入输出是格式化的,可能经过转码
  • 文本vs二进制
    • Unix喜欢用文本文件来做数据存储和程序配置
      • 交互式终端的出现使得人们喜欢用文本和计算机"talk"
      • Unix的shell提供了一些读写文本的小程序
        -Windoes喜欢用二进制文件
      • DOS是草根文化,并不继承和熟悉Unix文化
      • PC刚开始的时候能力有限,DOS的能力更有心啊,二进制更接近底层
    • 文本的优势是方便人类读写,而且跨平台
    • 文本的缺点是程序输入输出要经过格式化,开销大
    • 二进制的缺点是人类读写困难,而且不跨平台
      • int的大小不一致,大小端的问题…
        二进制的有点是程序读写快
  • 程序为什么要文件
    • 配置
      • Unix用文本,Windows用注册表
    • 数据
      • 稍微有点量的数据都放数据库了
    • 媒体
      • 这个只能是二进制的
    • 现实是,程序通过第三方库来读写文件很少直接读二进制文件了
  • 二进制读写
    • size_t fread(void *restrict ptr,size_t size,size_t nitems,IFLE *restrict stream);
    • size_t write(const void *restrict ptr,size_t size,size_t nitems,IFLE *restrict stream);
    • 注意FILE指针是最后一个参数
    • 返回的是成功读写的字节数
  • 为什么nitem?
    • 因为二进制文件的读写一般都是通过对一个结构体变量的操作来进行的
    • 于是nitem就是用来说明这次读写几个结构变量!
  • 在文件中定位
    • long ftell(FILE *stream);
    • int fseek(FILE *stream,long offset,int whence);
      • SEEK_SET:从头开始
      • SEEK_CUR:从当前位置开始
      • SEEK_END:从尾开始(倒过来)
  • 可移植性
    • 这样的二进制文件不具有可移植性
      • 在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出
    • 解决方案之一是放弃使用int,而是typedef具有明确大小的类型
    • 更好的方案是用文本
  • 一些代码
char format[STR_LEN];
sprintf(format."%%%ds",STR_LEN-1);	\\格式化字符串语句结束后format为%9d(假设STR_LEN为10)

二、*位运算

(1)按位运算

  • C有这些按位运算的运算符
  • & 按位的与
    • 按位与常用于两种应用:
      • 让某一位或某些位位0:x & 0xFE
      • 取一个数中的一段:x & 0xFF
  • | 按位的或
    • 按位或常用于两种应用:
      • 使得一位或几个位为1:x|0x01
      • 把两个数拼起来:0x:00FF | 0xFF00
  • ~ 按位取反
    • 把1位变0,0位变1
    • 想得到全部位为1的数:~0
    • 7的二进制是0111,x|7使得低三位为1,而
    • x&~7,就使得低3位为0
  • ^ 按位的异或
    • 如果两个位相等,那么结果为0;不相等。结果位1
    • 如果x和y相等,那么x^y的结果为0
    • 对一个变量用同一个值异或两次,等于什么也没做
  • << 左移
  • >> 右移

(2)移位运算

  • 左移<<
    • i<<j
    • i中所有的位向左移动j各位置,而右边填入0
    • 所有小于int的类型,位移以int的方式来做,结果是int
    • x<<=1 等价于x*=2
    • x<<=n 等价于x*= 2 n 2^{n} 2n
  • 右移>>
    • i>>j
    • i中所有的位向右移j位
    • 所有小于int的类型,位移以int的方式来做,结果是int
    • 对于unsigned的类型,左边填入0
    • 对于signed的类型,左边填入原来的最高位(保持符号不变)
    • x>>1 等价于 x/=2
    • x>>n 等价于 x/= 2 n 2^{n} 2n
//输出一个数的二进制
#include<stdio.h>
int mian(int argc,char const *argv[])
{
	int number;
	scanf("%d\n",&number);
	unsigned mask=1u<<31;
	for(;mask;mask>>1){
		printf("%d",number&mask? 1:0);
	}
	printf("\n");
	return 0;

(3) 位段

  • 把一个int的若干位组合成一个结构
	struct {
		unsigned int leading : 3;
		unsigned int FLAG1: 1;
		unsigned int FLAG2: 1;
		int trailing:11;
	};
  • 可以直接用位段的成员名称来访问
    • 比移位、与、或还方便
  • 编译器会安排其中的位的排列,不具有可以执行
  • 当所需的位超过一个int时会采用多个int
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值