C语言是结构化的程序设计语言,包括:
- 顺序结构
- 选择结构
- 循环结构
使用if,switch实现分支结构,使用for,while,do while实现循环结构。
1.if语句
1.1if
if (表达式)
语句
规定:表达式成立(为真),语句执行。表达式不成立(为假),语句不执行。
在C语言中:0为假,非零为真,
例子:输入一个整数,判断是否为奇数
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 1)
printf("%d 是奇数\n", num);
return 0;
}
输入:3 //判断其结果
若是偶数输入则
1.2else
如果我们要优化该程序,能判断该数是奇数还是偶数。
利用if else语句来完成
如下:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 0)
{
printf("%d 是偶数", num);
}
else
{
printf("%d 是奇数", num);
}
return 0;
}
1.3分支中包含多条语句
默认if和else语句中默认都只能控制一条语句,比如:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num > 18)
printf("成年了\n");
printf("可以谈恋爱了\n");
return 0;
}
结果会发现不管是小于18的还是大于18的,都可以打印“可以谈恋爱了”
所以就可以得出结论:if只能控制一条语句(eles一样),如何解决这样的问题,就需要运用到我们的大括号{},这样就可以控制多条语句。
1.4嵌套if
在if else 语句中,else可以与另一个if语句连用,构成多重判断。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num == 0)
{
printf("输入的数值为0\n");
}
else if (num > 0)//这里的if相当于嵌套在else语句中,形成了嵌套结构
{
printf("输入的数值为正数\n");
}
else
{
printf("输入的数值为负数\n");
}
return 0;
}
另一种嵌套
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num > 0)
{
if (num % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
else
{
printf("非正数\n");
}
return 0;
}
1.5悬空else问题
如果有多个if或者多个else出现,规则:else总是跟最接近的if匹配。
例子:
结果:啥也不是
对该代码进行解读:让else和第一个if语句对齐,让我们以为else是和第一个if匹配的,当if语句不成立时,自然想到执行else语句,打印haha,但实际上else是和第二个if进行匹配的,这样后面if...else语句是嵌套在if语句里面的,如果第一个if语句不成立,嵌套if和else就没机会执行了。
所以我们为了严谨,就必须加上大括号,使用if语句时。
对代码进行修改,如下:
2.关系操作符
C语言中用于比较的表达式,称为“关系表达式”,里面使用的运算符就称为“关系运算符”。
- < 小于运算符
- >= 大于等于运算符
- <= 小于等于运算符
- == 等于运算符
- != 不等于运算符
关系运算符通常返回0或1,表示真假。
关系表达式常用if或while结构。
注意:相等运算符==与赋值运算符=是两个不一样的运算符,容易搞错。
例如:if(x = 3)
这个式子表示对变量x赋值3,它的返回值为3,所以if的判断总为真。
为了防止出现这个错误,可以写成这个样子:if(3 == x)
这样写等同于x 赋值为3,但是如果把==误写成=,编译器就会报错。
另一个要避免的错误:多个关系运算符不宜连用。
1. i<j<k
这个是合法表达式,不会报错,但是达不到想要的结果,不能保证变量j的值在i于k之间。因为关系运算符是从左向右计算的。
1.(i<j)<k
所以正确的书写:
1.i<j&&j<k
例如:输入一个年龄,如果在18~36之间,我们输出青年。
3.条件操作符
条件操作符又叫三目操作符,需要接受三个操作数的,形式如下:
1.exp1 ? exp2 : exp3
条件操作符的计算逻辑:如果exp1为真,exp2计算,计算的结果是整个表达式的结果;如果exp1为假,exp3计算,计算的结果是在整个表达式的结果。
练习1:使用条件操作符表示下面代码逻辑
源代码:
#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", &a);
b = a > 5 ? 3 : -3;
printf("%d\n", b);
return 0;
}
延申知识点:逗号表达式
#include<stdio.h>
int main()
{
int b = 0;
int c = 4;
int a = (a = 3, a + 3, b = c + 3, c = 2 * a + b);
printf("%d", a);
return 0;
}
结果输出为13
//逗号表达式:会从左向右依次计算,但整个表达式结果是最后一个表达式的结果。
4.逻辑操作符:&&,||,!
用于搭建更复杂的表达式
- !:逻辑取反运算符(改变单个表示的真假)
- &&:与运算符,就是并且的意思
- ||:或运算符,就是或者的意思
4.1逻辑取反运算符!
a | !a |
非0 | 0 |
0 | 1 |
4.2与运算符(全真才真)
&&就是与运算符,也是并且的意思,&&是双目操作符,使用的方式是a&&b,&&两边的表达式都是真的时候,整个表达式才为真。
4.3或运算符(全假才假)
||就是或运算符,也就是或者的意思,||也是一个双目操作符,使用方式是a||b,||两边的表达式只要有一个真,整个表达式就是真。
4.4练习:闰年的判断方法
闰年判断的规则:
- 能被4整除并且不能被100整除是闰年
- 能被400整除
#include<stdio.h>
int main()
{
int year = 0;
scanf("%d", &year);
if (year % 4 == 0 && year % 100 != 0)
printf("%d为闰年\n", year);
else if (year % 400 == 0)
printf("%d为闰年\n", year);
else
printf("%d不是闰年\n", year);
return 0;
}
4.5短路
C语言逻辑运算符有个特点,它总是先对左侧的表达式求值,在对右边的表达式求值,这个顺序是保证的。如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
1 if(month >= 3 && month <= 5)
表达式中&&的左操作数是month >= 3,右操作数是month <= 5,当左操作数month >= 3为假时,即使不判断month <= 5,整个表达式的结果也为0.
||或操作符雷同
5.switch语句
switch语句来实现分支结构,它是一种特殊形式的if...else结构。
switch(expression){
case value1: statement
case value2: statement
default: statement
}
根据表达式expression不同的值,执行相应的case分支。如果找不到对应的值,就执行default分支。
注:
- switch后的expression必须是整型表达式
- case后的值,必须是整型常量表达式
5.1 if语句和switch语句的对比
练习:输入任意一个整数值,计算除3之后的余数
if语句:
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n % 3 == 0)
printf("整除,余数为0\n");
else if (n % 3 == 1)
printf("余数为1\n");
else
printf("余数为2\n");
return 0;
}
switch语句:
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch (n % 3)
{
case 0:
printf("整除,余数为0\n");
break;
case 1:
printf("余数为1\n");
break;
case 2:
printf("余数为2\n");
break;
}
return 0;
}
注:
- case和后边的数字之间必须有空格
- 每个case语句中的代码执行完成后,需要加上break,才能跳出这个switch语句
5.2switch语句中的break
如果没有break,就会出现:
我们发现,7除以3本来余数是1,但是我们发现程序运行的结果多了
“余数是2”的打印。
这是为什么呢?
原因是 switch语甸也是分支效果的,只有在Switch语句中使用break才能在跳出switch语句,如果某一个case语句的后边没有break 语句,代码会继续玩下执行,有可能执行其他case语句中的代码,直到遇到 break语句或者 switch 语何结束。就比如上面的代码就执行了case 2中的语句。
所以在 switch语句中break语句是非常重要的,能实现真正的分支效果。
5.3switch语句中的default
在使用switch语句的时候,可能会遇到switch后的表达式中的值无法匹配代码中的case语句的时候,这时候要不就不做处理,要不就得在switch语句中加入default子句
switch(expression){
case value1: statement
case value2: statement
default: statement
}
如果switch后边的expression的结果不是value1,也不是value2的时候,就会执行default子句。
5.4switch语句中的case和default的顺序问题
在switch语句中case语句和default语句是没有顺序要求的,只要你的顺序是满足实际需要的就可以,不过通常default子句一般放在最后处理。
6.while循环
6.1if和while的对比
两个代码对比:
if语句
#include<stdio.h>
int main()
{
if (1)
{
printf("hehe\n");//if后边条件满足,打印一次hehe
}
return 0;
}
while语句:可以实现循环效果
#include<stdio.h>
int main()
{
while(1)
printf("hehe\n");//while后边的条件满足,死循环的打印hehe
return 0;
}
6.2while循环的实践
练习:在屏幕上打印1~10的值
#include<stdio.h>
int main()
{
int n = 0;
while (n <= 10)
{
printf(" %d", n);
n = n + 1;
}
return 0;
}
练习:输入一个正的整数,逆序打印这个整数的每一位
题目分析:
- 要想得到n的最低位,可以使用n%10的运算,得到的余数就是最低位,
- 要想去掉n的最低位,找到倒数第二位,则使用n=n/10操作就可以去掉最低位的,
- 循环1和2两个步骤
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
while (n)
{
printf("%d ", n % 10);
n = n / 10;
}
return 0;
}
7.for循环
for循环是三种循环中使用最多的,for循环的语法形式:
1 for(表达式1;表达式2;表达式3)
语句;//如果要加上更多语句,可以加上大括号
表达式1:用于循环变量的初始化
表达式2:用于循环结束的判断
表达式3:用于循环变量的调整
首先执行 表达式工初始化循环变量,接下来就是执行 表达式2的判断部分,表达式2的结果如果==0,则循环结束;表达式2的结果如果!=0则执行循环语句,循环语句执行完后,再去执行表达式3,调整循环变量,然后再去(表达式2的地方执行判断,表达式2的结果是否为0,决定循环是否继续。
整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3在循环。
7.1for循环的实践
练习:在屏幕上打印1~10的值
#include<stdio.h>
int main()
{
int n = 0;
for (n = 1; n <= 10; n++)
{
printf("%d ", n);
}
return 0;
}
7.2while循环和for循环的对比
for循环的三个部分(初始化,判断,调整)非常集中,便于代码的维护
练习1:计算1~100之间3的倍数的数字之和
#include<stdio.h>
int main()
{
int n = 0;
int sum = 0;
for (n = 1; n <= 100; n++)
{
if (n % 3 == 0)
{
sum += n;
}
}
printf("%d\n", sum);
return 0;
}
8.do-while循环
语法形式:
1 do
2 语句;
3 while(表达式);
do-while循环是先直接进入循环体,执行循环语句,然后再执行while后的判断表达式,表达式为真,就会进行下一次,表达式为假,则不再继续循环。
所以在do-while语句中循环体至少执行一次的。
8.1do-while循环的实例
在屏幕上打印1~10的值
#include<stdio.h>
int main()
{
int n = 1;
do
{
printf("%d ", n);
n = n + 1;
} while (n <= 10);
return 0;
}
9.1break和continue语句
在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。C语言中提供了break和continue两个关键字,就是应该到循环中的。
- break的作用是用于永久的终止循环,只要break被执行,直接就会跳出循环,继续往后执行。
- 。continue的作用是跳出本次循环continue后边的代码,在for循环和while循环中有所差异的。
9.1.1break举例
当i等于5时,循环正break的地方终止,不再打印,不再循环。
9.1.2continue举例
continue在循环中的作用就是跳出本次循环中continue后边的代码,继续进行下一次循环的判断。
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
continue;
printf("%d", i);
i = i + 1;
}
return 0;
}
当i等于5后,就执行continue,直接跳过continue的代码,去循环的判断的地方
因为跳过了i=i+1,所以i一直为5,程序陷入死循环
9.2for循环中的break和continue
9.2.1break
和while循环中的break一样,for循环中的break也适用于终止循环的。
9.2.2continue
#include<stdio.h>
int main()
{
int i = 1;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d", i);
}
return 0;
}
所以for循环中continue的作用是跳过本次循环中continue后的代码,直接去到循环的调整部分。
while与for里面的continue作用不一样
9.3do-while循环中的break和continue
do-while语句中的break和continue的作用和while循环中几乎一样
10.循环的嵌套
练习:找到100~200之间的素数
分析:
- 用循环提取100~200之间的数
- 判断i是否为素数,需要拿2~i-1之间的数字去试除
- 2~i-1之间的数能整除i,则i不是素数,若不能整除,则i是素数
#include<stdio.h>
int main()
{
int i = 1;
for (i = 100; i <= 200; i++)
{
int j = 0;
int flag = 1;
for (j = 2; j < i; j++)
{
if (i % j == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
printf("%d ", i);
}
return 0;
}
注:flag: flag 通常被用作一个标记变量,用于表示某个特定的条件是否已经满足。 通常情况下, flag 的 初始值 被设置为 0 或 1,然后程序根据需要修改其值来表示特定条件是否满足。