C语言学习-分支循环

                C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构,我们生活中几乎所有事情,比如做饭、打车、网购,都能拆解成这三种基本操作的组合。

        我们可以使用if、switch实现分支,使用for、while、do while实现循环

1、if语句

1.1、if

        if 语句的语法形式如下:

if(/*表达式*/)
    语句

        若表达式为真,则执行语句;若为假,则不执行。

        在C语言中,0表示假,非0值表示真。当表达式结果为0时,语句不会执行;若结果为非0,则语句将被执行。

#include <stdio.h>

int main() {
    int num;
    printf("请输入一个整数: ");
    scanf("%d", &num);

    if (num % 2 != 0) {
        printf("%d 是奇数\n", num);
    }
    return 0;
}
 

        假设用户输入数字5,程序将输出:

5 是奇数
 

        代码流程图如下:

1.2、else

        如果一个数,不是奇数,那就是偶数了,这里就需要if...else..语句了:

if (/*表达式*/)
    //语句1  
else
    //语句2
 
#include <stdio.h>

int main() {
    int num;
    printf("请输入一个整数: ");
    scanf("%d", &num);

    if (num % 2 != 0) {
        printf("%d 是奇数\n", num);
    } else {
        printf("%d 是偶数\n", num);
    }

    return 0;
}
 
4 是偶数
 

        小练习:写一个C语言代码,输入一个年龄,>=18岁就输出:成年,否则就输出:未成年

#include <stdio.h>

int main() {
    int age;
    printf("请输入年龄:");
    scanf("%d", &age);

    if (age >= 18) {
        printf("成年\n");
    } else {
        printf("未成年\n");
    }

    return 0;
}
 
1.3、分支中包含多条语句

        if...else语句中,默认只控制一条语句,例如:

#include <stdio.h>

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
		printf("成年了\n");
		printf("上大学了");
	return 0;
}

        我们发现,无论我们输入小于18的数字还是输入大于18的数字,控制台都会打印出“上大学了”,因为if默认只是控制一条语句,如果为真就打印“成年了”,如果为假就不打印,而printf("上大学了");是独立存在的,不管if是真是假都会执行!!!如果if要控制多个语句则要加上{ }将代码区域括起来,else同理。

#include <stdio.h>

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
    {
		printf("成年了\n");
		printf("上大学了");
    }
    else{
        printf("未成年\n")
    }
	return 0;
}
1.4、嵌套if

        在if..else...语句中,else可以和另一个if搭配,构成多重判断:

#include <stdio.h>

int main() {
    int num;
    printf("请输入一个整数: ");
    scanf("%d", &num);

    if (num > 0) {
        printf("输入的是正数\n");
    } else if (num < 0) {//这⾥的if 相当于嵌套在els语句中,形成了嵌套结构
        printf("输入的是负数\n");
    } else {
        printf("输入的是0\n");
    }

    return 0;
}
 

1.5、悬空else问题

        如果有多个if..else...,else只跟距离他最近的if匹配:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}

        当你运行代码的时候会发现什么也没有输出,如果我们希望else和第一个if进行匹配,那么可以加上大括号:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
	{
		if (b == 2)
			printf("hehe\n");
	}	
	else
	{
		printf("haha\n");
	}
		
	return 0;
}

2、关系操作符

        C语言⽤于比较的表达式,称为“关系表达式”(relationalexpression),里面使用的运算符就称 为“关系运算符”(relationaloperator),主要有下面6个。

2.1、关系运算符列表

        C语言中的关系运算符用于比较两个值的大小或相等性,返回结果为布尔值(1表示真,0表示假)。以下是6个基本的关系运算符:

  • :大于。例如 a > b,若a的值大于b,则返回1,否则返回0
  • :小于。例如 a < b,若a的值小于b,则返回1,否则返回0
  • >= :大于等于。例如 a >= b,若a的值大于或等于b,则返回1,否则返回0
  • <= :小于等于。例如 a <= b,若a的值小于或等于b,则返回1,否则返回0
  • == :等于。例如 a == b,若a的值等于b,则返回1,否则返回0
  • != :不等于。例如 a != b,若a的值不等于b,则返回1,否则返回0
2.2、使用示例
#include <stdio.h>

int main() {
    int a = 5, b = 3;
    printf("a > b: %d\n", a > b);   // 输出 1
    printf("a < b: %d\n", a < b);   // 输出 0
    printf("a == b: %d\n", a == b); // 输出 0
    return 0;
}

2.3、注意事项
  1. 区分 和 == 是赋值运算符,== 是关系运算符。混淆两者会导致逻辑错误。
  2. 浮点数比较:由于浮点数精度问题,直接使用==比较可能不准确,通常用绝对值差小于某个极小值(如1e-9)代替。
float x = 0.1 + 0.2;
if (fabs(x - 0.3) < 1e-9) { /* 视为相等 */ }
2.4、代码解释
  1. float x = 0.1 + 0.2; 在数学上应该等于0.3,但由于浮点数的存储特性,实际结果可能是类似0.30000000000000004的值。
  2. if (fabs(x - 0.3) < 1e-9) 使用极小的容差(10^-9)来判断两个浮点数是否"相等"。fabs()计算绝对差值,当差值小于阈值时认为两者相等。
