叠甲:以下文章主要是依靠我的实际编码学习中总结出来的经验之谈,求逻辑自洽,不能百分百保证正确,有错误、未定义、不合适的内容请尽情指出!
文章目录
- 1.何为控制语句
- 2.控制语句-分支语句
- 2.1.if
- 2.2.switch
- 3.控制语句-循环语句
- 3.1.while
- 3.2.do...while
- 3.3.for
- 4.控制语句-转向语句
- 4.1.break
- 4.2.continue
- 4.3.goto
- 5.一些简单练习
- 5.1.倒计时关机程序
- 5.2.判断一个数是否为素数
- 5.3.计算 1!+2!+...+n! 的值
- 5.4.求解两个数的最小公倍数和最大公因数
- 5.4.1.公倍数和公因数概念
- 5.4.2.朴素求得最小公倍数
- 5.4.3.朴素求得最大公约数
- 5.4.4.LCM 和 GCD 的关系
- 5.4.5.使用辗转相除法解决
- 5.5.使用循环来清空缓冲区
- 5.6.简易二分法查找算法
1.何为控制语句
一份 C
代码由多种语句组合而成, C
的语句主要分为下面几种:
- 表达式语句
- 函数调用语句
- 控制语句
- 复合语句
- 空语句
我这里主要给您提及控制语句的相关语法,其他的语句的相关概念您可以简单使用 google/bing/chatGPT
查询一下…
C
语言是结构化的程序设计语言,而这些结构实际上是对现实生活中的一种抽象,基本所有要做的事情都会包含“顺序、选择、循环”结构。
因此映射到 C
语言中就对应了三种控制语句:
- 分支语句(
if、switch
) - 循环语句(
do...while、while、for
) - 跳转语句(
break、goto、continue、return
)
控制语句可以按照某种要求,跳转到对应的代码中进行执行。
在分支语句和循环语句中,依靠表达式的真假(零表示真,非零为假)来跳转代码决定执行哪些语句。但跳转语句则无需在意真假,是无条件的跳转代码。
另外,多种控制语句直接也可以互相嵌套使用,构成复杂的代码…
2.控制语句-分支语句
2.1.if
if
语句会分为单分支、双分支、多分支的情况,一个 if
语句可以被视为一个整体,经过逻辑判断后,只能选择执行其中一个分支的代码。
而所谓的逻辑判断就是指判断表达式内的真假,if
语句一旦遇到:
- 表达式的整体结果判定为假的时候,就会跳过跟在后面的代码块的所有内容,继续判断下一个表达式的真假
- 表达式的整体结果判定为真的时候,就会立刻执行后面跟着的代码块的内容,执行完后就抛弃其他分支的代码,也就执行完一条
if
语句
而表达式的真和假根据 零表示真,非零为假 来判断,例如:
- 对于代码
int num = 1; num + 3;
中num + 3
的整体结果就是真 - 对于代玛
int num = 3; 3 - num
中3 - num
的整体结果就是假 - 对于代码
int x = 9; int y; y = x;
中y = x
的整体结果就是真
//单分支语句的语法形式
if (表达式)
{语句0;
}
//双分支语句的语法形式
if (表达式)
{语句1;
}
else
{语法2;
}
//多分支语句的语法形式
if (表达式1)
{语句1;
}
else if (表达式2)
{语句2;
}
else if (表达式3)
{语句3;
}
//... 其他的 if 语句
else if (表达式n-1)
{语句n-1;
}
else
{ 语句n;
}
这里举一个简单的例子:当用户输入一个数字,程序可以通过 if
语句检查该数字是否为正数、负数、零,并给出相应的提示信息。
//if 语句的使用例子
#include <stdio.h>
int main()
{int num;printf("请输入一个整数: ");scanf("%d", &num);if (num > 0){printf("这是一个正数\n");}else if (num < 0){printf("这是一个负数\n");}else{printf("这是零\n");}return 0;
}
写双分支语句、多分支语句时,如果分支内只需要执行一条语句,则可以省略代码块 {}
,但是语句特别多的时候最好是要养成加上代码块 {}
的习惯。
//省略代码块
#include <stdio.h>
int main()
{int num;printf("请输入一个整数: ");scanf("%d", &num);if (num > 0)printf("这是一个正数\n");else if (num < 0)printf("这是一个负数\n");elseprintf("这是零\n");return 0;
}
补充:分支语句的书写习惯对比
//两种 if 书写习惯的对比 //代码1 if (表达式) {//代码块1 } else {//代码块2 }//代码2 if(表达式) {//代码块1 } else {//代码块2 }
代码1
和代码2
是写的较多两种形式,第一种强调是if
以及内容是一个整体、第二种强调语句的“块”状,两种写法都可以,凭您的美感而言。
警告:关于
==
的判断写法分支语句判断相等时最常见的错误就是将
==
写作=
,漏写一个等号带来的困扰有时是灾难性的(好在现代的编译器在很多情况下都会警告这一做法,不过您依然不能太过依赖这点)。//有错误的代码 int num = 0; if(num = 0) //这里原意是判断一个数是否为 0,但这里变成了赋值语句,把 num 又赋值为 0,导致表达式的判断结果为 0,也就是假,后续代码块将不会被执行... {printf("hehe\n"); }
而关于这种写法有一种典型的检错方法,就是把变量和常量判断反过来写。
//两种 == 的判断写法 //代码 1 int num = 1; if(num == 0) {printf("hehe\n"); }
//代码 2 int num = 1; if(0 == num) //这里把变量和常量反过来写了 {printf("hehe\n"); }
代码2
的写法会比较好一点,自带检错功能。假设num == 0
错写成了num = 0
,那么意义就不同了(相当于0
赋值给了num
),编译器不一定会报错,但是如果将0 == num
写成0 = num
,那么编译器就会报错,因为无法使用变量赋值给一个常量。不过这种方法也只能规避常量和变量的情况,无法规避变量和变量之间比较的情况。
警告:
if
和else
的就近对应原则(悬空else
)//有问题的代码 #include <stdio.h> int main() {int num1 = 0;int num2 = 1;if(num1 == 1) //第一个 ifif(num2 == 1) //第二个 ifprintf("hello");else //这个 else 故意不进行缩进printf("limou");return 0; }
实际上第二个
if
才是和else
对应的(这里是故意不缩进的),这里发现程序结果是什么都不打印。这就是没有加上“代码块”的后果,有可能造成和您内心所需不同的结果。但是如果加上代码块就会情况就好了一些。//没问题的代码 #include <stdio.h> int main() {int num1 = 0;int num2 = 1;if(num1 == 1) //第一个 if{if(num2 == 1) //第二个 if{printf("hello");}}else{printf("limou");}return 0; }
这样代码就会在第一个表达式判断为假时,执行
printf("limou");
从而打印"limou"
。因此加上代码块,一是增加代码可读性,二是减少逻辑错误。我个人推荐,就算是单分支语句也最好加上“代码块”,不要太过于省事。
2.2.switch
switch
语句的运行和 if
语句有些类似。
//switch 的语法形式
switch(整型表达式)
{case 值 1:语句 1;break;case 值 2:语句 2;break;case 值 3:语句 3;break;//...还可以添加更多个 case 语句case 值 n-1:语句 n-1;break;case 值 n:语句 n;break;default:语句;break;
}
- 当
整型表达式
的计算值和case
后的值相匹配时,就会执行case
后续的代码,直到遇到break
时才结束switch
语句 - 其中
default
子句是默认选项,当整型表达式
的结果均不满足值1~值n
时,就会执行default
后的语句 - 每条
switch
只能有一条default
子句,default
放在其他case
之前之后都可以,并没有顺序要求 - 最后一个
default
的break
不写也没有问题,当然最好还是加上为好,维护代码的时候可以减少bug
的产生
case
后面的多条语句可以不加大括号,当然最好还是写上,逻辑会更加清晰一些…
补充:
if
和switch
最大的差别在于if
可以范围判断,switch
是枚举判断。
注意一个上面细节 直到遇到 break 时才结束 switch 语句,这句话很值得琢磨,如果匹配到对应的 case
选项后没有遇到 break
怎么办?可以看看下面的的代码,当 b = 1 或 2
时都是输出 "hello 你好 default"
,当 b = 3 或 4
时都是输出 "你好 default"
//缺少 break 的 switch 语句
#include <stdio.h>
int main()
{int num = 0;scanf("%d", &num);switch (num){case 1:case 2:printf("hello ");case 3:case 4:printf("你好 ");default:printf("default");}return 0;
}
因此,可以利用这一特性来达到多种选择对应同一个结果的目的。
//多个 case 标签指向相同的语句块
#include <stdio.h>int main()
{int choice;//提示用户输入选择printf("请选择选项(1、2、3): ");scanf("%d", &choice);//使用switch语句根据用户的选择执行相应的操作switch(choice){case 1:case 2:case 3:{printf("您选择了选项 1 或 2 或 3\n");break;}case 4:{printf("您选择了选项 4\n");break;}default:{printf("无效的选项\n");break;}}return 0;
}
警告:在一个
case
结束时,忘记写break
语句也会引发一些逻辑错误,这种错误