程序设计进阶——C语言(翁凯版)第七周

7.1 文件

7.1.1 格式化输入输出

格式化的输入输出

  • printf
  • %[flags][width][.prec][hIL]type
  • scanf
  • %[flag]type

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
printf和scanf都是有返回值的,printf返回读入的项目数,scanf返回输出的字符数,在要求严格的程序中,应该判断每次调用scanf或printf的返回值,从而了解程序运行中是否存在问题。

7.1.2 文件输入输出

文件输入输出

  • 用<和>做重定向;

FILE

  • FILE* fopen(const char *restrict path,const char *restrict mode);
  • int fclose(FILE *stream);
  • fscanf(FILE*,…);
  • fprintf(FILE*,…);

打开文件的标准代码

FILE* fp=fopen("file","r");
if(fp){
	fscanf(fp,...);
	fclose(fp);
}else{
	...
}

在这里插入图片描述

7.1.3 二进制文件

二进制文件

  • 其实所有的文件最终都是二进制的;
  • 文本文件无非是用最简单的方式可以读写的文件;
  • more、tail;
  • cat;
  • vi;
  • 而二进制文件是需要专门的程序来读写的文件;
  • 文本文件的输入输出是格式化,可能经过转码;

文本和二进制相比,文本优势在于方便人类读写并且跨平台;缺点是程序输入输出需要经过格式化,开销大;二进制缺点是人类读写困难,不跨平台,比如int的大小不一致,大小端的问题等;优点是程序读写快。

程序为什么要文件

  • 配置;
  • Unix用文本,Windows用注册表;
  • 数据;
  • 稍微有点量的数据都放数据库了;
  • 媒体;
  • 这个只能是二进制的;
  • 现实是,程序通过第三方库来读写文件,很少直接读写二进制文件了。

二进制读写

  • size_t fread(void *restrict ptr,size_t size,size_t nitems,FILE *restrict stream);
  • size_t fwrite(const void *restrict ptr,size_t size,size_t nitems,FILE *restrict stream);
  • 注意FILE指针是最后一个参数;
  • 返回的是成功读写的字节数;

在文件中定位

  • long ftell(FILE *stream);
  • int fseek(FILE *stream,long offset,int whence);
  • SEEK_SET:从头开始;
  • SEEK_CUR:从当前位置开始;
  • SEEK_END :从尾开始(倒过来);

可移植性

  • 这样的二进制文件不具有可移植性;
  • 在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出;
  • 解决方案之一是放弃使用int,而是typedef具有明确大小的类型;
  • 更好的方案是用文本。

7.2 位运算

7.2.1 按位运算

按位运算
C有这些按位运算的运算符

  • & 按位的与;
  • |按位的或;
  • ~按位取反;
  • ^按位的异或;
  • <<左移,>>右移;

按位与&
在这里插入图片描述
按位或|
在这里插入图片描述
按位取反~
在这里插入图片描述
逻辑运算VS按位运算
在这里插入图片描述
按位异或
在这里插入图片描述

7.2.2 移位运算

左移<<
在这里插入图片描述
右移>>
在这里插入图片描述
移位的位数不要用负数,这是没有定义的行为!

7.2.3 位运算例子

输出一个数的二进制

代码如下

#include <stdio.h>

int main(int argc,char const argv[])
{
	int number;
	number=12345;
	unsigned mask=1u<<31;
	for(;mask;mask>>=1){
		printf("%d",number&mask?1:0);
	}
	printf("\n");
	return 0;
}

输出

00000000000000000011000000111001

位运算在单片机编程中的应用
在这里插入图片描述

7.2.4 位段

  • 把一个int的若干位组合成一个结构;
struct{
		unsigned int leading:3;
		unsigned int FLAG1:1;
		unsigned int FLAG2:1;
		int trailing:11;
};

代码如下

#include <stdio.h>


void prtBin(unsigned int number);

struct U0{
	unsigned int leading:3;
	unsigned int FLAG1:1;
	unsigned int FLAG2:1;
	int trailing:27;
};

int main(int argc,char const argv[])
{
	struct U0 uu;
	uu.leading=2;
	uu.FLAG1=0;
	uu.FLAG2=1;
	uu.trailing=0;
	printf("sizeof(uu)=%lu\n",sizeof(uu));
	prtBin(*(int*)&uu);
	return 0;
}

void prtBin(unsigned int number)
{
	unsigned mask=1u<<31;
	for(;mask;mask>>=1){
		printf("%d",number&mask?1:0);
	}
	printf("\n");
}

输出

sizeof(uu)=4
00000000000000000000000000010010

位段

  • 可以直接用位段的成员名称来访问;
  • 比移位、与、或还方便;
  • 编译器会安排其中的位的排列,不具有可移植性;
  • 当所需的位超过一个int时会采用多个int;
  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值