格式化输入输出
输入 - printf
printf("%[flags][width][.prec][hlL]type...",参数表...);
返回值
输出的字符数
flag
Flag | 含义 |
---|---|
- | 左对齐 |
+ | 给一个正数强制加一个+号 |
(space) | 正数留空 |
0 | 左边补零,不能和左对齐同时使用 |
width和prec
width | 含义 |
---|---|
number | 最小字符数(整个输出,包括小数点和小数点后的数) |
* | 下一个参数是字符数 |
prec | 含义 |
.number | 小数点后的位数 |
.* | 下一个参数是小数点后的位数 |
/* 关于"*" */
printf("%*d",6,10); // 6会被填到*的位置,然后按%6d的格式print 10
修饰类型
修饰类型 | 含义 |
---|---|
hh | 单个字节 |
h | short |
l | long |
ll | long long |
L | long double |
type
type | 用于 | type | 用于 |
---|---|---|---|
i 或 d | int | g | float |
u | unsigned int | G | float |
o | 八进制 | a 或 A | 16进制浮点数 |
x | 十六进制 | c | char |
X | 字母大写的十六进制 | s | string |
f 或 F | float.6 | P | 指针 |
e 或 E | 指数 | n | 读入/写出的个数 |
关于 %n
的一个例子:
int num = 0;
printf("12345%s%n\n","hello",&num);
printf("%d\n",num);
输出结果:
12345hello
10
输出 - scanf
scanf("%[flag]type...",参数表...);
返回值
读入的项目数(不是读入的字符数)
flag
flag | 含义 | flag | 含义 |
---|---|---|---|
* | 跳过 | l | long, double |
数字 | 最大字符数 | ll | long long |
hh | char | L | long double |
h | short |
关于 *
的一个例子:
int num = 0;
scanf("%*d%d",&num);
printf("%d\n",num);
输入:
123 456
输出:
456
type
type | 用于 | type | 用于 |
---|---|---|---|
d | int | s | 字符串(单词) |
i | 正数,可能为非十进制 | [...] | 所允许的字符 |
u | unsigned int | p | 指针 |
o | 八进制 | ||
x | 十六进制 | ||
a,e,f,g | float | ||
c | char |
关于 i
的一个例子
int num = 0;
for(int i = 0; i < 3; i++){
scanf("%i",&num);
printf("%d\n",num);
}
输入:
12
012
0x12
输出:
12
10
18
文件输入输出
重定向方式
使用>和<做输出输入重定向.假设有这样一个程序(可执行程序名:test):
#include<stdio.h>
int main(void){
int num = 0;
scanf("%d",&num);
int cnt = 1;
while(num/10 != 0){
num /= 10;
cnt++;
}
printf("这个数有%d位\n",cnt);
return 0;
}
如果我们想将输出结果存在result.txt文件中,可以:
./test > result.txt
123
result.txt:
这个数有3位
如果我们想从一个input.txt文件输入,可以:
input.txt:
123
./test < input.txt
这个数有3位
FILE
在stdio.h
中,声明了一种类型FILE(一种结构,里面包含了打开文件的一些信息).
可以使用fopen()
来打开一个文件.他的用法如下:
FILE *xxx = fopen("文件名","打开方式");
打开方式 | 含义 |
---|---|
r | 只读,从文件头开始 |
r+ | 读且可写,从文件头开始 |
w | 只写,不存在则新建,存在则清空原有内容 |
w+ | 写且可读,不存在则新建,存在则清空原有内容 |
a | 追加,不存在则新建,存在则在文件尾追加 |
x | 只新建,如果文件存在则不能打开(与w和w+配合使用可以保护文件不被破坏) |
打开文件后可以使用fscanf()
来做输入.
fscanf(文件指针,"输入格式",参数表);
使用fprintf()
来做输出.
fprintf(文件指针,"输出格式",参数表);
使用完文件后,记得用fclose()
来关闭文件.
fclose(文件指针);
下面是一个示例程序:
#include<stdio.h>
typedef struct _studentInfo{
char name[20];
char sex[3];
int age;
} stuInfo;
int main(void){
FILE *db = fopen("studentInfo.db","w");
int n = 0;
scanf("%d",&n);
stuInfo list[n];
int cnt = 0;
while(n--){
printf("请输入第%d个学生的信息:\n",cnt+1);
printf("%10s\n","姓名:");
scanf("%s",list[cnt].name);
getchar();
printf("%10s\n","性别:");
scanf("%s",list[cnt].sex);
printf("%10s\n","年龄:");
scanf("%d",&list[cnt].age);
fprintf(db,"姓名:%s|性别:%s|年龄:%d\n",\
list[cnt].name,list[cnt].sex,list[cnt].age);
cnt++;
}
fclose(db);
return 0;
}
输入:
2
请输入第1个学生的信息:
姓名:
orzmiku
性别:
+
年龄:
18
请输入第2个学生的信息:
姓名:
dzoer
性别:
+
年龄:
15
输出 (studentInfo.db) :
orzmiku@MikuNet(~/Study/文件)$ cat studentInfo.db
姓名:orzmiku|性别:+|年龄:18
姓名:dzoer|性别:+|年龄:15
二进制文件
可以使用fread和fwrite对二进制文件进行操作.
fwrite 和 fread函数的用法小结 | 菜鸟教程 (runoob.com)
位运算
位运算符 | 含义 |
---|---|
& | 与 |
| | 或 |
~ | 非 |
^ | 异或 |
<< | 左移 |
>> | 右移 |
按位运算
按位与 &
01011010 & 11110101 = 01010000
常用应用:
-
让某一位或者某些位为0
- 11111110 & xxxxxxxx , 让前七位原封不动,最后一位无论是1还是0都变成0
-
取一个数中的一段
- 00011000 & xxxxxxxx, 只要中间两个数,其余数变成0
按位或 |
01011010 & 01010101 = 01011111
常用应用:
- 让某一位或者某些位为0
- 00000001 | xxxxxxxx , 让前七位原封不动,最后一位无论是1还是0都变成1
- 将两个数拼起来
- 如: 11000011 | 00111100 = 11111111
按位取反 ~
~ 00001111 = 11110000
按位异或 ^
10101100 ^ 01011100 = 00001111
-
如果两个相等的数进行异或运算,结果为0
-
对于同一值异或两次,原数值不变
按位异或有一个应用,可以不创建第三个变量来交换两个变量的值:
int a = 1;
int b = 2;
// a => 1; b => 2;
a = a^b;
b = a^b;
a = a^b;
// a -> 2; b => 1;
位移运算
左移 <<
- i << j
- i中所有的位向左移动j位,右边填0
- 所有小于int的类型,位移以int的方式来做
x <<= 1
<==>x *= 2
x <<= n
<==>x *= pow(2,n)
- 上面这两点可以用二进制的按权展开来理解
右移 >>
- i >> j
- i中所有的位向右移动j位
- 所有小于int的类型,位移以int的方式来做
- 对于unsigned类型,左边填0
- 对于sign类型,由于最左边的那一位是符号位,因此符号位不变
x >>= 1
<==>x *= 1/2
x >>= n
<==>x *= 1/pow(2,n)
- 上面这两点可以用二进制的按权展开来理解