C语言格式控制符 和 scanf
C语言格式控制符 和 scanf

格式控制符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
%a  浮点数、十六进制数字和p-记数法(c99)
%A 浮点数、十六进制数字和p-记法(c99)
%c    一个字符 
%d    有符号十进制整数 ------------------------------
%e    浮点数、e-记数法
%E    浮点数、E-记数法
%f    浮点数、十进制记数法(***隐含输出6位小数***)  ---------------------
%g    根据数值不同自动选择%f或%e.
%G    根据数值不同自动选择%f或%e.
%i 有符号十进制数(与%d相同)
%o    无符号八进制整数-------------
%p    指针    
%s    字符串 ---------------
%u    无符号十进制整数
%x    使用十六进制数字0f的无符号十六进制整数 -----------
%X    使用十六进制数字0f的无符号十六进制整数
%%    打印一个百分号

###注意
float,单精度浮点型,对应 %f
double,双精度浮点型,对应 %lf ---这里是英文字母L的小写

###常用
%c    一个字符 
%d    有符号十进制整数
%f    浮点数、十进制记数法
%lf    双精度浮点数、十进制记数法
%s    字符串

###扩展
%md:m为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出( 常见 %02d )
%ms:输出的字符串占m列,如字符串本身长度大于m,则突破获m的限制,将字符串全部输出。若串长小于m,则左补空格。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
printf("整数: %d", 90);
printf("浮点数: %.2f", 100.2);

// 整型宽度
int foo = 1;
printf("%03d", foo); // 输出 001

// 单精度和双精度
double bar; // 双精度
scanf("%lf", &bar); // 这里必须用 lf,否则出现未知的错误数
printf("bar当前值为 %lf \n", bar);

float foo; // 单精度
scanf("%f", &foo);
printf("foo当前值为 %f \n", foo);

// 字符串%s
printf("%5s", "abc"); // 长小于5,左补空格

修饰符

修饰符 意义
l 用于长整型和双精度实型数据,可加在格式字符 d、o、x、u、f 前面。
m (正整数) 数据最小宽度
n (正整数) 对于实数,表示输出n位小数;
对于字符串,表示截取的字符个数。
- 输出的数字或字符在域内向左靠,右边填空格
# 当整数以八进制或十六进制形式输出时,输出前缀。可加在格式字符o、x前面。
1
2
3
4
// %m.nf 举例
double foo = 123.09;
// 结果 foo = 123.090
printf ("foo = %2.3lf", foo);

指数e

  1. e/E之前必须有数字
  2. 指数(E之后的数)必须为整数,正负均可
  3. e 用在浮点数上,整型没有e
1
2
printf("%.2f\n", 3e2); // 3*(10*10) 输出 300.00
// printf("%d\n", 3e2); // 这个是错误,要用浮点数 %f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 判断2个浮点数差是否是 0,  
// fabs 取绝对值
a = 0.100003;
c = 0.100002;
disc = a - c;
if (fabs(disc) <= 1e-6) {
printf("--Yes");
}else{
printf("--No");
}
// 因为实数表示和计算存在微小误差,无法精确表达,
// 因此实数相等比较用差值的绝对值的精度来判断。 具体就是:f1和f2是两个浮点数,
// precision 是我们自己设置的精度,比如1e-6。
// 则可以用 fabs(f1-f2)<=precision 来判断f1和f2是否相等。
// 例如:该题就用if(fabs(disc)<=1e-6) 替换if(disc==0)

// demo2, 二元一次方程根的个数
float a, b, c, disc;
scanf("%f,%f,%f", &a, &b, &c);
disc = b * b - 4 * a * c;

if (fabs(disc) <= 1e-6) { // 这里设置精度为 1e-6
printf("有两个相等的实根\n");
} else {
if (disc > 0)
printf("有两个不等的实根\n");
else {
printf("无实根\n");
}
}

浮点数范围

一般float型只能精确到小数后六位(即1e-6),float的精度误差在1e-6;double精度误差在1e-15

运算符

类型转化

  1. 两个运算量类型一致时,与两个运算量的类型一致。
  2. 两个运算量类型不一致时,表达式的类型与其中较高类型运算量的类型一致(较低类型运算量先被自动转换为高类型再运算)
1
2
3
4
#低类型转换为高类型:
char → int → float → double

特殊:所有浮点数必然都转换为 double 再运算(即使两个float型量的运算也都先转换为 double

优先级最高 逻辑非! ++ --

三目运算符: 优先级倒数第三, “从右到左”的结合性

复合的赋值运算符与赋值运算符(=)相同:优先级倒数第二, “从右到左”的结合性

逗号运算符优先级最低(倒数第一),结合顺序为自左至右。

其他
1
2
3
//  字符串运算
char foo ='A';
printf("%c", foo + 1); // 输出B

三目运算符

1
2
3
4
5
6
7
a > b ? a : c > d ? c : d 这个式子应该理解为如下:
a > b ? a : (c > d ? c : d) 从右侧至左

int i = 5, j = 4, k = 6;
int f;
f = (i < j && j < k) ? i : (j < k) ? j : k;
printf("%d", f); // 输出 4

逗号运算符

1
2
3
4
5
6
表达式1 , 表达式2 , 表达式3

#demo
1+1, 2+3 表达式的值为5
x=5, 5+2, x-3 表达式的值为2(x被赋值为5,必须依次计算)
x= (a=1, b=3, ++b, a+b); 此为赋值语句,x被赋值为 5
  1. 依次从左到右分别计算各个表达式的值
  2. 整个“逗号表达式”的值为其中最后一个表达式(上例为表达式 3)的值。

逗号运算符优先级最低(倒数第一),结合顺序为自左至右。

1
2
3
4
5
6
如有int a=2, b=4, c=6, x, y;
1) 若执行 y=( (x=a+b),(b+c) ); 后,x值为 6 ,y值为 10 ;
y=( (x=6),10); ---> y=(6,10); ---> y=10

