c语言10怎么打开文件,Lecture 10 C语言文件操作

博主不定期更新【保研/推免、C/C++、5G移动通信、Linux、生活随笔】系列文章,喜欢的朋友【点赞+关注】支持一下吧!

Lecture 10 文件

1. 文件

1.1 格式化输入输出

printf

%[flags][width][.prec][hlL]typeFlag

含义-

左对齐

+

在前面放+或-

(space)

整数留空

0

0填充width或prec

含义number

最小字符数(输出宽度)

*

下一个参数是字符数

.number

小数点后的位数

.*

下一个参数是小数点后的位数类型修饰

含义hh

单个字节(char)

h

short

l

long

ll

long long

L

long doubletype

用于

type

用于i或d

int

g

float

u

unsignde int

G

float

o

八进制

a或A

十六进制浮点

x

十六进制

c

char

X

字母大写的十六进制

s

字符串

f或F

float,6

p

指针

e或E

指数

n

到目前为止读入/写出的个数#include

int main()

{

int num;

printf("%d%n\n", 123456, &num);

printf("%d\n", num);

return 0;

}

运行结果:

123456

6

注:因为会造成格式化字符串漏洞的原因,目前Windows已弃用%n,因此在本地IDE上运行可能无法得到正确结果

scanf

%[flag]typeflag

含义

flag

含义*

跳过

l

long, double

数字

最大字符数

ll

long long

hh

char

L

long double

h

shorttype

含义

type

含义d

int

s

字符串

i

整数,可能十六进制或八进制

[…(多种可能)]

所允许的字符

u

unsigned int

p

指针

o

八进制

x

十六进制

a,e,f,g

float

c

charscanf和printf的返回值

读入的项目数

输出的字符数

在要求严格的程序中,应该判断每次调用printf或scanf的返回值,从而了解程序运行中是否存在问题

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

{

printf("无法打开文件");

...

}

fopen

rrr

打开只读r+

打开读写,从文件头开始

w

打开只写。如果不存在则新建,如果存在则清空

w+

打开读写。如果不存在则新建,如果存在则清空

a

打开追加。如果不存在则新建,如果存在则从文件尾开始

…x

(一般为wx/ax)只新建,如果文件已存在则不能打开

1.3 二进制文件

其实所有的文件最终都是二进制的

文本文件无非是用最简单的方式可以读写的文件(unix系统)

more、tail

cat

vi

而二进制文件是需要专门的程序来读写的文件

文本文件的输入输出是格式化,可能经过转码

文本 VS 二进制

Unix喜欢用文本文件来做数据存储和程序配置,Windows喜欢用二进制文件

文本的优势是方便人类读写,而且跨平台

文本的缺点是程序输入输出要经过格式化,开销大

二进制的优点是程序读写快

二进制的缺点是人类读写困难,而且不跨平台

int的大小不一致,大小端的问题…

程序为什么要文件

配置

Unix用文本,Window用注册表

数据

稍微有点量的数据都放数据库了

媒体

这个只能是二进制的

现实是,程序通过第三方库来读写文件,很少直接读写二进制文件了

二进制读写

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指针是最后一个参数

返回的是成功读写的字节数

为什么有nitem?

因为二进制文件的读写一般都是通过对一个结构变量的操作来进行的

于是nitem就是用来说明这次读写几个结构变量

在文件中定位

long ftell(FILE *stream);

int fseek(FILE *stream, long offset, int whence);

SEEK_SET:从头开始

SEEK_CUR:从当前位置开始

SEEK_END:从尾开始(倒过来)

可移植性

这样的二进制文件不具有可移植性(int不同)

解决方案之一是放弃使用int,而是typedef具有明确大小的类型

更好的方案是用文本

2. 位运算

2.1 按位运算

按位运算的运算符:

& 按位的与

让某一位或某些位为0:x & 0xFE

0xFE->1111 1110,其作用为让x的最低位变为0

取一个数中的一段:x & 0xFF

0xFF->0000 0000 0000 0000 0000 0000 1111 1111

取x的最后一个字节,前面三个字节置0(这里假设x是32位int型)

| 按位的或

使得一位或几个位为1:x | 0x01

把两个数拼起来:0x00FF | 0xFF00

~ 按位取反

把1位变0,0位变1

想得到全部位为1的数:~0

7=0111;x | 7使得低3位为1,而x & ~7使得低3位为0

^ 按位的异或

两个位相等,结果为0;不相等,结果为1

对一个变量用同一个值异或两次,等于什么也没做

x ^ y ^ y -> x

逻辑运算 VS 按位运算

对于逻辑运算,它只看到两个值:0和1

可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算5 & 4 -> 4 而 5 && 4 -> 1 & 1 -> 1

5 | 4 -> 5 而 5 || 4 -> 1 | 1 -> 1

~4 -> 3 而 !4 -> !1 -> 0

2.2 移位运算

<< 左移

i << j 表示i中所有的位向左移动j个位置,而右边填入0

所有小于int的类型,移位以int的方式来做,结果是int

x <<= 1 ⇔\Leftrightarrow⇔ x *= 2

x <<= n ⇔\Leftrightarrow⇔ x *= 2n2^n2n

>> 右移

i >> j 表示i中所有的位向右移j位

所有小于int的类型,移位以int的方式来做,结果是int

对于unsigned类型,左边填入0;对于signed类型,左边填入原来的最高位(保持符号不变)

x >>= 1 ⇔\Leftrightarrow⇔ x /= 2

x >>= n ⇔\Leftrightarrow⇔ x /= 2n2^n2n

移位的位数不要用负数,这是没有定义的行为

附:有符号十六进制数转换为十进制数:

首先给出原码、反码、补码转换:

原码 ⟹\Longrightarrow⟹ 按位取反(除符号位) ⟹\Longrightarrow⟹ 反码 ⟹\Longrightarrow⟹ 加1 ⟹\Longrightarrow⟹ 补码

补码的补码是原码

实例:(signed) int 0x82000000

首先写成二进制:1000 0010 0000 0000 0000 0000 0000 0000

按位取反(除符号位):1111 1101 1111 1111 1111 1111 1111 1111

加1:1111 1110 0000 0000 0000 0000 0000 0000

计算:−(7×167+14×166)=−2113929216-(7 \times 16^7+14 \times 16^6)=-2113929216−(7×167+14×166)=−2113929216

而 unsigned int 0x82000000

转换为十进制为:8×167+2×166=21810380808 \times 16^7+2 \times 16^6=21810380808×167+2×166=2181038080

2.3 位运算例子

输出一个数的二进制

#include

int main()

{

int number;

scanf("%d", &number);

unsigned mask = 1u<<31;

for ( ; mask; mask >>=1 )

{

printf("%d", number & mask? 1:0);//逐一判断number的每个位上是0还是1

}

printf("\n");

return 0;

}

2.4 位段

把一个int的若干位组合成一个结构

struct {

unsigned int leading : 3; //数字表示所占比特数

unsigned int FLAG1: 1;

unsigned int FLAG2: 1;

int trailing: 11;

}

可以直接用位段的成员名称来访问

比移位、与、或还方便

编译器会安排其中的位的排列,不具有可移植性

当所需的位超过一个int时会采用多个int

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值