本文最后更新于 118 天前,其中的信息可能已经过时,如有错误请发送邮件到 shikeAB@outlook.com。
- printf 函数称之为格式输出函数,方法名称的最后一个字母 f 表示 format。其功能是按照用户指定的格式,把指定的数据输出到屏幕上
- printf 函数的调用格式为:
printf("格式控制字符串",输出项列表 );
- 例如:
printf("a = %d, b = %d",a, b);
- 非格式字符串原样输出,格式控制字符串会被输出项列表中的数据替换
- 注意:格式控制字符串和输出项在数量和类型上 *** 必须一一对应 ***
- 格式控制字符串
- 形式:
%[标志][输出宽度][.精度][长度]类型
- 类型
- 格式:
printf("a = %类型", a);
- 类型字符串用以表示输出数据的类型,其格式符和意义如下所示
类型 |
含义 |
d |
有符号 10 进制整型 |
i |
有符号 10 进制整型 |
u |
无符号 10 进制整型 |
o |
无符号 8 进制整型 |
x |
无符号 16 进制整型 |
X |
无符号 16 进制整型 |
f |
单、双精度浮点数 (默认保留 6 位小数) |
e / E |
以指数形式输出单、双精度浮点数 |
g / G |
以最短输出宽度,输出单、双精度浮点数 |
c |
字符 |
s |
字符串 |
p |
地址 |
| #include |
| int main(){ |
| int a = 10; |
| int b = -10; |
| float c = 6.6f; |
| double d = 3.1415926; |
| double e = 10.10; |
| char f = 'a'; |
| |
| printf("a = %d\n", a); |
| printf("a = %i\n", a); |
| |
| |
| printf("a = %u\n", a); |
| printf("b = %u\n", b); |
| |
| |
| printf("a = %o\n", a); |
| printf("b = %o\n", b); |
| |
| |
| printf("a = %x\n", a); |
| printf("b = %x\n", b); |
| |
| |
| printf("a = %X\n", a); |
| printf("b = %X\n", b); |
| |
| |
| printf("c = %f\n", c); |
| printf("d = %lf\n", d); |
| |
| |
| printf("e = %e\n", e); |
| printf("e = %E\n", e); |
| |
| |
| printf("e = %g\n", e); |
| printf("e = %G\n", e); |
| |
| |
| printf("f = %c\n", f); |
| } |
| |
- 宽度
- 格式:
printf("a = %[宽度]类型", a);
- 用十进制整数来指定输出的宽度,如果实际位数多于指定宽度,则按照实际位数输出,如果实际位数少于指定宽度则以空格补位
| #include |
| int main(){ |
| |
| int a = 1; |
| printf("a =|%d|\n", a); |
| printf("a =|%5d|\n", a); |
| |
| int b = 1234567; |
| printf("b =|%d|\n", b); |
| printf("b =|%5d|\n", b); |
| } |
| |
- 标志
- 格式:
printf("a = %[标志][宽度]类型", a);
标志 |
含义 |
– |
左对齐,默认右对齐 |
+ |
当输出值为正数时,在输出值前面加上一个 + 号,默认不显示 |
0 |
右对齐时,用 0 填充宽度.(默认用空格填充) |
空格 |
输出值为正数时,在输出值前面加上空格,为负数时加上负号 |
# |
对 c、s、d、u 类型无影响 |
# |
对 o 类型,在输出时加前缀 o |
# |
对 x 类型,在输出时加前缀 0x |
| #include |
| int main(){ |
| int a = 1; |
| int b = -1; |
| |
| printf("a =|%d|\n", a); |
| printf("a =|%5d|\n", a); |
| printf("a =|%-5d|\n", a); |
| |
| printf("a =|%d|\n", a); |
| printf("a =|%+d|\n", a); |
| printf("b =|%d|\n", b); |
| printf("b =|%+d|\n", b); |
| |
| printf("a =|%5d|\n", a); |
| printf("a =|%05d|\n", a); |
| |
| printf("a =|% d|\n", a); |
| printf("b =|% d|\n", b); |
| |
| int c = 10; |
| printf("c = %o\n", c); |
| printf("c = %#o\n", c); |
| printf("c = %x\n", c); |
| printf("c = %#x\n", c); |
| } |
| |
- 精度
- 格式:
printf("a = %[精度]类型", a);
- 精度格式符以”.” 开头,后面跟上十进制整数,用于指定需要输出多少位小数,如果输出位数大于指定的精度,则删除超出的部分
| #include |
| int main(){ |
| double a = 3.1415926; |
| printf("a = %.2f\n", a); |
| } |
| |
- 动态指定保留小数位数
- 格式:
printf("a = %.*f", a);
| #include |
| int main(){ |
| double a = 3.1415926; |
| printf("a = %.*f", 2, a); |
| } |
| |
- 实型 (浮点类型) 有效位数问题
- 对于单精度数,使用 % f 格式符输出时,仅前 6~7 位是有效数字
- 对于双精度数,使用 % lf 格式符输出时,前 15~16 位是有效数字
- 有效位数和精度 (保留多少位) 不同,有效位数是指从第一个非零数字开始,误差不超过本数位半个单位的、精确可信的数位
- 有效位数包含小数点前的非零数位
| #include |
| int main(){ |
| |
| float a = 1234.567890123456789; |
| |
| double b = 1234.567890123456789; |
| printf("a = %.15f\n", a); |
| printf("b = %.15f\n", b); |
| } |
| |
- 长度
- 格式:
printf("a = %[长度]类型", a);
长度 |
修饰类型 |
含义 |
hh |
d、i、o、u、x |
输出 char |
h |
d、i、o、u、x |
输出 short int |
l |
d、i、o、u、x |
输出 long int |
ll |
d、i、o、u、x |
输出 long long int |
| #include |
| int main(){ |
| char a = 'a'; |
| short int b = 123; |
| int c = 123; |
| long int d = 123; |
| long long int e = 123; |
| printf("a = %hhd\n", a); |
| printf("b = %hd\n", b); |
| printf("c = %d\n", c); |
| printf("d = %ld\n", d); |
| printf("e = %lld\n", e); |
| } |
| |
- 转义字符
- 格式:
printf("%f%%", 3.1415);
- % 号在格式控制字符串中有特殊含义,所以想输出 % 必须添加一个转移字符
| #include |
| int main(){ |
| printf("%f%%", 3.1415); |
| } |
| |
- scanf 函数用于接收键盘输入的内容,是一个阻塞式函数,程序会停在 scanf 函数出现的地方,直到接收到数据才会执行后面的代码
- printf 函数的调用格式为:
scanf("格式控制字符串", 地址列表);
- 例如:
scanf("%d", &num);
- 基本用法
- 地址列表项中只能传入变量地址,变量地址可以通过 & 符号 + 变量名称的形式获取
| #include |
| int main(){ |
| int number; |
| scanf("%d", &number); |
| printf("number = %d\n", number); |
| } |
| |
- 接收非字符和字符串类型时,空格、Tab 和回车会被忽略
| #include |
| int main(){ |
| float num; |
| |
| scanf("%f", &num); |
| printf("num = %f\n", num); |
| } |
| |
- 非格式字符串原样输入,格式控制字符串会赋值给地址项列表项中的变量
| #include |
| int main(){ |
| int number; |
| |
| scanf("number = %d", &number); |
| printf("number = %d\n", number); |
| } |
| |
- 接收多条数据
- 格式控制字符串和地址列表项在数量和类型上必须一一对应
- 非字符和字符串情况下如果没有指定多条数据的分隔符,可以使用空格或者回车作为分隔符 (不推荐这种写法)
- 非字符和字符串情况下建议明确指定多条数据之间分隔符
| #include |
| int main(){ |
| int number; |
| scanf("%d", &number); |
| printf("number = %d\n", number); |
| int value; |
| scanf("%d", &value); |
| printf("value = %d\n", value); |
| } |
| |
| #include |
| int main(){ |
| int number; |
| int value; |
| |
| scanf("%d%d", &number, &value); |
| printf("number = %d\n", number); |
| printf("value = %d\n", value); |
| } |
| |
| #include |
| int main(){ |
| int number; |
| int value; |
| |
| scanf("%d,%d", &number, &value); |
| printf("number = %d\n", number); |
| printf("value = %d\n", value); |
| } |
| |
- \n 是 scanf 函数的结束符号,所以格式化字符串中不能出现 \n
| #include |
| int main(){ |
| int number; |
| |
| scanf("%d\n", &number); |
| printf("number = %d\n", number); |
| } |
| |
- 系统会将用户输入的内容先放入输入缓冲区
- scanf 方式会从输入缓冲区中逐个取出内容赋值给变量
- 如果输入缓冲区的内容不为空,scanf 会一直从缓冲区中获取,而不要求再次输入
| |
| int main(){ |
| int num1; |
| int num2; |
| char ch1; |
| scanf("%d%c%d", &num1, &ch1, &num2); |
| printf("num1 = %d, ch1 = %c, num2 = %d\n", num1, ch1, num2); |
| char ch2; |
| int num3; |
| scanf("%c%d",&ch2, &num3); |
| printf("ch2 = %c, num3 = %d\n", ch2, num3); |
| } |
| |
- 利用 fflush 方法清空缓冲区 (不是所有平台都能使用)
- 格式:
fflush(stdin);
- C 和 C++ 的标准里从来没有定义过 fflush (stdin)
- MSDN 文档里清除的描述着”fflush on input stream is an extension to the C standard” (fflush 是在标准上扩充的函数,不是标准函数,所以不是所有平台都支持)
- 利用 setbuf 方法清空缓冲区 (所有平台有效)
| #include |
| int main(){ |
| int num1; |
| int num2; |
| char ch1; |
| scanf("%d%c%d", &num1, &ch1, &num2); |
| printf("num1 = %d, ch1 = %c, num2 = %d\n", num1, ch1, num2); |
| |
| setbuf(stdin, NULL); |
| char ch2; |
| int num3; |
| scanf("%c%d",&ch2, &num3); |
| printf("ch2 = %c, num3 = %d\n", ch2, num3); |
| } |
| |
| #include |
| int main(){ |
| char ch = 'a'; |
| putchar(ch); |
| } |
| |
| #include |
| int main(){ |
| char ch; |
| ch = getchar(); |
| printf("ch = %c\n", ch); |
| } |
| |
- 和数学中的运算符一样,C 语言中的运算符是告诉程序执行特定算术或逻辑操作的符号
-
什么是表达式
- 表达式就是利用运算符链接在一起的有意义,有结果的语句;
- 例如: a + b; 就是一个算数表达式,它的意义是将两个数相加,两个数相加的结果就是表达式的结果
- 注意:表达式一定要有结果
- 按照功能划分:
- 算术运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 按照参与运算的操作数个数划分:
- 单目运算
- 双目运算
- 三目运算
- C 语言中唯一的一个,也称为问号表达式 如: a>b ? 1 : 0;
- 早在小学的数学课本中,我们就学习过” 从左往右,先乘除后加减,有括号的先算括号里面的”, 这句话就蕴含了优先级和结合性的问题
- C 语言中,运算符的运算优先级共分为 15 级。1 级最高,15 级最低
- 在 C 语言表达式中,不同优先级的运算符,运算次序按照由高到低执行
- 在 C 语言表达式中,相同优先级的运算符,运算次序按照结合性规定的方向执行
优先级 |
名称 |
符号 |
说明 |
3 |
乘法运算符 |
* |
双目运算符,具有左结合性 |
3 |
除法运算符 |
/ |
双目运算符,具有左结合性 |
3 |
求余运算符 (模运算符) |
% |
双目运算符,具有左结合性 |
4 |
加法运算符 |
+ |
双目运算符,具有左结合性 |
4 |
减法运算符 |
– |
双目运算符,具有左结合性 |
- 注意事项
- 如果参与运算的两个操作数皆为整数,那么结果也为整数
- 如果参与运算的两个操作数其中一个是浮点数,那么结果一定是浮点数
- 求余运算符,本质上就是数学的商和余” 中的余数
- 求余运算符,参与运算的两个操作数必须都是整数,不能包含浮点数
- 求余运算符,被除数小于除数,那么结果就是被除数
- 求余运算符,运算结果的正负性取决于被除数,跟除数无关,被除数是正数结果就是正数,被除数是负数结果就是负数
- 求余运算符,被除数为 0, 结果为 0
- 求余运算符,除数为 0, 没有意义 (不要这样写)
| #include |
| int main(){ |
| int a = 10; |
| int b = 5; |
| |
| int result = a + b; |
| printf("%i\n", result); |
| |
| result = a - b; |
| printf("%i\n", result); |
| |
| result = a * b; |
| printf("%i\n", result); |
| |
| result = a / b; |
| printf("%i\n", result); |
| |
| |
| |
| int c = 50; |
| result = a + b + c; |
| printf("%i\n", result); |
| |
| |
| result = a + b * c; |
| printf("%i\n", result); |
| } |
| |
| #include |
| int main(){ |
| |
| printf("%i\n", 10 / 3); |
| |
| |
| printf("%f\n", 10 / 3.0); |
| } |
| |
| #include |
| int main(){ |
| |
| int result = 10 % 3; |
| printf("%i\n", result); |
| |
| |
| result = 2 % 10; |
| printf("%i\n", result); |
| |
| |
| result = 10 % 3; |
| printf("%i\n", result); |
| result = -10 % 3; |
| printf("%i\n", result); |
| result = 10 % -3; |
| printf("%i\n", result); |
| } |
| |
优先级 |
名称 |
符号 |
说明 |
14 |
赋值运算符 |
= |
双目运算符,具有右结合性 |
14 |
除后赋值运算符 |
/= |
双目运算符,具有右结合性 |
14 |
乘后赋值运算符 (模运算符) |
*= |
双目运算符,具有右结合性 |
14 |
取模后赋值运算符 |
%= |
双目运算符,具有右结合性 |
14 |
加后赋值运算符 |
+= |
双目运算符,具有右结合性 |
14 |
减后赋值运算符 |
-= |
双目运算符,具有右结合性 |
| #include |
| int main(){ |
| |
| |
| int a = 10; |
| printf("a = %i\n", a); |
| } |
| |
| #include |
| int main(){ |
| |
| |
| int num1 = 10; |
| |
| num1 += 1; |
| printf("num1 = %i\n", num1); |
| int num2 = 10; |
| |
| num2 -= 1; |
| printf("num2 = %i\n", num2); |
| int num3 = 10; |
| |
| num3 *= 2; |
| printf("num3 = %i\n", num3); |
| int num4 = 10; |
| |
| num4 /= 2; |
| printf("num4 = %i\n", num4); |
| int num5 = 10; |
| |
| num5 %= 3; |
| printf("num5 = %i\n", num5); |
| } |
| |
| #include |
| int main(){ |
| int number = 10; |
| |
| |
| |
| number += 1 + 5 * 5; |
| printf("number = %i\n", number); |
| } |
| |
- 在程序设计中,经常遇到 “i=i+1” 和 “i=i-1” 这两种极为常用的操作。
- C 语言为这种操作提供了两个更为简洁的运算符,即 ++ 和–
优先级 |
名称 |
符号 |
说明 |
2 |
自增运算符 (在后) |
i++ |
单目运算符,具有左结合性 |
2 |
自增运算符 (在前) |
++i |
单目运算符,具有右结合性 |
2 |
自减运算符 (在后) |
i– |
单目运算符,具有左结合性 |
2 |
自减运算符 (在前) |
–i |
单目运算符,具有右结合性 |
- 自增
- 如果只有 *** 单个 *** 变量,无论 ++ 写在前面还是后面都会对变量做 + 1 操作
| #include |
| int main(){ |
| int number = 10; |
| number++; |
| printf("number = %i\n", number); |
| ++number; |
| printf("number = %i\n", number); |
| } |
| |
- 如果出现在一个表达式中,那么 ++ 写在前面和后面就会有所区别
- 前缀表达式:++x, –x; 其中 x 表示变量名,先完成变量的自增自减 1 运算,再用 x 的值作为表达式的值;即 “先变后用”, 也就是变量的值先变,再用变量的值参与运算
- 后缀表达式:x++, x–; 先用 x 的当前值作为表达式的值,再进行自增自减 1 运算。即 “先用后变”, 也就是先用变量的值参与运算,变量的值再进行自增自减变化
| #include |
| int main(){ |
| int number = 10; |
| |
| |
| int result = 3 + number++; |
| printf("result = %i\n", result); |
| printf("number = %i\n", number); |
| } |
| |
| #include |
| int main(){ |
| int number = 10; |
| |
| |
| int result = 3 + ++number; |
| printf("result = %i\n", result); |
| printf("number = %i\n", number); |
| } |
| |
| #include |
| int main(){ |
| int number = 10; |
| |
| |
| int result = number-- + 3; |
| printf("result = %i\n", result); |
| printf("number = %i\n", number); |
| } |
| |
| #include |
| int main(){ |
| int number = 10; |
| |
| |
| int result = --number + 3; |
| printf("result = %i\n", result); |
| printf("number = %i\n", number); |
| } |
| |
- 注意点:
- 自增、自减运算只能用于单个变量,只要是标准类型的变量,不管是整型、实型,还是字符型变量等,但不能用于表达式或常量
- 企业开发中尽量让 ++ – 单独出现,尽量不要和其它运算符混合在一起
| int i = 10; |
| int b = i++; |
| 或者 |
| int b = ++i; |
| 或者 |
| int a = 10; |
| int b = ++a + a++; |
| int i = 10; |
| int b = i; |
| i++; |
| 或者; |
| i++; |
| int b = i; |
| 或者 |
| int a = 10; |
| ++a; |
| int b = a + a; |
| a++; |
- C 语言标准没有明确的规定,
同一个表达式中同一个变量自增或自减后如何运算
, 不同编译器得到结果也不同,在企业开发中千万不要这样写
| int a = 1; |
| |
| |
| |
| |
| int b = ++a + ++a; |
| printf("b = %i\n", b); |
| #include |
| int main(){ |
| int a = 10; |
| double b = 3.14; |
| |
| |
| |
| double res = sizeof a+b; |
| printf("res = %lf\n", res); |
| } |
| |
- 在 C 语言中逗号 “,” 也是一种运算符,称为逗号运算符。 其功能是把多个表达式连接起来组成一个表达式,称为逗号表达式
- 逗号运算符会从左至右依次取出每个表达式的值,最后整个逗号表达式的值等于最后一个表达式的值
- 格式:
表达式1,表达式2,… …,表达式n;
- 例如:
int result = a+1,b=3*4;
| #include |
| int main(){ |
| int a = 10, b = 20, c; |
| |
| |
| |
| |
| c = (a + 1, b + 1); |
| printf("c = %i\n", c); |
| } |
| |
- 为什么要学习关系运算符
- 默认情况下,我们在程序中写的每一句正确代码都会被执行。但很多时候,我们想在某个条件成立的情况下才执行某一段代码
- 这种情况的话可以使用条件语句来完成,但是学习条件语句之前,我们先来看一些更基础的知识:如何判断一个条件是否成立
- C 语言中的真假性
- 在 C 语言中,条件成立称为 “真”,条件不成立称为 “假”,因此,判断条件是否成立,就是判断条件的 “真假”
- 怎么判断真假呢?C 语言规定,任何数值都有真假性,任何非 0 值都为 “真”,只有 0 才为 “假”。也就是说,108、-18、4.5、-10.5 等都是 “真”,0 则是 “假”
- 关系运算符的运算结果只有 2 种:如果条件成立,结果就为 1,也就是 “真”;如果条件不成立,结果就为 0,也就是 “假”
优先级 |
名称 |
符号 |
说明 |
6 |
大于运算符 |
> |
双目运算符,具有左结合性 |
6 |
小于运算符 |
< |
双目运算符,具有左结合性 |
6 |
大于等于运算符 |
>= |
双目运算符,具有左结合性 |
6 |
小于等于运算符 |
<= |
双目运算符,具有左结合性 |
7 |
等于运算符 |
== |
双目运算符,具有左结合性 |
7 |
不等于运算符 |
!= |
双目运算符,具有左结合性 |
| #include |
| int main(){ |
| int result = 10 > 5; |
| printf("result = %i\n", result); |
| result = 5 < 10; |
| printf("result = %i\n", result); |
| result = 5 > 10; |
| printf("result = %i\n", result); |
| result = 10 >= 10; |
| printf("result = %i\n", result); |
| result = 10 <= 10; |
| printf("result = %i\n", result); |
| result = 10 == 10; |
| printf("result = %i\n", result); |
| result = 10 != 9; |
| printf("result = %i\n", result); |
| } |
| |
| #include |
| int main(){ |
| |
| |
| int result = 10 == 5 > 3; |
| printf("result = %i\n", result); |
| } |
| |
| #include |
| int main(){ |
| |
| |
| |
| int result = 10 == 5 != 3; |
| printf("result = %i\n", result); |
| } |
| |
| int result1 = 3 > 4 + 7 |
| int result2 = (3>4) + 7 |
| int result3 = 5 != 4 + 2 * 7 > 3 == 10 |
- 注意点:
- 无论是 float 还是 double 都有精度问题,所以一定要避免利用 == 判断浮点数是否相等
| #include |
| int main(){ |
| float a = 0.1; |
| float b = a * 10 + 0.00000000001; |
| double c = 1.0 + + 0.00000000001; |
| printf("b = %f\n", b); |
| printf("c = %f\n", c); |
| int result = b == c; |
| printf("result = %i\n", result); |
| } |
| |
优先级 |
名称 |
符号 |
说明 |
2 |
逻辑非运算符 |
! |
单目运算符,具有右结合性 |
11 |
逻辑与运算符 |
&& |
双目运算符,具有左结合性 |
12 |
逻辑或运算符 |
\|\| |
双目运算符,具有左结合性 |
- 逻辑非
- 格式:
! 条件A;
- 运算结果:真变假,假变真
- 运算过程:
- 先判断条件 A 是否成立,如果添加 A 成立,那么结果就为 0,即 “假”;
- 如果条件 A 不成立,结果就为 1,即 “真”
- 使用注意:
- 可以多次连续使用逻辑非运算符
- !!!0; 相当于 (!(!(!0))); 最终结果为 1
| #include |
| int main(){ |
| |
| |
| |
| int result = !(10 == 10); |
| printf("result = %i\n", result); |
| } |
| |
- 逻辑与
- 格式:
条件A && 条件B;
- 运算结果:一假则假
- 运算过程:
- 总是先判断 "条件 A" 是否成立
- 如果 "条件 A" 成立,接着再判断 "条件 B" 是否成立,如果 "条件 B" 也成立,结果就为 1,即 “真”
- 如果 "条件 A" 成立,"条件 B" 不成立,结果就为 0,即 “假”
- 如果 "条件 A" 不成立,不会再去判断 "条件 B" 是否成立,因为逻辑与只要一个不为真结果都不为真
- 使用注意:
| #include |
| int main(){ |
| |
| int result = (10 == 10) && (5 != 1); |
| printf("result = %i\n", result); |
| |
| result = (10 == 9) && (5 != 1); |
| printf("result = %i\n", result); |
| |
| result = (10 == 10) && (5 != 5); |
| printf("result = %i\n", result); |
| |
| result = (10 == 9) && (5 != 5); |
| printf("result = %i\n", result); |
| } |
| |
| #include |
| int main(){ |
| int a = 10; |
| int b = 20; |
| |
| int result = (a == 9) && (++b); |
| printf("result = %i\n", result); |
| printf("b = %i\n", b); |
| } |
| |
- 逻辑或
- 格式:
条件A || 条件B;
- 运算结果:一真则真
- 运算过程:
- 总是先判断 "条件 A" 是否成立
- 如果 "条件 A" 不成立,接着再判断 "条件 B" 是否成立,如果 "条件 B" 成立,结果就为 1,即 “真”
- 如果 "条件 A" 不成立,"条件 B" 也不成立成立,结果就为 0,即 “假”
- 如果 "条件 A" 成立,不会再去判断 "条件 B" 是否成立,因为逻辑或只要一个为真结果都为真
- 使用注意:
| #include |
| int main(){ |
| |
| int result = (10 == 10) || (5 != 1); |
| printf("result = %i\n", result); |
| |
| result = (10 == 9) || (5 != 1); |
| printf("result = %i\n", result); |
| |
| result = (10 == 10) || (5 != 5); |
| printf("result = %i\n", result); |
| |
| result = (10 == 9) || (5 != 5); |
| printf("result = %i\n", result); |
| } |
| |
| #include |
| int main(){ |
| int a = 10; |
| int b = 20; |
| |
| int result = (a == 10) || (++b); |
| printf("result = %i\n", result); |
| printf("b = %i\n", b); |
| } |
| |
| int result = 3>5 || 2<4 && 6<1; |
| 示例: |
| int a = 10; |
| int b = 20; |
| int max = (a > b) ? a : b; |
| printf("max = %d", max); |
| 输出结果: 20 |
| 等价于: |
| int a = 10; |
| int b = 20; |
| int max = 0; |
| if(a>b){ |
| max=a; |
| }else { |
| max=b; |
| } |
| printf("max = %d", max); |
- 注意点
- 条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符
- 条件运算符?和:是一个整体,不能分开使用
| #include |
| int main(){ |
| int a = 10; |
| int b = 5; |
| |
| |
| |
| int max= a>b ? a : b; |
| printf("max = %i\n", max); |
| } |
| |
| #include |
| int main(){ |
| int a = 10; |
| int b = 5; |
| int c = 20; |
| int d = 10; |
| |
| |
| |
| |
| |
| |
| |
| int res = a>b?a:c>d?c:d; |
| printf("res = %i\n", res); |
| } |
| |
强制类型转换 (显示转换) |
自动类型转换 (隐式转换) |
(需要转换的类型)(表达式) |
1. 算数转换 2. 赋值转换 |
- 算数转换
- 系统会自动对占用内存较少的类型做一个 “自动类型提升” 的操作,先将其转换为当前算数表达式中占用内存高的类型,然后再参与运算
| |
| double a = (double)(1 / 2); |
| |
| double b = (double)1 / 2; |
| #include |
| int main(){ |
| double d = 3.14; |
| int num = (int)d; |
| printf("num = %i\n", num); |
| printf("d = %lf\n", d); |
| } |
| |
- 从键盘输入一个整数,判断这个数是否是 100 到 200 之间的数
- 表达式 6==6==6 的值是多少?
- 用户从键盘上输入三个整数,找出最大值,然后输入最大值
- 用两种方式交换两个变量的保存的值
| 交换前 |
| int a = 10; int b = 20; |
| 交换后 |
| int a = 20; int b = 10; |
- C 语言中提供了两大选择结构,分别是 if 和 switch
## 选择结构 if
- if 第一种形式
| if(age >= 18) { |
| printf("开网卡\n"); |
| } |
| printf("买烟\n"); |
- if 第二种形式
- 如果表达式为真,则执行语句块 1, 否则执行语句块 2
- else 不能脱离 if 单独使用
| if(表达式){ |
| 语句块1; |
| }else{ |
| 语句块2; |
| } |
| 后续语句; |
| if(age > 18){ |
| printf("开网卡\n"); |
| }else{ |
| printf("喊家长来开\n"); |
| } |
| printf("买烟\n"); |
- if 第三种形式
- 如果 "表达式 1" 为真,则执行 "语句块 1", 否则判断 "表达式 2", 如果为真执行 "语句块 2", 否则再判断 "表达式 3", 如果真执行 "语句块 3", 当表达式 1、2、3 都不满足,会执行最后一个 else 语句
- 众多大括号中,只有一个大括号中的内容会被执行
- 只有前面所有添加都不满足,才会执行 else 大括号中的内容
| if(表达式1) { |
| 语句块1; |
| }else if(表达式2){ |
| 语句块2; |
| }else if(表达式3){ |
| 语句块3; |
| }else{ |
| 语句块4; |
| } |
| 后续语句; |
| if(age>40){ |
| printf("给房卡"); |
| }else if(age>25){ |
| printf("给名片"); |
| }else if(age>18){ |
| printf("给网卡"); |
| }else{ |
| printf("给好人卡"); |
| } |
| printf("买烟\n"); |
- if 嵌套
- if 中可以继续嵌套 if, else 中也可以继续嵌套 if
| if(表达式1){ |
| 语句块1; |
| if(表达式2){ |
| 语句块2; |
| } |
| }else{ |
| if(表达式3){ |
| 语句块3; |
| }else{ |
| 语句块4; |
| } |
| } |
| #include |
| int main(){ |
| if(0){ |
| printf("执行了if"); |
| }else{ |
| printf("执行了else"); |
| } |
| } |
| |
- 当 if else 后面只有一条语句时,if else 后面的大括号可以省略
| |
| int age = 17; |
| if (age >= 18) |
| printf("开网卡\n"); |
| else |
| printf("喊家长来开\n"); |
- 当 if else 后面的大括号被省略时,else 会自动和距离最近的一个 if 匹配
| #include |
| int main(){ |
| if(0) |
| if(1) |
| printf("A\n"); |
| else |
| printf("B\n"); |
| else |
| if (1) |
| printf("C\n"); |
| else |
| printf("D\n"); |
| } |
| |
-
- 如果 if else 省略了大括号,那么后面不能定义变量
| #include |
| int main(){ |
| if(1) |
| int number = 10; |
| printf("number = %i\n", number); |
| } |
| |
| #include |
| int main(){ |
| if(0){ |
| int number = 10; |
| }else |
| int value = 20; |
| printf("value = %i\n", value); |
| } |
| |
- C 语言中分号 (;) 也是一条语句,称之为空语句
| |
| |
| if(10 > 2); |
| { |
| printf("10 > 2"); |
| } |
| |
- 但凡遇到比较一个变量等于或者不等于某一个常量的时候,把常量写在前面
| #include |
| int main(){ |
| int a = 8; |
| |
| if (10 == a){ |
| printf("a的值是10\n"); |
| }else{ |
| printf("a的值不是10\n"); |
| } |
| } |
| |
-
if 练习
- 从键盘输入一个整数,判断其是否是偶数,如果是偶数就输出 YES,否则输出 NO;
- 接收用户输入的 1~7 的整数,根据用户输入的整数,输出对应的星期几
- 接收用户输入的一个整数 month 代表月份,根据月份输出对应的季节
- 接收用户输入的两个整数,判断大小后输出较大的那个数
- 接收用户输入的三个整数,判断大小后输出较大的那个数
- 接收用户输入的三个整数,排序后输出
-
实现石头剪刀布
| 剪刀石头布游戏: |
| 1)定义游戏规则 |
| 剪刀 干掉 布 |
| 石头 干掉 剪刀 |
| 布 干掉石头 |
| 2)显示玩家开始猜拳 |
| 3)接收玩家输入的内容 |
| 4)让电脑随机产生一种拳 |
| 5)判断比较 |
| (1)玩家赢的情况(显示玩家赢了) |
| (2)电脑赢的情况(显示电脑赢了) |
| (3)平局(显示平局) |
- 由于 if else if 还是不够简洁,所以 switch 就应运而生了,他跟 if else if 互为补充关系。switch 提供了点的多路选择
- 格式:
| switch(表达式){ |
| case 常量表达式1: |
| 语句1; |
| break; |
| case 常量表达式2: |
| 语句2; |
| break; |
| case 常量表达式n: |
| 语句n; |
| break; |
| default: |
| 语句n+1; |
| break; |
| } |
- 语义:
- 计算 "表达式" 的值,逐个与其后的 "常量表达式" 值相比较,当 "表达式" 的值与某个 "常量表达式" 的值相等时,即执行其后的语句,然后跳出 switch 语句
- 如果 "表达式" 的值与所有 case 后的 "常量表达式" 均不相同时,则执行 default 后的语句
- 示例:
| #include |
| |
| int main() { |
| |
| int num = 3; |
| switch(num){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 2: |
| printf("星期二\n"); |
| break; |
| case 3: |
| printf("星期三\n"); |
| break; |
| case 4: |
| printf("星期四\n"); |
| break; |
| case 5: |
| printf("星期五\n"); |
| break; |
| case 6: |
| printf("星期六\n"); |
| break; |
| case 7: |
| printf("星期日\n"); |
| break; |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
- switch 注意点
- switch 条件表达式的类型必须是整型,或者可以被提升为整型的值 (char、short)
| #include |
| |
| int main() { |
| |
| switch(1.1){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 2: |
| printf("星期二\n"); |
| break; |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
- +case 的值只能是常量,并且还必须是整型,或者可以被提升为整型的值 (char、short)
| #include |
| |
| int main() { |
| |
| int num = 3; |
| switch(1){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 'a': |
| printf("星期二\n"); |
| break; |
| case num: |
| printf("星期三\n"); |
| break; |
| case 4.0: |
| printf("星期四\n"); |
| break; |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
| #include |
| |
| int main() { |
| switch(1){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 1: |
| printf("星期一\n"); |
| break; |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
- case 后面要想定义变量,必须给 case 加上大括号
| #include |
| |
| int main() { |
| switch(1){ |
| case 1:{ |
| int num = 10; |
| printf("num = %i\n", num); |
| printf("星期一\n"); |
| break; |
| } |
| case 2: |
| printf("星期一\n"); |
| break; |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
- switch 中只要任意一个 case 匹配,其它所有的 case 和 default 都会失效。所以如果 case 和 default 后面没有 break 就会出现穿透问题
| #include |
| |
| int main() { |
| |
| int num = 2; |
| switch(num){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 2: |
| printf("星期二\n"); |
| case 3: |
| printf("星期三\n"); |
| default: |
| printf("回火星去\n"); |
| break; |
| } |
| } |
| |
| #include |
| |
| int main() { |
| switch(1){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| case 2: |
| printf("星期一\n"); |
| break; |
| } |
| } |
| |
- switch 中 default 的位置不一定要写到最后,无论放到哪都会等到所有 case 都不匹配才会执行 (穿透问题除外)
| #include |
| |
| int main() { |
| switch(3){ |
| case 1: |
| printf("星期一\n"); |
| break; |
| default: |
| printf("Other,,,\n"); |
| break; |
| case 2: |
| printf("星期一\n"); |
| break; |
| } |
| } |
| |
- if 和 Switch 转换
- 看上去 if 和 switch 都可以实现同样的功能,那么在企业开发中我们什么时候使用 if, 什么时候使用 switch 呢?
- if else if 针对于范围的多路选择
- switch 是针对点的多路选择
- 判断用户输入的数据是否大于 100
| #include |
| |
| int main() { |
| int a = -1; |
| scanf("%d", &a); |
| if(a > 100){ |
| printf("用户输入的数据大于100"); |
| }else{ |
| printf("用户输入的数据不大于100"); |
| } |
| } |
| |
| #include |
| |
| int main() { |
| int a = -1; |
| scanf("%d", &a); |
| |
| switch (a) { |
| case 101: |
| case 102: |
| case 103: |
| case 104: |
| case 105: |
| printf("大于\n"); |
| break; |
| default: |
| printf("不大于\n"); |
| break; |
| } |
| } |
| |
| 要求用户输入一个分数,根据输入的分数输出对应的等级 |
| A 90~100 |
| B 80~89 |
| C 70~79 |
| D 60~69 |
| E 0~59 |
- C 语言中提供了三大循环结构,分别是 while、dowhile 和 for
- 循环结构是程序中一种很重要的结构。
- 其特点是,在给定条件成立时,反复执行某程序段,直到条件不成立为止。
- 给定的条件称为 "循环条件", 反复执行的程序段称为 "循环体"
| while ( 循环控制条件 ) { |
| 循环体中的语句; |
| 能够让循环结束的语句; |
| .... |
| } |
-
构成循环结构的几个条件
- 循环控制条件
- 循环体
- 能够让循环结束的语句 (递增、递减、真、假等)
-
示例:
| int count = 0; |
| while (count < 3) { |
| printf("发射子弹~哔哔哔哔\n"); |
| count++; |
| } |
- while 循环执行流程
- 首先会判定 "循环控制条件" 是否为真,如果为假直接跳到循环语句后面
- 如果 "循环控制条件" 为真,执行一次循环体,然后再次判断 "循环控制条件" 是否为真,为真继续执行循环体,为假跳出循环
- 重复以上操作,直到 "循环控制条件" 为假为止
| #include |
| int main(){ |
| int count = 4; |
| |
| while (count < 3) { |
| printf("发射子弹~哔哔哔哔\n"); |
| count++; |
| } |
| |
| printf("循环执行完毕\n"); |
| } |
| |
| #include |
| int main(){ |
| int count = 0; |
| |
| |
| |
| |
| while (count < 3) { |
| |
| |
| |
| printf("发射子弹~哔哔哔哔\n"); |
| |
| |
| |
| count++; |
| } |
| |
| printf("循环执行完毕\n"); |
| } |
| |
| #include |
| int main(){ |
| while (1) { |
| printf("发射子弹~哔哔哔哔\n"); |
| |
| } |
| } |
| |
- 当 while 后面只有一条语句时,while 后面的大括号可以省略
| #include |
| int main(){ |
| while (1) |
| printf("发射子弹~哔哔哔哔\n"); |
| |
| } |
| |
- 如果 while 省略了大括号,那么后面不能定义变量
| #include |
| int main(){ |
| while (1) |
| int num = 10; |
| |
| } |
| |
- C 语言中分号 (;) 也是一条语句,称之为空语句
| #include |
| int main(){ |
| int count = 0; |
| while (count < 3);{ |
| printf("发射子弹~哔哔哔哔\n"); |
| count++; |
| } |
| } |
| |
- while 练习
- 计算 1 + 2 + 3 + …n 的和
- 获取 1~100 之间 7 的倍数的个数
| do { |
| 循环体中的语句; |
| 能够让循环结束的语句; |
| .... |
| } while (循环控制条件 ); |
| int count = 0; |
| do { |
| printf("发射子弹~哔哔哔哔\n"); |
| count++; |
| }while(count < 10); |
-
do-while 循环执行流程
- 首先不管 while 中的条件是否成立,都会执行一次 "循环体"
- 执行完一次循环体,接着再次判断 while 中的条件是否为真,为真继续执行循环体,为假跳出循环
- 重复以上操作,直到 "循环控制条件" 为假为止
-
应用场景
| #include |
| int main() |
| { |
| int num = -1; |
| do{ |
| printf("请输入密码,验证您的身份\n"); |
| scanf("%d", &num); |
| }while(123456 != num); |
| printf("主人,您终于回来了\n"); |
| } |
| |
- while 和 dowhile 应用场景
- 绝大多数情况下 while 和 dowhile 可以互换,所以能用 while 就用 while
- 无论如何都需要先执行一次循环体的情况,才使用 dowhile
- do while 曾一度提议废除,但是他在输入性检查方面还是有点用的
| for(初始化表达式;循环条件表达式;循环后的操作表达式) { |
| 循环体中的语句; |
| } |
| for(int i = 0; i < 10; i++){ |
| printf("发射子弹~哔哔哔哔\n"); |
| } |
-
for 循环执行流程
- 首先执行 "初始化表达式",而且在整个循环过程中,*** 只会执行一次 *** 初始化表达式
- 接着判断 "循环条件表达式" 是否为真,为真执行循环体中的语句
- 循环体执行完毕后,接下来会执行 "循环后的操作表达式",然后再次判断条件是否为真,为真继续执行循环体,为假跳出循环
- 重复上述过程,直到条件不成立就结束 for 循环
-
for 循环注意点:
- 和 while 一模一样
- 最简单的死循环
for(;;);
-
for 和 while 应用场景
- while 能做的 for 都能做,所以企业开发中能用 for 就用 for, 因为 for 更为灵活
- 而且对比 while 来说 for 更节约内存空间
| int count = 0; |
| while (count < 10) { |
| printf("发射子弹~哔哔哔哔 %i\n", count); |
| count++; |
| } |
| |
| printf("count = %i\n", count); |
| |
| |
| |
| for (int count = 0; count < 10; count++) { |
| printf("发射子弹~哔哔哔哔 %i\n", count); |
| } |
| |
| |
| int count = 0; |
| for (; count < 10; count++) { |
| printf("发射子弹~哔哔哔哔\n", count); |
| } |
| printf("count = %i\n", count); |
| while(1) { |
| while(2) { |
| break; |
| } |
| printf("while1循环体\n"); |
| } |
| while(2){ |
| break; |
| printf("打我啊!"); |
| } |
- continue
- 结束 *** 本轮 *** 循环,进入 *** 下一轮 *** 循环
- 应用场景:
- continue 注意点:
- goto
- 这是一个不太值得探讨的话题,goto 会破坏结构化程序设计流程,它将使程序层次不清,且不易读,所以慎用
- goto 语句,仅能在本函数内实现跳转,不能实现跨函数跳转 (短跳转)。但是他在跳出多重循环的时候效率还是蛮高的
| #include |
| int main(){ |
| int num = 0; |
| |
| loop:if(num < 10){ |
| printf("num = %d\n", num); |
| num++; |
| |
| goto loop; |
| } |
| } |
| |
| #include |
| int main(){ |
| while (1) { |
| while(2){ |
| goto lnj; |
| } |
| } |
| lnj:printf("跳过了所有循环"); |
| } |
| |
- return
- 结束当前函数,将结果返回给调用者
- 不着急,放一放,学到函数我们再回头来看它
- 循环结构的循环体中存在其他的循环结构,我们称之为循环嵌套
- 注意:一般循环嵌套不超过三层
- 外循环执行的次数 * 内循环执行的次数就是内循环总共执行的次数
- 格式:
| while(条件表达式) { |
| while循环结构 or dowhile循环结构 or for循环结构 |
| } |
| for(初始化表达式;循环条件表达式;循环后的操作表达式) { |
| while循环结构 or dowhile循环结构 or for循环结构 |
| } |
| do { |
| while循环结构 or dowhile循环结构 or for循环结构 |
| } while (循环控制条件 ); |
- 循环优化
- 在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少 CPU 跨切循环层的次数
| for (row=0; row<100; row++) { |
| |
| for ( col=0; col<5; col++ ) { |
| sum = sum + a[row][col]; |
| } |
| } |
| for (col=0; col<5; col++ ) { |
| |
| for (row=0; row<100; row++) { |
| sum = sum + a[row][col]; |
| } |
| } |
| 好友列表1 |
| 好友1 |
| 好友2 |
| 好友列表2 |
| 好友1 |
| 好友2 |
| 好友列表3 |
| 好友1 |
| 好友2 |
| |
| for (int i = 0; i < 4; i++) { |
| printf("好友列表%d\n", i+1); |
| for (int j = 0; j < 4; j++) { |
| printf(" 角色%d\n", j); |
| } |
| } |
- 一重循环解决线性的问题,而二重循环和三重循环就可以解决平面和立体的问题了
- 打印矩形
| |
| |
| for (int i = 0; i < 3; i++) { |
| |
| for (int j = 0; j < 4; j++) { |
| printf("*"); |
| } |
| printf("\n"); |
| } |
- 打印三角形
- 尖尖朝上,改变内循环的条件表达式,让内循环的条件表达式随着外循环的 i 值变化
- 尖尖朝下,改变内循环的初始化表达式,让内循环的初始化表达式随着外循环的 i 值变化
| |
| |
| |
| |
| |
| for(int i = 0; i< 5; i++) { |
| for(int j = 0; j <= i; j++) { |
| printf("*"); |
| } |
| printf("\n"); |
| } |
| for(int i = 0; i< 5; i++) { |
| for(int j = i; j < 5; j++) { |
| printf("*"); |
| } |
| printf("\n"); |
| } |
| for (int i = 0; i < 3; i++) { |
| for (int j = 0; j <= i; j++) { |
| printf("%d", j+1); |
| } |
| printf("\n"); |
| } |
| for (int i = 1; i <= 3; i++) { |
| for (int j = 1; j <= i; j++) { |
| printf("%d", i); |
| } |
| printf("\n"); |
| } |
| for (int i = 0; i <= 5; i++) { |
| for (int j = 0; j < 5 - i; j++) { |
| printf("-"); |
| } |
| for (int m = 0; m < 2*i+1; m++) { |
| printf("*"); |
| } |
| printf("\n"); |
| } |
| 1 * 1 = 1 |
| 1 * 2 = 2 2 * 2 = 4 |
| 1 * 3 = 3 2 * 3 = 6 3 * 3 = 9 |
| for (int i = 1; i <= 9; i++) { |
| for (int j = 1; j <= i; j++) { |
| printf("%d * %d = %d \t", j, i, (j * i)); |
| } |
| printf("\n"); |
| } |