2) 若执行 y=(x=a+b), (b+c); 后,x值为 6 ,y值为 6 。
y=(x=6),10; ---> y=6, 10; ---> 6,10; ---> 10(被丢弃)

逻辑运算符

逻辑运算符 &&,||,!

运算符 描述 实例
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真 (1&&1) 为真
\ \ 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真 (0\ \ 1) 为真
! 称为逻辑非运算符。用来逆转操作数的逻辑状态。
如果条件为真则逻辑非运算符将使其为假(简单理解: 取反)
(!0) 为真
(!1) 为假

逻辑与 && 和逻辑 ||短路操作

菜鸟教程—逻辑运算符

位运算符

位运算符 &, |,^,~,>>,<<, 这几个都是按照二进制进行运行

按位与 &, 离散数学中合取
按位或 |, 离散数学中析取
取反 ~, 离散数学中非

位运算真值表

p q p&q p\ q
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 1

异或运算符 ^ , 实现2数交换

1
2
3
4
5
6
int a = 1, b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;

printf("%d,%d", a, b);

菜鸟教程—位运算符

类型说明符

类型说明符为int、long、unsigned、float、double 、char等

字符型常量
用英文单引号括起来,只保存一个字符’a’、’b’ 、’*’ ,还有转义字符 ‘\n’ 、’\t’。

字符串常量
用英文的双引号引起来 可以保存多个字符:”abc”。

输入输出

  1. putchar() 函数——单字符输出
  2. getchar() 函数——单字符输入
  3. 格式输出函数 printf()
  4. 格式输入函数 scanf()
1
2
3
4
5
6
7
8
9
10
11
12
// 输出2个字符
char c1, c2 ,c3;
c1 = getchar();
c2 = getchar();
putchar(c1);
putchar(c2);

// 输出字母的大写对应的小写
char c1, c2;
c1 = getchar();
c2 = c1 + 32;
putchar(c2);

格式输出函数 printf

1
2
3
4
// 格式控制符对应从左到右的表达式  左-->右
int foo = 2;
// 结果为2,7
printf("%d,%d", foo, foo + 5, foo + 2);
1
2
3
4
5
6
7
8
char foo = 'A';
//输出结果:foo = A //(以字符形式输出)
printf ("foo = %c \n\r", foo);


char bar = 'A';
//输出结果:bar = 65 // (以'A'字符的ASCII码形式输出)
printf ("bar = %d", bar);

格式输入函数 scanf

1
2
3
4
5
#使用规则
scanf("格式控制字符串", 变量1的地址, 变量2的地址, 变量3的地址, ...);

#格式控制符一般形式
[=%[*][width][modifiers]type=]
  • 在输入数据时,默认遇空格或按“回车”表示该数据结束,但是格式输入控制中无需加\n。

  • 输入数据时不能规定小数位数

  • 要是有逗号要原样输入

    1
    2
    int a, b;
    scanf("%d,%d",&a,&b); // %d,%d 之间的逗号要原样输入
    1
    2
    3
    4
    // width 截取
    char foo[5]; // 定义字符串
    scanf("%3c",&foo); // 截取width为3
    printf ("输入的值为%s", foo);
注意事项
  1. 如果相邻两个格式控制符之间,不指定数据分隔符(如逗号、冒号等),则相应的两个输入数据之间至少用一个空格分隔,或者用Tab键分隔,或者输入一个数据后,按回车,然后再输入下一个数据
  2. 格式控制字符串中出现的常规字符(包括转义字符),务必原样输入
  3. 当格式控制字符串中指定了输入数据的域宽width时,将读取输入数据中相应的width位,但按需要的位数赋给相应的变量,多余的部分被舍去
  4. 当格式控制字符串中含有抑制符*,表示本输入项对应的数据读入后,不赋给相应的变量(该变量由下一个格式指示符输入)
  5. 使用格式控制符%c输入单个字符时,空格和转义字符均作为有效字符被输入
  6. 输入数据时,遇到以下情况,系统被认为 该数据结束
    1. 遇到空格,或者回车键,或者Tab
    2. 遇到输入域宽度结束,例如%3d,只取3列
    3. 遇到非法输入,毕方说,在输入数值数据时,遇到字母等非数值符号
  7. 当一次scanf调用需要输入多个数据项时,如果前面数据的输入遇到非法字符,并且输入的非法字符不是格式控制字符串中的常规字符,那么,这种 非法输入将影响后面的输入,导致数据输入失败
  8. 个人理解—scanf里面的格式控制符要和定义常量(变量)保持一致
1
2
3
4
5
6
7
8
// 测试数据,依次输入 A B C D (记得加空格),没有使用fflush(stdin),第四个字母一直输入不进去
// ---注意看规则1和规则6
char ch1, ch2, ch3, ch4;
scanf("%c%c%c", &ch1, &ch2, &ch3);
fflush(stdin); // 刷新缓冲,否则下面的不能输入和获取
scanf("%c", &ch4);

printf("ch1=%d, ch2=%d, ch3=%d, ch4=%d, \n", ch1, ch2, ch3, ch4);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// scanf里面的格式控制符要和定义常量(变量)保持一致

// 01双精度
double bar; // 双精度
scanf("%lf", &bar); // 这里必须用 lf ,否则出现未知的错误数
printf("bar当前值为 %lf \n", bar);

// 02单精度
float foo; // 单精度
scanf("%f", &foo);
printf("foo当前值为 %f \n", foo);

// 03整型
int fei;
scanf("%d", &fei);
printf("fei当前值为 %d \n", fei);

底部

没有了