该系列为本人的学习笔记,主要由本人整理书写而成。部分内容来自教材、视频课程等,不能保证完全原创性。
萌新的学习笔记,写错了恳请斧正。
# 算术操作符:+ - * / %
这些操作符左右两边都要有操作数,所以它们属于双目操作符
- 加法:
- 就正常加法
- 减法:
就正常减法
乘法:
就正常乘法
/ 除法:
- 如果两端都是整型,那么执行整数除法,余数约去。如 5/2 的结果为 2
- 如果两端有哪怕一个小数 (浮点), 那么结果就正常算,输出浮点数
% 取模:
- 两边只能是整型,输出除法的余数。如 5%2 的结果为 1
- 结果的正负号由前一个数决定。如 - 9%-5 的结果为 - 4
# 赋值操作符:= 与复合赋值符
在创建变量是给变量一个值叫初始化
之后给变量值就叫赋值
int a = 0; // 初始化 | |
a = 1; // 赋值 |
也可以连续赋值,按照从右向左的顺序,但不建议这么写
a = b = c + 1 | |
// 不建议这样写 |
# 复合赋值
有的时候会对变量进行自增自减:
a = 0; | |
a = a + 2; | |
a = a + 3; |
那么其实可以写成这样:
a = 0; | |
a += 2; | |
a += 3; |
类似的,有:+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=(后面几个后面再说)
# 单目操作符:++、--、+(正)、-(负)
单目操作符就是只有一个操作数的操作符
++ 和 -- 是一种自增的操作符,分为前置和后置两种
++ 就是自己加一的意思,-- 就是自己减一
++/-- 放在变量前面就是先自增 / 减,再参与该行代码的运算
++/-- 放在变量后面就是先参与该行代码的运算,再自增 / 减
int a = 1; | |
int b = ++a; | |
// 这时 a=2,b=2 |
a = 1; | |
b = a++; | |
// 这时 a=2,b=1 |
# 强制类型转换
可以用 (datatype) 来强制转换类型,比如:
int a = (int)114.514; | |
// 这里 114.514 是 double 型,被强制转换为整型 | |
// 这导致其失去小数点后面内容,被当成 114 |
# printf 和 scanf
# printf
printf 就是用来把字符打印到屏幕上的
print 是打印,f 是 format (格式)
所以要用格式化符号来指定输出格式,这些符号应包括在格式控制字符串中
(除非只要打印字符串)
// 注意格式化符号 | |
printf("%d阿巴阿巴%f歪比巴卜%lf", 1, 1.4, 5.14); |
括号里第一部分叫格式控制字符串
后面是输出字符参数表,与前面的字符串中的格式化符号按顺序对应填充
printf 在输出完之后不会换到下一行,想换行需要自行添加 \ n
# printf 格式化符号 (占位符)
下面列举占位符:
- % a: 十六进制浮点数,字母小写
- % A: 十六进制浮点数,字母大写
- % c: 字符
- % d: 十进制整数
- % e: 科学计数法,e 小写
- % E: 科学计数法,E 大写
- % i: 整数,老写法。用于 scanf 会将 0 打头的数字当 8 进制、0x 打头的当 16 进制,会转换为 10 进制。
- % f: 小数 / 浮点,包括 float 和 double
- % g:6 个有效数字的浮点数,整数部分超过六个或小于 0.0001 会自动转换成科学计数法,e 小写
- % G: 同上,但 E 大写
- % hd:10 进制 short
- % ho:8 进制 short
- % hx:16 进制 short
- %hu:unsigned short
- % ld:10 进制 long
- % lo:8 进制 long
- % lx:16 进制 long
- %lu:unsigned long
- % lld:10 进制 long long
- % llo:8 进制 long long
- % llx:16 进制 long long
- %llu:unsigned long long
- % Le: 科学计数法的 long double
- %Lf:long double
- % n: 已输出的字符串数量。这个占位符本身不输出,只把值存在特定变量中
- % o:8 进制整数
- % p: 指针
- % s: 字符串
- %u:unsigned
- % x:16 进制整数
- %zd:size_t
- %%: 输出正常的百分号
注意:
- 上述以 o、x 结尾的均为无符号数
- 以 x 结尾的十六进制中字母小写,若以 X 结尾则大写
占位符可以添加限定:
- 占位符的 % 后面加数字可以限定占位符输出的最小宽度
- 如 %[n].[m] d、%[n].[m] s、%[n].[m] f、%[n].[m] g、%[n].[m] G
- 其中 n、m 用数字替换,n 限定了输出的最小总宽度、m 限定精度
#include <stdio.h> | |
int main() | |
{ | |
printf("%5.2d\n", 123); // 输出为 "__123"(_代表空格) | |
return 0; | |
} |
少于最小宽度的会**补空格**来达到要求,多于最小宽度的正常输出 默认右对齐,即左边加空格。在 “%” 和数字间加 “-” 可以改为左对齐 如果写成类似 "%05d" 的形式,就不会补空格而是补0
对于整型 % d,n 限制的是实际输出的整数位数 (从左往右截取), 如果数字位数小于 n 就左边填充 0 (这与 m 限制时填充空格不同)
对于浮点数 % f, 如 “%7.3f”:
此时小数点前面的数 7 表示浮点数最小总位数为 7 而小数点后面的 3 表示浮点数小数部分**强制保留**为 3 位 小数点前面可以没有数字,如:“%.4f”,只有小数强制 4 位的限定 可以只有小数点前面:“%5f”,这种依旧适用,限制最小宽度对于字符串 % s,n 限制的是实际输出的字符个数 (从左往右截取)
对于 % g (% G),n 限制的是有效数字位数,但会删除末尾的 0
占位符 “%” 后面加 “+” 可以让输出强制带有正负号
对于字符串也可以用 “%[n].[m] s” 来限制长度,[n][m] 替换为数字,n 为
比如 “%.5s” 就是截取字符串前 5 位输出
注意! 小数点也算一位!指数里的 e (E) 也算一位!!!
# scanf
scanf 函数用于从外界 (键盘) 获得数据
程序运行到 scanf 函数就会停下来等待输入
输入完按回车后 scanf 开始处理输入的数据
用法和 printf 类似:
int a,b,c; | |
scanf("%d %d %d",&a,&b,&c); |
scanf 第一个参数和 printf 一样,也是格式控制字符串
里面会有占位符,用以规定 scanf 如何读取输入的数据
(C 语言的数据都有类型,所以 scanf 要提前知道类型才能处理数据)
scanf 会自动过滤输入中的空白字符,包括空格、制表符、换行符等
所以输入的数据之间可以有一至多个空格甚至换行
(在最后一个数据也被填入后再回车就会结束输入继续运行)
“% c” 字符类型除外! 空格会被读入!
为什么会有这些特性呢?
让我们追本溯源看看原理:
用户的输入会被放入缓存,按下回车后开始解读
解读时会从上一次解读遗留的第一个字符开始,直到读完缓存或遇到第一个不符合条件的字符
所以在遇到空格时就结束了这个数据的读取 (空格是字符所以会被字符类型读取)
而 scanf 后面的几个参数,如果不是字符串 / 数组等类型 (自带指针)
就必须在变量名前加一个 &, 代表读取其对应的内存地址
# scanf 的返回值
scanf 函数也是有返回值的,返回值就是顺次成功读取的变量个数
(即到第一个错误读取为止之前正确读了几个)
如果输入不匹配,没有读取到任何值,返回 0
如果直接碰到缓存结尾,返回 EOF (其值等于 - 1)
返回 EOF 可以通过按 Ctrl+Z 来实现
# scanf 格式化符号 (占位符)
基本与 printf 一致,但有个特殊的:
- %[]: 在方括号内指定一组匹配字符,遇到不在其中的就结束 (比方说 "%[0-9]")
- % 后用数字限制只能限制最大宽度为 n, 不能用 m 限制
另外还有几个相关要点:
- 对于 “% c” 我们知道它不会忽略起始的空格,但如果写成如下形式可强制跳过起始的一个或多个空格
scanf(" %c", &ch); | |
// 前面加个空格 |
- 对于 “% s” 其代表的不仅仅是一个字符串了,它将从当前第一个非空白字符读起,直到再次遇到空白字符。因此 “% s” 不适合读取带有任何空格的字符串。
- 另外 scanf 在读取 “% s” 时,会在结尾补上 \ 0
- 为了避免 scanf 读取 “% s” 时读太多字符进来溢出字符串类型的最大长度,可以用 “%[m] s” 来限定字符串最大长度。这样可以避免长度溢出。
# 赋值忽略符
#include <stdio.h> | |
int main() | |
{ | |
int year = 0; | |
int month = 0; | |
int day = 0; | |
scanf("%d-%d-%d", &year, &month, &day); | |
printf("%d %d %d\n", year, month, day); | |
return 0; | |
} |
在这里,如果输入 2023-10-17, 就能正常读入
但是如果输入 2023/10/17 就不能正常读入
可以使用赋值忽略符:
在占位符 “%” 后加个 “*”, 比方说:“%*c”
这样,改占位符会正常读取,但不会返回任何值
所以上方代码可以改成这样:
#include <stdio.h> | |
int main() | |
{ | |
int year = 0; | |
int month = 0; | |
int day = 0; | |
scanf("%d%*c%d%*c%d", &year, &month, &day); | |
return 0; | |
} |
这样,无论输入 2023-10-17 还是 2023/10/17 都行了