2.5、运算符优先级

        关系运算符的优先级低于算术运算符(如+*),但高于赋值运算符(如=)。例如:

int result = 5 + 3 < 10; // 等价于 (5 + 3) < 10,结果为1

3、条件操作符

        条件操作符也叫三目操作符,需要接受三个操作数的,形式如下:

exep1 ? exp2 : exp3
 

        条件操作符的计算逻辑是:如果 exp1 为真, exp2 计算,计算的结果是整个表达式的结果;如果exp1为假exp3 计算,计算的结果是整个表达式的结果。

int a = 5, b = 10;
int max = (a > b) ? a : b; // max的值为10
 
#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    
    if (a > 5)
        b = 3;
    else
        b = -3;
    
    printf("%d\n", b);
    return 0;
}
 

        改进后:

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    
    b = (a > 5) ? 3 : -3;
    
    printf("%d\n", b);
    return 0;
}
 

4、逻辑操作符

4.1、逻辑与 &&
  • 功能:当且仅当两个操作数均为非零(真)时,结果为真(1);否则为假(0)。
  • 示例
    int a = 5, b = 3;
    if (a > 0 && b > 0) {
        // 条件成立,执行此处代码
    }
    
4.2、逻辑或 ||
  • 功能:若任意一个操作数为非零(真),结果为真(1);仅当两者均为零(假)时结果为假(0)。
  • 示例
    int x = 0, y = 2;
    if (x > 0 || y > 0) {
        // 条件成立(y为真),执行此处代码
    }
    
4.3、逻辑非 !
  • 功能:对操作数取反。若操作数为非零(真),结果为假(0);若操作数为零(假),结果为真(1)。
  • 示例
    int flag = 0;
    if (!flag) {
        // flag为假,取反后条件成立,执行此处代码
    }
    
4.4、注意事项
  • 短路求值&&|| 会从左至右计算,若左操作数已能确定结果,右操作数不会被计算。
    int *ptr = NULL;
    if (ptr != NULL && *ptr == 10) { // 避免解引用空指针
        // 安全操作
    }
    

        阅读下面代码,判断结果:

#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	//i = a++||++b||d++;
	printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
	return 0;
}

4.4、闰年判断练习

     闰年判断的规则:

  1. 能被4整除并且不能被100整除是闰年
  2. 能被400整除是闰年
#include <stdio.h>

int main() {
    int year = 0;
    scanf("%d", &year);
    
    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
        printf("是闰年\n");
    } else {
        printf("不是闰年\n");
    }
    
    return 0;
}
 

5、switch语句

        除了if,在C语言中switch也能实现分支运算。switch的基本语法如下:

switch (表达式) {
    case 常量1:
        语句块1;
        break;
    case 常量2:
        语句块2;
        break;
    // 更多case...
    default:
        默认语句块;
}
 

        注意:switch后面的表达式必须是整型表达式,case后面的值必须是整型常量表达式。

5.1、if和switch的对比

        例子,判断一个数是多少,if和switch的对比:

#include <stdio.h>

int main() {
    int num = 2;

    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;
}
 
#include <stdio.h>

int main() {
    int num = 2;

    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");
    }
    return 0;
}
 

上述的代码中有几点需要注意:

  1. case后面必须要跟空格
  2. 每一个case后面的代码块执行完后,需要break才能跳出switch语句,否则会发生击穿现象!
5.2、switch中的break

        switch语句的执行逻辑是依次匹配case标签,一旦匹配成功,会从该标签处开始执行,直到遇到break或switch语句结束。若未显式添加break,编译器不会自动插入终止逻辑,导致代码继续向下执行。

switch (value) {
    case 1:
        printf("Case 1\n");
        // 无break,发生击穿
    case 2:
        printf("Case 2\n");
        break;
    default:
        printf("Default\n");
}
 

        若value为1,输出:

Case 1
Case 2
 

        若value为2,仅输出:

Case 2
 

        那是不是击穿现象就没有用了呢?不是的,某些情况下击穿现象可以简化代码结构:

例子:输入个1~7的数字,打印对应的星期几:

#include <stdio.h>
int main()
{
    int day = 0;
    scanf("%d", &day);
    switch(day)
    {
        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("输入错误,请输入1-7的数字\n");
    }
    return 0;
}
 

如果需求发生变化,变为:

  1. 输入1-5,输出的是“工作日”;
  2. 输入6-7,输出“休息日”
#include <stdio.h>

int main() {
    int day = 0;
    printf("请输入数字1-7: ");
    scanf("%d", &day);
    switch(day) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            printf("工作日\n");
            break;
        case 6:
        case 7:
            printf("休息日\n");
            break;
    }
    return 0;
}
 

        由此可见,我们可以根据实际需求来自行选择是否利用击穿现象。

5.3、switch语句中的default

        当switch表达式的值不匹配任何case时,执行default下的代码块。

#include <stdio.h>

