一、文件
(1)格式化输入输出
- printf
- %[flags][width][.prec][hlL]type
Flag | 含义 |
---|
- | 左对齐 |
+ | 在前面放+或- |
(space) | 正数留空 |
0 | 0填充 |
width或prec | 含义 |
---|
number | 最小字符数 |
* | 下一个参数是字符数 |
.number | 小数点后位数 |
.* | 下一个参数是小数点后的位数 |
类型修饰 | 含义 |
---|
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 | float |
G | float |
a或A | 十六进制浮点 |
c | char |
s | 字符串 |
p | 指针 |
n | 读入/写出的个数 |
#include<stdio.h>
int main(int argc,char const *argv[])
{
printf("%9d\n",123);
printf("%-9d\n",123);
printf("%+9d\n",123);
printf("%+-9d\n",123);
printf("%-09d\n",123);
printf("%09d\n",123);
printf("%9.2f\n",123.0);
printf("%*d\n",6,123);
int num;
printf("%d%n\n",123,&num);
printf("%d\n",num);
flag | 含义 |
---|
* | 跳过 |
数字 | 最大字符数 |
hh | char |
h | short |
l | long,double |
ll | long long |
L | long double |
type | 用于 |
---|
d | int |
i | 整数,可能为十六进制或八进制 |
u | unsigned int |
o | 八进制 |
x | 十六进制 |
a,e,f,g | float |
c | char |
s | 字符串 |
[…] | 所允许的字符 |
p | 指针 |
#include<stdio.h>
int main(int argc,char const *argv[])
{
int num;
scanf("%*d%d",&num);
printf("%d\n",num);
scanf("%*[^,]%[^,]",&num);
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)二进制文件
- 二进制文件
- 其实所有的文件最终都是二进制的
- 文本文件无非是用最简单的方式可以读写的文件
- 而二进制文件是需要专门的程序来读写的文件
- 文本文件的输入输出是格式化的,可能经过转码
- 文本vs二进制
- Unix喜欢用文本文件来做数据存储和程序配置
- 交互式终端的出现使得人们喜欢用文本和计算机"talk"
- Unix的shell提供了一些读写文本的小程序
-Windoes喜欢用二进制文件 - DOS是草根文化,并不继承和熟悉Unix文化
- PC刚开始的时候能力有限,DOS的能力更有心啊,二进制更接近底层
- 文本的优势是方便人类读写,而且跨平台
- 文本的缺点是程序输入输出要经过格式化,开销大
- 二进制的缺点是人类读写困难,而且不跨平台
- int的大小不一致,大小端的问题…
二进制的有点是程序读写快
- 程序为什么要文件
- 配置
- 数据
- 媒体
- 现实是,程序通过第三方库来读写文件很少直接读二进制文件了
- 二进制读写
- 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) 位段
struct {
unsigned int leading : 3;
unsigned int FLAG1: 1;
unsigned int FLAG2: 1;
int trailing:11;
};
- 可以直接用位段的成员名称来访问
- 编译器会安排其中的位的排列,不具有可以执行
- 当所需的位超过一个int时会采用多个int