这篇笔记主要是介绍C语言中的第一个重点知识,流程控制,包括顺序、选择、循环等。阅读本文预计需要 30 分钟。
流程控制是我们学习C语言的第一个重点,也是我们看懂程序的第一步,学习这部分后一定要能够熟练地分析一个程序代码的执行顺序。郝斌老师视频中讲解的非常详细,而且通俗易懂,如果某一部分理解有问题,可以多去看几遍郝斌老师的视频。
流程控制是指程序代码的执行顺序。
流程控制基本分为顺序
、选择
、循环
三种,其中顺序
是最简单的,选择
和循环
复杂一些。
顺序执行指按代码的先后顺序依次执行。
例1 顺序执行
/*
时间:2020年2月21日10:00:07
目的:
测试顺序执行
*/
# include
int main(void)
{
printf("打印1\n");
printf("打印2\n");
printf("打印3\n");
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
打印1
打印2
打印3
--------------------------
*/
这里,代码依次打印1,2,3,就是按照顺序执行。顺序执行,比较好理解,这里不过多介绍。
选择执行指某些代码可能执行,也可能不执行。即有选择地去执行某些代码。
选择执行主要分为if
, if...else...
, if...else if...else...
, switch
几种情况。重点是掌握if
的相关用法,switch
了解即可。
格式:
if (表达式)
语句A;
功能:
如果表达式为真,则执行语句 A
,否则不执行语句 A
。
例2 if 的最简单用法
/*
时间:2020年2月19日17:04
目的:
测试if的最简单用法
总结:
1. if后的表示式如果为真,则执行if后的第一个语句。
2. if后的表示式如果为假,则不执行if后的第一个语句。
*/
# include
int main(void)
{
if (3 > 2) // 为真
printf("AAAA\n"); // 输出结果:AAAA
if (3) // 为真
printf("BBBB\n"); // 输出结果:BBBB
if (0) // 为假
printf("CCCC\n"); // 不会输出
if (0 == 0) // 为真
printf("DDDD\n"); // 输出结果:DDDD
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
AAAA
BBBB
DDDD
--------------------------
*/
关于 if
的使用一定要注意其作用范围
,if
默认只能控制一个语句
的执行或不执行,如果想控制多个语句的执行或不执行,那么就必须把这些语句用{}
括起来。
说明 1:
if (表达式)
语句A;
语句B;
解释:if
默认只能控制语句 A
的执行或者不执行,无法控制语句 B
的执行或不执行。即:语句B一定会执行
。所以这种时候,推荐写成如下格式,便于阅读:
if (表达式)
语句A;
语句B;
如果想要 if
同时控制语句 A
和语句 B
则需要把语句 A
和语句 B
用{}
括起来。
说明 2:
if (表达式)
{
语句A;
语句B;
}
解释:此时 if
可以控制语语句 A
和语句 B
。
格式:
if (表达式)
语句A;
else
语句B;
功能:
如果表达式为真,则执行语句 A
,否则执行语句 B
。
关于 if
和 else
的使用一定要注意其作用范围
,if
和 else
默认只能控制一个语句
的执行或不执行,如果想控制多个语句的执行或不执行,那么就必须把这些语句用{}
括起来。如:
格式:
if (表达式)
{
语句A;
语句B;
}
else
{
语句C;
语句D;
}
另外,else
前面必须有 if
成对,否则报错。
常见错误写法:
if (表达式)
语句A;
语句B;
else
语句C;
解释:这样写法是错误的,因为语句 B
把 else
和 if
隔断了,导致没有 if
和 else
成对,
这种写法等价于:
if (表达式)
语句A;
语句B;
else
语句C;
例3 if…else…的用法:
/*
时间:2020年2月19日 17:33
目的:
测试if...else...的用法
总结:
1. if和else默认只能控制一个语句的执行或不执行。
2. if和else要控制多个语句,则用{}把多个语句括起来。
3. 注意非if和else控制的语句不要缩进。
*/
# include
int main(void)
{
int i, j;
scanf("%d %d", &i, &j); // 接受输入
if (i > j)
printf("i大于j\n");
else
printf("i小于j\n");
printf("\n"); // 打印空行
if (1 > 2)
printf("AAAA\n");
// printf("哈哈哈哈\n"); // 加了这行会报错,导致30行的 else 没有 if 配对
else
printf("BBBB\n");
printf("CCCC\n"); // 注意代码规范,这行代码不要缩进
return 0;
}
/*
在VSCode中的输入输出结果是:
--------------------------
1 2
i小于j
BBBB
CCCC
--------------------------
*/
格式:
if (表达式1)
语句A;
else if (表达式2)
语句B;
else if (表达式3)
语句C;
else:
语句D;
功能:
如果表达式1成立,则执行语句 A
;如果表达式2成立,则执行语句 B
;如果表达式3成立,则执行语句 C
;否则执行语句 D
。
关于 if
、 else if
、else
的使用一定要注意其作用范围
,if
、 else if
、else
默认只能控制一个语句
的执行或不执行,如果想控制多个语句的执行或不执行,那么就必须把这些语句用{}
括起来。
这里的注意事项和常见错误同 if...else...
,不再赘述。
例4 if…else if…else…的用法
/*
时间:2020年2月19日 17:57
目的:
测试if...else if...else的用法
总结:
1. 注意if...else if ...else必须成对出现
2. 警惕if...else if...else的作用范围导致的错误
*/
# include
int main(void)
{
double delta = 3;
if (delta > 0)
printf("有两个解!\n");
// printf("哈哈!\n"); // 加了这句会报错,导致后面的else if语法错误
else if (delta == 0)
printf("有一个唯一解!\n");
else
printf("无解!\n");
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
有两个解!
--------------------------
*/
1. 空语句问题
if (3 > 2);
等价于
if (3 > 2)
; // 这是一个空语句
2. if...else...
if (表达式)
语句A;
else:
语句B;
这是正确的。
而:
if (表达式); // 这里多了个 ';',形成了空语句
语句A;
else // 这个 else 没有 if 配对
语句B;
是错误的。
3. if...else if...else
if (表达式1)
语句A;
else if (表达式2)
语句B;
else if (表达式3)
语句C;
else
语句D;
即便表达式1/2/3都成立,也只会执行A语句.
4. if...else if...
if (表达式1)
语句A;
else if (表达式2)
语句B;
else if (表达式3)
语句C;
这么写语法没有错,但是逻辑上有漏洞。
5. if...else if...else
if (表达式1)
语句A;
else if (表达式2)
语句B;
else if (表达式3)
语句C;
else (表达式4) // 7行
语句D;
这样写是错误的,正确的写法是:
要么去掉7行的(表达式4);要么在7行的 else 后面加 if 。
6. if...else if...else
if (表达式1)
语句A;
else if (表达式2)
语句B;
else if (表达式3)
语句C;
else (表达式4); // 注意这里有个 ; ,跟5不一样
语句D;
这样写语法不会出错,但逻辑上是错误的。
else (表达式4);
语句D;
等价于
else
(表达式4);
语句D;
格式:
switch (表达式)
{
case 常量表达式1: 语句1;
case 常量表达式2: 语句2;
default: 语句3;
case 常量表达式3: 语句4;
}
说明:
所有 case
后面的常量表达式,为便于描述我们姑且称之为标签,这些标签都只能是:1)枚举常量(有些书称之为枚举元素);2)数值常量;3)字符常量;4)常变量;5)宏名中的一种,注意普通变量,枚举变量是不能作为标签使用的。
switch
后面括号里的表达式允许是任何类型。
执行完一个case语句后,流程控制就转移到下一个case子句继续执行,"case"常量表达式只是起语句标号的作用,并不是在该处进行条件判断。在执行switch语句时,根据switch()中的表达式的值找到与之匹配的case子句,就从此case子句开始执行下去,不再进行判断。即找到程序执行的入口后,就顺序执行剩下的代码
。
switch
是选择不是循环,如果在 switch
中出现了 break
语句。该语句的功能知识退出 switch
语句转去执行它下面的语句。在 switch
中出现 continue
是错误的,除非 switch
本身就属于 for
或 while
循环的一部分。
例5 switch
的用法
/*
时间:2020年2月20日15:13:55
功能:
测试switch的用法,电梯程序
总结:
1. switch就是找程序的入口,找到后就顺序执行剩余的代码。
*/
# include
int main(void)
{
int val;
printf("请输入您要进入的楼层:");
scanf("%d", &val);
switch (val)
{
case 1:
printf("1层开!\n");
// break;
case 2:
printf("2层开!\n");
// break;
case 3:
printf("3层开!\n");
// break;
default:
printf("还没有盖到这一层!\n");
}
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
请输入您要进入的楼层:1
1层开!
2层开!
3层开!
还没有盖到这一层!
--------------------------
*/
循环是指某些代码会被重复执行。循环的创造是为了把一些规律性的操作,通过几行循环代码解决,避免我们输入冗余的代码,提升开发效率,使得代码更加简洁。
循环语句主要有 for
、while
、do...while
,三种,其中 for
和 while
是用的最多的,do...while
主要用于人机交互。
for
和 while
可能一次循环都不执行,而do...while
至少执行一次循环。
格式:
for (1; 2; 3)
A;
功能:
先执行 1 ,然后执行条件判断语句 2。如果 2 成立,则依次执行语句 A
和 3
,再执行2,以此循环。如果 2 不成立,则循环结束,不再继续执行 A
和 3
。注意:1 永远只执行一次。
例6 单个 for 循环的用法
/*
时间:2020年2月20日09:48:37
功能:
for循环求1-100之间所有奇数之和
总结:
1. for 的默认作用范围是一个语句。
2. for 作用于多个语句,需要使用 {} 把多个语句括起来
*/
# include
int main(void)
{
int i;
int sum = 0;
for (i=1; i<100; i+=2) // i+=2 等价于 i = i + 2
{
sum += i; // 等价于 sum = sum + i;
}
printf("i = %d, sum = %d\n", i, sum);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
i = 101, sum = 2500
--------------------------
*/
关于单个 for
的使用也一定要注意其作用范围
,for
默认只能控制一个语句
的循环或不循环,如果想控制多个语句的循环或不循环,那么就必须把这些语句用{}
括起来。
这里的注意事项和常见错误同 if
类似,不再赘述。
格式 1:
for (1; 2; 3) // 1
for (4; 5; 6) // 2
A; // 3
B; // 4
功能:
多个 for 循环嵌套,从最外面的循环开始执行,先执行 1 ,再执行条件判断语句 2。如果 2 成立,则依次执行语句 4 和 5,如果 5 成立 则执行 A和 6,如果 5不成立,则结束第二个 for 循环,去执行3,再执行2,以此循环。直到 2 为假时,结束循环。(这里有点绕,详细的请看郝斌老师视频,讲解非常细)
这里整体算两个语句,1 2 3 行是第一个语句,4 行是第2个语句。
格式 2:
for (1; 2; 3)
for (4; 5; 6)
{
A;
B;
}
整体是一个语句。可能执行顺序:1 2 4 5 A B 6 5 3 2 (每个循环只执行一次)
格式 3:
for (1; 2; 3)
for (4; 5; 6)
{
A;
B;
for (7; 8; 9)
C;
}
整体是一个语句。可能执行顺序:1 2 4 5 A B 7 8 C 9 8 6 5 3 2 (每个循环只执行一次)
关于多个 for
的嵌套使用更要注意其作用范围
,for
默认只能控制一个语句
的循环或不循环,如果想控制多个语句的循环或不循环,那么就必须把这些语句用{}
括起来,推荐一个语句也用花括号{}
。
例7 多个 for 循环的嵌套的用法
/*
时间:2020年2月20日12:55:12
目的:
多个for嵌套使用案例
总结:
1. 多个 for 嵌套注意范围问题
*/
# include
int main(void)
{
int i, j;
for (i=0; i<3; ++i)
// printf("嘿嘿!\n"); // 例子2
for (j=2; j<5; ++j)
printf("哈哈!\n");
// printf("嘻嘻!\n"); // 不推荐这么写
printf("嘻嘻!\n"); // 推荐
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
嘻嘻!
--------------------------
*/
for 和 if 可以组合使用。
例8 for 和 if 嵌套的用法
/*
时间:2020年2月20日10:52:45
功能:
求1-100之间的奇数之和
求1-100之间的奇数个数
求1-100之间的奇数平均值
求1-100之间的奇数之和,再求1-100之间的偶数之和
*/
# include
int main(void)
{
int i; // 循环变量
int sum_odd = 0; // 奇数之和
int sum_even = 0; // 偶数之和
int cnt = 0; // 奇数的个数,个数一般用cnt表示
float average_odd = 0; // 奇数的平均值
for (i=1; i<=100; ++i)
{
if (i%2 == 0)
{
sum_even += i; // 等价于 sum_even = sum_even + i;
}
else
{
sum_odd += i; // 等价于 sum_odd = sum_odd + i;
++ cnt; // 等价于 cnt = cnt + 1;
}
}
average_odd = 1.0*sum_odd / cnt; // 推荐这么写,1.0 默认是double类型
// average_odd = sum_odd / (float)(cnt); // 不推荐这么写
printf("1-100之间的奇数之和是:%d\n", sum_odd);
printf("1-100之间的奇数个数是:%d\n", cnt);
printf("1-100之间的奇数平均值:%f\n", average_odd); // 这里是%f
printf("1-100之间的奇数之和是:%d, 偶数之和是:%d\n", sum_odd, sum_even);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
1-100之间的奇数之和是:2500
1-100之间的奇数个数是:50
1-100之间的奇数平均值:50.000000
1-100之间的奇数之和是:2500, 偶数之和是:2550
--------------------------
*/
while和for可以相互转换,但for逻辑性更强,更不容易出错,推荐多使用for。
格式:
while (表达式)
A;
功能:
表达式为真时,执行语句 A, 直到表达式为假,结束循环。
while 和 for 互换,如下:
for (1; 2; 3)
A;
等价于
1;
while (2)
{
A;
3;
}
关于 while
的使用也要注意其作用范围
,while
默认只能控制一个语句
的循环或不循环,如果想控制多个语句的循环或不循环,那么就必须把这些语句用{}
括起来,推荐一个语句也用花括号{}
。
例9 while Vs for
循环的用法
/*
时间:2020年2月20日13:41:31
功能:
求 1 + 2 + 3 + ... + 100 的和
目的:
比较 for 和 while 的异同
总结:
1. for和while可以互相转换。
2. for逻辑性更强,更不易出错,推荐使用。
*/
# include
int main(void)
{
int i;
int j;
int sum_1 = 0; // for求和
int sum_2 = 0; // while求和
for (i=1; i<101; ++i)
{
sum_1 += i;
}
printf("sum_1 = %d\n", sum_1);
j = 1;
while (j<101)
{
sum_2 += j;
++j;
}
printf("sum_2 = %d\n", sum_2);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
sum_1 = 5050
sum_2 = 5050
--------------------------
*/
do...while
循环格式:
do
{
A;
B;
} while (表达式)
功能:
先执行 do {}
中的语句 A
和 B
,再执行 while
表达式,如果表达式成立,则继续执行 do {}
,否则结束循环,即循环体至少会执行 1 次。
while
循环格式:
while (表达式)
{
A;
B;
}
for
循环格式:
for (1; 2; 3)
{
A;
B;
}
注意:do...while
并不等价于 for
,当然也不等价于 while
。
主要是用于人机交互。
例10 do...while
循环的用法
/*
时间:2020年2月20日14:48:36
功能:
用 do...while 实现一元二次方程
总结:
1. do...while主要是便于人机交互。
2. do...while至少会执行一次循环,while和for可能一次循环都不执行。
3. scanf()输入%c时,一定要在%c前保留一个空格
*/
#include
#include
int main(void)
{
double a, b, c;
double delta;
double x1, x2;
char ch;
do
{
printf("请输入一元二次方程的三个系数:\n");
printf("a = ");
scanf("%lf", &a);
printf("b = ");
scanf("%lf", &b);
printf("c = ");
scanf("%lf", &c);
delta = b * b - 4 * a * c;
if (delta > 0)
{
x1 = (-b + sqrt(delta)) / (2 * a);
x2 = (-b - sqrt(delta)) / (2 * a);
printf("该一元二次方程有两个解,x1 = %lf,x2 = %lf\n", x1, x2);
}
else if (delta == 0)
{
x1 = x2 = (-b) / (2 * a);
printf("该一元二次方程有唯一解,x1 = x2 = %lf\n", x1, x2);
}
else
{
printf("该一元二次方程无实数解!\n");
}
printf("您想继续吗(Y/N):");
scanf(" %c", &ch); // %c前面必须得加一个空格 原因略
// scanf("%c", &ch); // 错误写法,程序直接跳出循环
} while ('Y'==ch || 'y'==ch);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
请输入一元二次方程的三个系数:
a = 1
b = 2
c = 3
该一元二次方程无实数解!
您想继续吗(Y/N):y
请输入一元二次方程的三个系数:
a = 3
b = 4
c = 5
该一元二次方程无实数解!
您想继续吗(Y/N):N
--------------------------
*/
break
有 3 种用法:
break
如果用于循环是用来终止循环,并且是距离它最近的一个循环。
break
如果用于switch,则是用来终止switch。
break
不能直接用于if,除非if属于循环内部的一个子句。
这里主要放出一些 break
使用情况的代码片段:
例11 break
的用法1
/*
时间:2020年2月20日16:27:18
目的:
测试 break 的用法
总结:
break 只能终止距离它最近的循环
*/
# include
int main(void)
{
int i, j;
for (i=0; i<3; ++i) // 第 1 个 for 循环
{
for (j=1; j<4; ++j) // 第 2 个 for 循环
break; // break 只能终止距离它最近的循环,即 第 2 个 for
printf("同志们好!\n");
}
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
同志们好!
同志们好!
同志们好!
--------------------------
*/
例12 break
的用法2
/*
时间:2020年2月20日16:43:56
目的:
测试 break 在多层嵌套 switch 中的用法
总结:
1. 在多层switch嵌套中,break 只能够终止距离它最近的switch。
*/
# include
int main(void)
{
int x=1, y=0, a=0, b=0;
switch(x) // 第一个 switch
{
case 1:
switch(y) // 第二个switch
{
case 0:
a++;
break; // 终止的是第二个switch
case 1:
b++;
break; // 终止的是第二个switch
}
b = 100;
break; // 终止的是第一个switch
case 2:
a++;
b++;
break; // 终止的是第一个switch
}
printf("a = %d, b = %d\n", a, b);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
a = 1, b = 100
--------------------------
*/
例13 break
的用法3
/*
时间:2020年2月20日16:16:26
目的:
测试 break 的用法
总结:
break 虽然是if内部的语句,但break终止的的确是外部的for循环
*/
#include
int main(void)
{
int i;
switch (2)
{
case 2:
printf("哈哈!\n");
break; // OK,break 可以用于switch
default:
break;
}
for (i = 0; i < 3; ++i)
{
if (3 > 2)
break; // break 虽然是if内部的语句,但break终止的的确是外部的for循环
printf("嘿嘿!\n"); // 永远不会输出
}
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
哈哈!
--------------------------
*/
用于跳过本次循环余下的语句,转去判断是否需要执行下次循环。
continue
在 for
循环中的使用: for (1; 2; 3)
{
A;
B;
continue; // 如果执行该语句,则执行完该语句后,会执行语句3,跳过 C 和 D
C;
D;
}
如果执行 continue
,则执行完 continue
后,会执行语句 3 ,跳过 C 和 D,去执行 3 和 2。
continue
在 while
循环中的使用 while (表达式)
{
A;
B;
continue; // 如果执行该语句,则执行完该语句后,会执行表达式,跳过 C 和 D
C;
D;
}
如果执行 continue
,则执行完 continue
后,会执行语句 3 ,跳过 C 和 D,去执行表达式。
非 0 是真
0 就是假
真用 1 表示
假用 0 表示
这也是刷算法题的心得。
尝试自己去编程解决它,但要意识到大部分人都是自己无法解决的,这时不要气馁,如果10分钟还想不出来,就看答案。
如果解决不了,就看答案。关键是把答案看懂,这个要花很大精力,也是我们学习的重点。看懂一个程序要分三步:流程、每个语句的功能、试数。
看懂之后尝试自己去修改程序,并且知道修改之后程序的输出结果的含义。
不建议看懂程序之后就立即自己敲程序。
照着答案去敲。
调试错误。
不看答案,自己独立把答案敲出来。
如果程序实在无法彻底理解,就把它背会,这种情况极少见。
进制目前需要弄懂以下四个问题:
什么叫n进制?即:逢n进一。
把r进制转成十进制。即:从左到右依次把数字乘以r对应的幂指数。
十进制转成r进制。方法:除r取余,直至商0,余数倒序排列。
不同进制所代表的的数值之间的关系。十进制的 3981
转化为十六进制是 F8D
。十进制的 3981
和 十六进制的 F8D
所代表的本质上都是同一个数
。
运算符 | 表达式 | 说明 |
---|---|---|
前自增 | ++i | 使得变量 i 的值 +1 |
后自增 | i++ | 使得变量 i 的值 +1 |
前自减 | –i | 使得变量 i 的值 -1 |
后自减 | i– | 使得变量 i 的值 -1 |
三目运算符 | i = A ? B : C | 若 A 真,则 i = B; 否则 i = C |
逗号表达式 | (A, B, C, D) | i = (3, 2, 5, 6); i 最后等于 6 |
设计自增和自减的可能原因:
代码更加精炼。
自增的速度更快。
比较前后自增的异同
前自增 | 后自增 | |
---|---|---|
表达式 | ++i | –i |
相同 | 都使 i 的值 +1 | 都使 i 的值 +1 |
不同 | ++i 整体表达式的值是i加1之后的值 | i++ 后自增整体表达式的值是i加1之前的值 |
学习自增要明白的几个问题:
编程时应该尽量不要体现自增和自减的区别。或者说编程时尽量屏蔽掉前后自增和自减的差别。
i++ 和 ++i 单独成一个语句,不要把它作为一个完成复合语句的一部分来使用。或者说,自增表达式最好不要作为一个更大的表达式的一部分来使用。
如:写成 int m = i++ + ++i + i + i++;
这么写,不但是不规范的代码,而且是不可移植的代码。不可移植是因为,不同机器上对于这个语句的执行顺序有区别。顺序点有三个 ,
和 ()
以及 ;
。 printf("%d %d %d", i++, ++i, i);
也是不推荐,原因同上。
例14 前后自增的用法
/*
时间:2020年2月20日12:22:24
目的:
前后自增的异同
总结:
前自增和后自增的异同:
相同:
最终都是使i的值加1.
不同:
前自增整体表达式的值是i加1之后的值。
后自增整体表达式的值是i加1之前的值。
*/
# include
int main(void)
{
int i, j, k, m;
i = j = 3; // 等价于 i = 3; j = 3;
k = i++;
m = ++j;
printf("i = %d, j = %d, k = %d, m = %d\n", i, j, k, m);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
i = 4, j = 4, k = 3, m = 4
--------------------------
*/
自减同自增,不再赘述。
格式:
A ? B : C
等价于
if (A)
B;
else
C;
功能:
如果 A 为真,则执行 B ,否则执行 C。
例15 三目运算符的用法
/*
时间:2020年2月20日12:39:31
目的:
测试三目运算符
总结:
A ? B : C
等价于
if (A)
B;
else
C;
*/
# include
int main(void)
{
int i;
i = (3>2 ? 5 : 1);
printf("i = %d\n", i);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
i = 5
--------------------------
*/
格式:
(A, B, C, D)
功能:
从左到右执行,最终表达式的值是最后一项的值。
例16 逗号表达式的用法
/*
时间:2020年2月20日12:44:01
目的:
测试逗号表达式用法
总结:
1. 从左到右执行,最终表达式的值是最后一项的值。
*/
# include
int main(void)
{
int i;
int j = 2;
i = (3, 2, 5, 6);
printf("i = %d\n", i);
i = (j++, ++j, j+2, j-3); // 不要这么写,这里是为了测试
printf("i = %d\n", i);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
i = 6
i = 1
--------------------------
*/
格式:
(数据类型)(表达式)
功能:
把表达式的值强制转化为前面所执行的数据类型。
如:
表达式 | 结果 |
---|---|
(int)(4.5+2.2) | 6 |
(float)(5) | 5.000000 |
能不用强制类型转换就不用,使用灵活的方法替换。
例17 强制类型转换的用法
/*
2020年2月20日10:13:40
功能:
求1 + 1/2 + 1/3 + ... + 1/100之和
总结:
1. 能不用强制类型转换就不用,使用灵活的方法替换
*/
# include
int main(void)
{
int i;
float sum = 0;
for (i=1; i<=100; ++i)
{
sum = sum + 1.0/i; // 是OK的,推荐使用
// sum = sum + (float)(1/i); // 这样写是不对的
// sum = sum + 1 / (float)(i); // 这样写也可以,不过不推荐使用
}
printf("sum = %f\n", sum); // float 必须用%f输出
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
sum = 5.187378
--------------------------
*/
原则:把自己当计算机,严格按照计算机的顺序执行。也可以通过断点调试,一步一步看程序执行的过程。
float
和 double
都不能保证可以精确地存储一个小数。
题目:有一个浮点型的变量x,如何判断x的值是否是0.
// 解法一,这是伪代码
if (0 == x)
是0
else
不是0
// 这种解法是错误的
// 解法二,这是伪代码
if (|x-0.000001| <= 0.000001)
是0
else
不是0
// 这种解法才是正确
另外,循环更新的变量不能定义为浮点型,以免发生不可预测的错误。
例18 循环更新变量的错误用法
/*
时间:2020年2月20日10:48:42
总结:
1. 本程序不对,因为循环中更新的变量不能定义为浮点型
*/
# include
int main(void)
{
float i;
float sum = 0;
for (i=1.0; i<=100; ++i)
{
sum = sum + 1/i;
}
printf("sum = %f\n", sum);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
sum = 5.187378
--------------------------
*/
【说明】
本学习笔记整理自B站郝斌老师的《郝斌C语言自学教程》片段P47-P96。
笔记中所有代码均在windows10操作系统,在VSCode编辑器中通过测试。具体VSCode C语言开发环境搭建方法请参照我的另一篇CSDN博客——Windows10下利用Visual Studio Code搭建C语言开发环境。
如果对你有所帮助,欢迎关注我的这个公众号。这个公众号主要是慢慢分享和记录自己学习编程的笔记,比如:C,Python,Java等,后续也会分享自己面试以及在职场上的成长心得。