int main() {
    int day = 0;
    printf("请输入数字1-7: ");
    scanf("%d", &day);
    switch(day) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            printf("工作日\n");
            break;
        case 6:
        case 7:
            printf("休息日\n");
            break;
        default:
            printf("输入无效,请输入1-7的数字\n");
    }
    return 0;
}
 

6、while循环

while (condition) {
    // 循环体
}
 
6.1、while语句的执行流程

while循环的执行步骤

  1. 计算condition(判断表达式)的值。
  2. 如果condition为真,执行循环体内的代码,然后回到步骤1。
  3. 如果condition为假,跳过循环体,继续执行循环之后的代码。
6.2、while循环的实践

在屏幕上打印1-10:

#include <stdio.h>

int main() {
    int i = 1;
    while (i <= 10) {
        printf("%d\n", i);
        i++;
    }
    return 0;
}
 
6.3、练习

        输入一个正的整数,逆序打印这个整数的每一位,例如: 输入:1234,输出:4321 输入:521,输出:125。

#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	while (n)
	{
		printf("%d ", n % 10);
		n /= 10;
	}
	return 0;
}

7、for循环

7.1、语法形式

        for循环是三种循环中使用最多的,其语法结构如下:

for (初始化表达式; 条件表达式; 更新表达式) {
    // 循环体
}
 
  • 初始化表达式(表达式1):在循环开始时执行一次,通常用于初始化循环变量。
  • 条件表达式(表达式2):每次循环前检查,若为真则执行循环体,否则退出循环。
  • 更新表达式(表达式3):每次循环后执行,通常用于更新循环变量。
7.2、for循环执行流程图

7.3、小练习

        在屏幕上打印1-10:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        printf("%d ", i);
    }
    return 0;
}
 

8、do-while循环

8.1、语法结构
do {
    // 循环体代码
} while (条件表达式);
 
8.2、代码流程图

8.3、do-while与while循环的区别
  • while循环:先检查条件,再决定是否执行循环体(可能一次都不执行)。
  • do-while循环:先执行循环体,再检查条件(至少执行一次)。
// while循环(可能不执行)
int i = 5;
while (i < 5) {
    printf("%d ", i); // 不输出
    i++;
}

// do-while循环(至少执行一次)
int j = 5;
do {
    printf("%d ", j); // 输出5
    j++;
} while (j < 5);
 
8.4、典型应用场景

        输入验证:确保用户至少输入一次数据。

int num;
do {
    printf("输入正数: ");
    scanf("%d", &num);
} while (num <= 0);
 

        菜单驱动程序:显示菜单并处理用户选择,直到退出。

char choice;
do {
    printf("1. 开始\n2. 退出\n");
    scanf(" %c", &choice);
    // 处理选择逻辑
} while (choice != '2');
 

        while(条件)后面必须加分号,否则编译器会报错

9、break和continue语句

9.1、break语句

        break语句用于立即终止当前所在的循环(for、while、do-while)或switch语句,并跳出该结构继续执行后续代码。通常用于满足特定条件时提前结束循环。

for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break; // 当i等于5时跳出循环
    }
    printf("%d ", i);
}
// 输出:0 1 2 3 4
 
9.2、continue语句

        continue语句用于跳过当前循环的剩余部分,直接进入下一次循环的条件判断(for、while、do-while)。通常用于忽略某些特定条件的迭代。

for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        continue; // 跳过偶数
    }
    printf("%d ", i);
}
// 输出:1 3 5 7 9
 
9.3、关键区别
  • break:完全终止循环,后续代码不再执行。
  • continue:仅跳过当前迭代,循环继续执行下一次迭代。

10、循环的嵌套

        找出100~200之间的素数,并打印在屏幕上。注:素数⼜称质数,只能被1和本⾝整除的数字。

#include <stdio.h>

int main()
{
	int i = 0;
	//循环产生100~200之间的数字
	for (i = 100; i <= 200; i++)
	{
		//判断i是不是素数
		
		int j = 0;
		int flag = 1;
		//假设i是素数,flag就为1,否则flag设置为0
		//非零整数不会被比自己大的数整除,所以我们选2~i-1之间的数字进行计算
		//循环产⽣2~i - 1之间的数字
		for (j = 2; j < i; j++)
		{
			if (i % j == 0)
			{
				flag = 0;//flag为0,就退出循环,因为肯定不是素数
				break;
			}

		}
		if (flag == 1)
			printf("%d ", i);//如果flag没变还是1,那么这个数就是素数,进行下一轮循环
	}
	return 0;
}

11、goto语句

        在C语言中,goto语句是一种无条件跳转语句,用于将程序控制流转移到同一函数内的指定标签处。语法格式为:

goto label;
...
label: statement;
 
#include <stdio.h>
int main()
{
    printf("hehe\n");
    goto next;
    printf("haha\n");
next:
    return 0;
}
 

        goto 语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以尽量不要使用goto语句。但goto语句并不是一无是处,当需要从嵌套循环中直接退出时,goto可以简化代码逻辑,避免设置多个标志变量:

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        if (error_condition) goto cleanup;
    }
}
cleanup: printf("Exited loops");
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值