分支和循环
文章目录
- 在C语言中,程序的执行流程并非总是按照代码的书写顺序来执行的。为了更加灵活地控制程序的执行流程,C语言提供了重要的结构:分支结构,循环结构,顺序结构。
- 我们可以用
if
,switch
实现分支结构,用for
,while
,do-while
实现循环结构
1.if
语句
1.1 if语句的基本语法形式:
if(表达式)
语句
表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行
(C语言中,0表示假,非0表示真)
#include <stdio.h>
int main() {
int number;
printf("请输入一个整数:");
scanf("%d", &number); // 读取用户输入的整数
if (number % 2 == 1) {
printf("%d 是奇数。\n", number);
}
return 0;
}
1.2 else
- else语句的基本语法形式:
if(表达式)
语句1
else
语句2
#include <stdio.h>
int main() {
int age;
printf("请输入年龄:");
scanf("%d", &age); // 读取用户输入的年龄
if (age >= 18) {
printf("成年\n");
} else {
printf("未成年\n");
}
return 0;
}
注意:
- 分支中包含多条语句时,就必须使用大括号
{}
将代码括起来; if
和else
语句默认都只控制一条语句
2.关系操作符
C语言中用于比较的表达式 称为 “关系表达式”。里面运用的运算符就称为“关系运算符”。
关系操作符包括:
小于(<) | 判断左边的操作数是否小于右边的操作数。 |
---|---|
大于(>) | 判断左边的操作数是否大于右边的操作数。 |
小于或等于(<=) | 判断左边的操作数是否小于或等于右边的操作数。 |
大于或等于(>=) | 判断左边的操作数是否大于或等于右边的操作数。 |
等于(==) | 判断两个操作数是否相等。 |
不等于(!=) | 判断两个操作数是否不相等。 |
- 关系表达式通常返回
0
或1
,表示真假 - 关系表达式常用于
if
,while
结构
值得注意的是:
1.在使用关系操作符时,需要注意操作数的类型和数据结构,以确保比较操作的有效性和正确性。同时,也要注意避免将赋值操作符(=)
与等于操作符(==)
混淆,以免导致逻辑错误。
2.多个关系运算符不易连用,因为这可能会导致一些意外的结果或逻辑错误。如果必须连续使用多个运算符时,则必须清楚运算符的优先级和结合性,以确保代码按照预期执行。
3. 条件操作符(三目运算符)
- 条件操作符(也称为三目运算符)在许多编程语言中都是一个非常有用的特性,它会根据某个条件的结果来返回两个值中的一个。
- 其基本的语法形式如下:
exp1 ? exp2 : exp3
计算逻辑:
- 如果
exp1
为真,则返回exp2
的值,即计算exp2
的结果是整个表达式的结果;
如果exp1
为假,则返回exp3
的值,即计算exp3
的结果是整个表达式子的结果 - 假设我们有一个简单的程序,它根据用户输入的分数来输出对应的等级。不使用三目运算符的形式如下:
#include <stdio.h>
int main() {
int score;
printf("请输入分数:");
scanf("%d", &score);
char grade;
if (score >= 90) {
grade = 'A';
} else {
grade = 'B'; // 这里为了简化,只考虑了A和B两种等级
}
printf("等级是:%c\n", grade);
return 0;
}
在这个例子中,我们使用了一个if-else
语句来判断分数并设置等级。现在,我们将使用三目运算符来简化这段代码:
#include <stdio.h>
int main() {
int score;
printf("请输入分数:");
scanf("%d", &score);
char grade = (score >= 90) ? 'A' : 'B'; // 使用三目运算符直接赋值
printf("等级是:%c\n", grade);
return 0;
}
4.逻辑操作符
- 逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。
• ! | 逻辑取反运算符(改变单个表达式的真假)。 |
---|---|
• && | 与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。 |
• || | 或运算符,就是或者的意思(两侧⾄少有⼀个表达式为真,则为真,否则为假)。 |
4.1逻辑取反运算符( !)
#include <stdio.h>
int main()
{
int flag = 0;
if(!flag)
{
printf("do something\n");
}
return 0;
}
如果 flag
为真, !flag
就是假,如果 flag
为假, !flag
就是真
所以上⾯的代码的意思就是 flag
为假,执行if
语句中的代码。
4.2与运算符( && )
4.3 或运算符( || )
a | b | a||b |
---|---|---|
非0 | 非0 | 1 |
非0 | 0 | 1 |
0 | 非0 | 1 |
0 | 0 | 0 |
4.4短路
- 逻辑与(&&)的短路行为
对于逻辑与运算符(&&),如果第一个操作数为假(即为0),则不会计算第二个操作数,因为无论第二个操作数的值是什么,整个表达式的结果都将是假。这是一种短路行为。
int a = 5, b = 0;
if (a > 0 && b > 0) {
printf("a 和 b 均为正数");
}
由于a
的值大于0
,但b
的值等于0
,所以第一个操作数为真,但第二个操作数为假。因此,整个表达式的结果将为假,第二个操作数不会被计算,也就不会执行printf
语句。
- 逻辑或(||)的短路行为
对于逻辑或运算符(||),如果第一个操作数为真(即非0),则不会计算第二个操作数,因为无论第二个操作数的值是什么,整个表达式的结果都将是真。这也是一种短路行为。
int a = 5, b = 0;
if (a > 0 || b > 0) {
printf("a 或 b 为正数.");
}
由于a
的值大于0
,所以第一个操作数为真。无论第二个操作数的值是什么,整个表达式的结果都将为真,因此第二个操作数不会被计算,也就不会执行printf
语句。
5.switch语句
- 除了if语句外,C语言还提供
switch
语句来实现分支结构。 switch
语句是一种特殊形式的if-else
语句,用于判断条件有多个结果的情况。它把多重else-if
语句改写成了更易用,可读性更好的形式;- switch语句的基本语法形式为:
switch (expression) {
case value1:
// 当expression的值等于value1时执行的代码
break;
case value2:
// 当expression的值等于value2时执行的代码
break;
case value3:
// 当expression的值等于value3时执行的代码
break;
default:
// 当expression的值不等于任何一个case时执行的代码
break;
}
switch语句的执行流程是:
- 首先计算
expression
的值, - 然后依次与每个
case
后的值进行比较, - 当找到匹配的值时,就执行对应的代码块,并通过
break
语句跳出switch
语句, - 如果没有找到匹配的值,则执行
default
代码块(如果有的话), - 最后结束
switch
语句。
5.switch
语句和if语句的比较
#include <stdio.h>
int main() {
int num = 2;
// 使用switch语句
switch (num) {
case 1:
printf("Number is 1\n");
break;
case 2:
printf("Number is 2\n");
break;
case 3:
printf("Number is 3\n");
break;
default:
printf("Number is not 1, 2, or 3\n");
break;
}
// 使用if语句
if (num == 1) {
printf("Number is 1\n");
} else if (num == 2) {
printf("Number is 2\n");
} else if (num == 3) {
printf("Number is 3\n");
} else {
printf("Number is not 1, 2, or 3\n");
}
return 0;
}
使用switch
语句时,可以直接根据num
的值进行匹配,并执行相应的代码块。而使用if
语句时,需要使用多个if-else
语句进行条件判断,每个条件都需要进行比较操作。
6.while
循环
while(表达式)
语句
#include <stdio.h>
int main() {
int i = 0;
while (i < 10) {
printf("%d\n", i);
i++;
}
return 0;
}
定义一个整数变量i
并初始化为0
。然后,我们使用while循环
来检查i是否小于10
。如果i
小于10
,我们就打印出i
的值,并将i
增加1
。这个过程会一直重复,直到i不再小于10
为止。因此,这个程序会打印出0到9
这十个数字。
7.for
循环
for循环的结构通常包括初始化、条件和迭代三个部分,它们一起控制循环的执行。
#include <stdio.h>
int main() {
int i;
// for循环的结构:初始化; 条件; 迭代
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
return 0;
}
- for循环的初始化部分i = 0将i设置为0。
- 接着,条件部分i < 10检查i是否小于10。
- 如果条件为真(即i小于10),则执行循环体内的代码块(在这个例子中是printf语句)。
- 然后,迭代部分i++将i的值增加1。这个过程会重复进行,直到i不再小于10为止。
- 因此,这个程序将打印出0到9这十个数字。
8.do-while循环
do
语句
while(表达式)
它与while
循环类似,但有一个重要的区别:do-while
循环至少会执行一次循环体,因为循环体是在检查条件之前执行的。这意味着即使初始条件不满足,do-while
循环体内的代码也会执行一次。之后,它会检查条件,如果条件为真,则继续执行循环体;如果条件为假,则循环终止。
#include <stdio.h>
int main() {
int i = 0;
do {
printf("%d\n", i);
i++;
} while (i < 10);
return 0;
}
- 定义一个整数变量i并初始化为0。
- 然后,使用do-while循环来打印i的值,并将i增加1。
- 与while循环不同的是,无论i的初始值是多少,循环体至少会执行一次。
- 因此,即使初始时i不小于10,程序仍然会打印出i的初始值,
- 然后因为条件不满足而退出循环。
9.break
和continue
语句
break
的作⽤是⽤于永久的终止循环,只要 break 被执行,直接就会跳出循环,继续往后执行。continue
的作用是跳过本次循环 continue 后边的代码,在 for 循环和while 循环中有所差异的
10.goto
语句
- C语言中的
goto
语句是一种无条件跳转语句,可以将程序的执行直接跳转到指定处,从而改变程序的执行顺序。
#include <stdio.h>
int main() {
int i = 0;
int sum = 0;
for (i = 0; i < 10; i++) {
sum += i;
if (i == 5) {
printf("在 i 等于 5 时跳出循环。\n");
goto end_loop; // 跳转到标记的位置
}
}
end_loop: // 标记的位置
printf("循环结束,sum 的值为: %d\n", sum);
return 0;
}
for
循环,用于计算 0 到 9 的整数和。- 当
i
等于 5 时,我们使用goto
语句跳转到标记为end_loop
的位置,从而提前结束循环。 - 然后,程序继续执行并打印
sum
的值。
10.随机数的生成
-
C语言中有一种函数叫rand函数,它可以生成随机数,原型如下:
int rand (void);
-
rand
函数会返回一个伪随机数,这个随机数的范围是0 ~ RAND_MAX之间,RAND_MAX取决于编译器,但大多数编译器上为32767. -
rand
函数的使用需要包含头文件<stdlib.h>
-
rand
函数生成的随机数是伪随机的,是通过某种算法生成的随机数,因为rand函数是对一个叫“种子”的基准数运算生成的随机数,所以我们只要让种子随时变化就可以生成随机数 -
所以C语言中提供了一个
srand
函数来初始化随机数的生成器
10.1 srand
函数
srand
函数,⽤来初始化随机数的生成器的,srand
的原型如下:
void srand (unsigned int seed);
为了确保每次生成的随机数序列都是不同的,程序在调用rand
函数之前会先调用srand
函数来设置随机数的种子。srand
函数的参数seed
决定了随机数的种子,只要种子不同,生成的随机数序列就会不同。这就意味着,只要给srand
函数的种子是随机的,rand
函数就能生成随机数。然而,这就产生了一个矛盾:在生成随机数时又需要一个随机数。
为了解决这个矛盾,可以使用当前的**系统时间**作为随机数的种子。由于系统时间是不断变化的,每次调用srand
函数时都会传入一个不同的种子,从而生成不同的随机数序列.
- 那我们要怎样用系统时间作为种子参数呢,那就涉及到
time
函数
10.2 time
函数
time函数的原型如下:
time_t time(time_t* timer);
timer
==NULL
时得到当前日历时间(从1970-01-01 00:00:00到现在的秒数),timer
=时间数值时,用于设置日历时间,time_t
是一个unsigned long
类型。如果timer
不为空,则返回值也存储在变量timer
中。time
函数使用时需要包含头文件<time.h>
总的来说,由于系统时间是不断变化的,每次调用srand
函数时都会传入一个不同的种子,从而生成不同的随机数序列。以下是一个示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
// 使用当前系统时间作为种子
srand(time(NULL));
// 生成随机数
for (int i = 0; i < 10; i++) {
int randNum = rand();
printf("%d\n", randNum);
}
return 0;
}
- 首先调用srand函数,传入time(NULL)作为种子,以使用当前系统时间初始化随机数生成器。
- 然后,使用for循环生成10个随机数,并使用printf函数将它们输出到控制台上。
- 以至于每次运行程序时,生成的随机数序列都会不同。