文章目录
0、总结
C语言是结构化的程序语言,这里的结构指的是顺序结构、选择结构、循环结构。
-
if
、switch
可实现分支结构。 -
while
、for
、do while
可实现循环结构。
1、分支
1、if语句
if语句的语法形式如下:
if (表达式)
语句;
表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行。
注:在C语言中,0为假,非0为真。
例1:输入一个整数,判断是否为奇数?
#include <stdio.h>
int main()
{
int num = 0;
printf("请输入整数:");
scanf("%d", &num);
if (num % 2 == 1)
printf("%d是奇数\n", num);
return 0;
}
输入:
3
输出:
请输入整数:3
3是奇数
如果想要表达一个数是偶数,那么需要if...else...
语句,语法形式如下:
if(表达式)
语句1;
else
语句2;
例2:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印数偶数。
#include <stdio.h>
int main()
{
int num = 0;
printf("请输入一个整数:");
scanf("%d", &num);
if (num % 2 == 1)
printf("%d是奇数\n", num);
else
printf("%d是偶数\n", num);
return 0;
}
输入:
2
输出:
请输入一个整数:2
2是偶数
if
和else
语句都默认只控制一条语句,如果要if和else语句同时控制多条语句,就需要使用{}
将多条语句括起来。
如下:
#include <stdio.h>
int main()
{
int age = 0;
printf("请输入一个年龄:");
scanf("%d", &age);
if (age >= 18)
{
printf("成年了。\n");
printf("可以独立自主了。\n");
}
else
{
printf("未成年。\n");
printf("好好学习,天天向上。\n");
}
return 0;
}
输入:
23
输出:
请输入一个年龄:23
成年了。
可以独立自主了。
嵌套if
语句:在if else
语句中,else
可以与另一个if
语句连用,构成多重判断。
如下:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num == 0)
printf("输入的数字是0\n");
// 这里的if相当于嵌套在else语句中,形成嵌套结构
else if (num > 0)
printf("输入的数字是正数\n");
else
printf("输入的数字是负数\n");
return 0;
}
输入:
1
输出:
1
输入的数字是正数
再如:
#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;
}
输入:
23
输出:
23
奇数
悬空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;
}
没有输出
2、switch语句
分支结构除了if
语句,还有switch
语句。
switch
语句:用于判断条件有多个结果的情况,是一种特殊形式的if...else
结构。
语法形式如下:
switch (expression)
{
case value1: statement;
case value2: statement;
default: statement;
}
上面代码中,根据表达式expression
不同的值,执行相应的case
分支。如果找不到对应的值,就执行default
分支。
注:
1、
switch
后的expression
必须是整型表达式。2、
case
后的值,必须是整形常量表达式。
例1:输入任意一个整数值,计算除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;
}
输入:
5
输出:
5
余数是2
// 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;
}
输入:
6
输出:
6
整除,余数为0
上述的代码,值得注意是:
1、
case
和后边的数字之间必须有空格。2、每一个
case
语句中的代码执行完成后,需要加上break
,才能跳出这个switch
语句。
如果case
语句后面没有break
语句,代码就会继续执行下去,可能执行其他case
语句中的代码,直至遇到break
语句或者switch
语句结束。
例2:输入1-5,输出“工作日”,输入6-7,输出“休息日”
#include <stdio.h>
int main()
{
int day = 0;
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;
}
输入:
1
输出:
1
工作日
上面的练习,应该从实际的情况出发,灵活使用break
,完成实际的需求。
在使用switch
语句的时候,如果switch
后的表达式中的值无法匹配代码中的case
语句的时候,这时候要么不做处理,要么在switch
语句中加入default
子句。
例3:输入1-5,输出“工作日”,输入6-7,输出“休息日”,输入不是1-7的值,输出“输入错误”
#include <stdio.h>
int main()
{
int day = 0;
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("输入错误\n");
break;
}
return 0;
}
输入:
8
输出:
8
输入错误
switch
语句中的case
和default
的顺序问题:
在
switch
语句中,case
语句和default
语句是没有顺序要求的,只要顺序是满足实际需求即可。不过通常是把
default
子句放在最后处理的。
2、操作符
1、关系操作符
关系表达式:C语言用于比较的表达式。
关系运算符:关系表达式里面使用的运算符。
主要有6个:
关系运算符 | 含义 |
---|---|
> | 大于运算符 |
< | 小于运算符 |
>= | 大于等于运算符 |
<= | 小于等于运算符 |
== | 相等运算符 |
!= | 不相等运算符 |
关系表达式通常返回0
或1
,表示真假。
C语言中,0
表示假,所有非零值表示真。比如,20>12
返回1
,12>20
返回0
。
关系表达式常用于if
或while
结构。
如下:
if (x == 3)
{
printf("x is 3.\n");
}
值得注意是,相等运算符==
与赋值运算符=
是两个不一样的运算符。
有时候可能会写出这个代码:
if (x = 3)...
上面的示例,这个式子表示对变量x
赋值3
,它的返回值为3
,所以if
判断总是为真。
为了防止这个错误,可以这样写:
if (3 == x)...
上面的示例,如果把==
误写成=
,编译器就会报错。
还有另一个值得注意是,多个运算符不宜连用。
i < j < k
上面的示例,虽然是合法表达式,编译器不会报错,但通常得不到想要的结果。因为实际执行是:
(i < j) < k
上面的式子,i < j
返回0
或1
,所以最终是0
或1
与变量k
进行比较。
正确写法是:
i < j && j < k
如果这样写:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (18 <= age <= 36)
printf("青年\n");
return 0;
}
输入:
10
输出:
10
青年
上面的示例,当输入10
,输出青年
。这是因为,先拿18
和age
比较,表达式返回值为0
,再拿0
和36
比较,0<=36
为真,因此打印青年
。
为了防止这个错误,代码应该这样写:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18 && age <= 36)
printf("青年\n");
return 0;
}
输入:
23
输出:
23
青年
2、条件操作符
条件操作符:也叫三目操作符,需要接受三个操作数。语法形式如下:
exp1 ? exp2 : exp3
计算逻辑是:如果exp1
为真,exp2
计算的结果是整个表达式的结果;如果exp1
为假,exp3
计算的结果是整个表达式的结果。
例1:
#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;
}
输入:
6
输出:
6
3
例2:使用表达式实现找两个数中较大值。
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = a > b ? a : b;
printf("%d\n", m);
return 0;
}
输入:
2 3
输出:
2 3
3
3、逻辑操作符
逻辑运算符:提供逻辑判断功能,用于构建更复杂的表达式。
主要有三个运算符:
逻辑运算符 | 含义 |
---|---|
! | 逻辑取反运算符(改变单个表达式的真假) |
&& | 与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假) |
|| | 或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假) |
注:C语言中,
非0
表示真,0
表示假
例1:
#include <stdio.h>
int main()
{
int flag = 0;
if (!flag)
printf("hello\n");
return 0;
}
输出:
hello
上面的代码意思是,flag
为假,!flag
为真,执行if语句中的代码。
&&
与运算符,是一个双目操作符。
例2:3月到5月是春天。
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month >= 3 && month <= 5)
printf("春季\n");
return 0;
}
输入:
5
输出:
5
春季
这里表达的意思是,month
既要大于等于3,又要小于等于5,必须同时满足。
||
或运算符,也是一个双目操作符。
例3:12月或者1月或者2月是冬天。
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month == 12 || month == 1 || month == 2)
printf("冬季\n");
return 0;
}
输入:
12
输出:
12
冬季
例4:输入一个年份year,判断year是否是闰年
闰年判断的规则:
1、能被4整除并且不能被100整除是闰年
2、能被400整除是闰年
// 代码1
#include <stdio.h>
int main()
{
int year = 0;
scanf("%d", &year);
if (year % 4 == 0 && year % 100 != 0)
printf("是闰年\n");
else if (year % 400 == 0)
printf("是闰年\n");
return 0;
}
输入:
2024
输出:
2024
是闰年
// 代码2
#include <stdio.h>
int main()
{
int year = 0;
scanf("%d", &year);
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
printf("是闰年\n");
return 0;
}
输入:
2024
输出:
2024
是闰年
值得注意是,C语言逻辑运算符有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。
如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为短路。
如前面的代码:
if (month >= 3 && month <= 5)
表达式中&&
的左操作数是month >= 3
,右操作数是month <= 5
,当左操作数month >= 3
的结果是0
的时候,右边操作数就不再执行。
再如前面的代码:
if (month == 12 || month == 1 || month == 2)
如果month == 12
的结果是真,则不用再判断后面的操作数。
像这种仅仅根据左操作数的结果,就能知道整个表达式的结果,不再对右操作数进行计算的运算,称之为短路求值。
例5:阅读代码,计算代码输出的结果
#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("i = %d\n", i);
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
printf("d = %d\n", d);
return 0;
}
输出:
i = 0
a = 1
b = 2
c = 3
d = 4
3、循环
1、while循环
C语言提供了3种循环语句,while
语句就是其中一种。
while
语句的语法结构和if
语句非常相似:
// if和while的对比
if (表达式)
语句;
while (表达式)
语句;
例1:
// 代码1:if语句
#include <stdio.h>
int main()
{
// if后边条件满足,打印一次hello
if (1)
printf("hello\n");
return 0;
}
输出:
hello
// 代码2:while语句
#include <stdio.h>
int main()
{
// while后边条件满足,死循环打印hello
while (1)
printf("hello\n");
return 0;
}
输出:
死循环
以上是if
语句和while
语句的区别,从中知while
语句可以实现循环效果。
while
语句循环的逻辑是:首先执行判断表达式,如果表达式的值为0,循环直接结束,如果表达式的值不为0,则执行循环语句,语句执行完后再继续判断是否进行下一次。
例2:打印1-10的值
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i = i + 1;
}
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
例3:
输入一个正的整数,逆序打印这个整数的每一位
例如:
输入:1234,输出:4 3 2 1
输入:521,输出:1 2 5
解析:
1、要得到n的最低位,用n%10的运算,得到的余数是最低位,如:1234%10得到4。
2、要去掉n的最低位,找出倒数第二位,用n=n/10的运算,可以去掉最低位,如:n=1234/10得到123。
3、循环1和2两个步骤,在n变成0之前,能得到所有的位。
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
while (n)
{
printf("%d ", n % 10);
n = n / 10;
}
return 0;
}
输入:
24
输出:
24
4 2
2、for循环
for
循环是三种循环中使用最多的,语法形式如下:
for (表达式1; 表达式2; 表达式3)
语句;
-
表达式1:用于循环变量的初始化
-
表达式2:用于循环结束条件的判断
-
表达式3:用于循环变量的调整
for
是如何循环的?
首先执行
表达式1
,进行初始化循环变量,接下来执行表达式2
的判断,如果表达式2
的结果为0
,循环结束;如果表达式2
的结果为非0
,执行循环语句,执行完后,再去执行表达式3
,调整循环变量,然后再执行表达式2
进行判断,表达式2
的结果是否为0
,决定循环语句是否继续。整个循环中,
表达式1
只被执行1次,剩下的表达式2
、循环语句
、表达式3
在循环。
例1:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
printf("%d ", i);
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
while循环和for循环的对比
// while循环
#include <stdio.h>
int main()
{
// 初始化
int i = 1;
// 判断
while (i <= 10)
{
printf("%d ", i);
// 调整
i = i + 1;
}
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
// for循环
#include <stdio.h>
int main()
{
int i = 0;
// 初始化、判断、调整
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
for
和while
在实现循环的过程中,都有初始化、判断、调整这三个部分,但是for
循环的三个部分非常集中,易于代码的维护。
例2:计算1~100之间3的倍数的数字之和
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for (i = 1; i <= 100; i++)
{
if (i % 3 == 0)
sum += i;
}
printf("%d\n", sum);
return 0;
}
输出:
1683
优化:省去多余的循环和判断
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for (i = 3; i <= 100; i += 3)
sum += i;
printf("%d\n", sum);
return 0;
}
输出:
1683
3、do-while循环
在循环语句中do while
语句的使用最少,语法形式如下:
do
语句;
while (表达式);
do while
如何循环,以及和while
、for
的区别?
while
、for
这两种循环都是先判断,满足条件可进入循环语句。而
do while
循环是先执行循环语句,然后再判断表达式,如果表达式为真,就会执行下一次循环语句,如果表达式为假,则不再继续循环。因此,
do while
语句中的循环语句是至少执行一次,这是do while
循环比较特殊的地方。
例1:
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i = i + 1;
} while (i <= 10);
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
例2:
输入一个正整数,计算这个整数是几位数?
例如:
输入:1234 输出:4
输入:12 输出:2
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int cnt = 0;
do
{
cnt++;
n = n / 10;
} while (n);
printf("%d\n", cnt);
return 0;
}
输入:
54321
输出:
54321
5
4、break和continue语句
在执行循环的过程中,如果需要提前终止循环,那么break
和continue
能解决这个问题。
-
break
的作用是用于永久的终止循环,只要break
执行,直接跳出循环。 -
continue
的作用是跳过本次循环continue
后面的代码,在for
循环和while
循环中有所差异。
例1:while的break举例
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
// 当i等于5,执行break,循环终止。
break;
printf("%d ", i);
i = i + 1;
}
return 0;
}
输出:
1 2 3 4
例2:while的continue举例
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
// 陷入死循环
continue;
printf("%d ", i);
i = i + 1;
}
return 0;
}
输出:
死循环
continue
可以帮助我们跳过某一次循环continue
后面的代码,直接到循环变量的判断,如果循环变量的调整是在continue
后面的话,可能会造成死循环。
例3:for的break举例
#include <stdio.h>
int main()
{
int i = 1;
for (i = 1; i <= 10; i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
输出:
1 2 3 4
例4:for的continue举例
#include <stdio.h>
int main()
{
int i = 1;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
输出:
1 2 3 4 6 7 8 9 10
在for
循环中,continue
的作用是跳过本次循环的continue
后的代码,直接到循环的调整地方。
在这里能感受到while
循环和for
循环中的continue
的区别,主要在于循环的调整地方。
例5:do while的break和continue
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
break;
printf("%d ", i);
i = i + 1;
} while (i <= 10);
return 0;
}
输出:
1 2 3 4
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
continue;
printf("%d ", i);
i = i + 1;
} while (i <= 10);
return 0;
}
输出:
死循环
do while
循环中的break
和continue
的作用和while
循环中几乎一模一样。
5、循环的嵌套
学完三种循环while
、do while
、for
,如果把这三种循环嵌套一起,那么这种方式称之为循环嵌套。
例1:
找出100~200之间的素数,并打印在屏幕上。
注:素数又称为质数,只能被1和本身整除的数字。
解析:
1、先有100~200之间的数,用循环解决,循环变量为
i
。2、先判断
i
是否为素数,需要在2
`i-1`之间的数字去试除,需要产生`2`i-1
之间的数字,用循环解决。3、如果
2
~i-1
之间有数字能整除i
,则i
不是素数,如果都不能整除,则i
是素数。
#include <stdio.h>
int main()
{
int i = 0;
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;
}
输出:
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
6、goto语句
C语言提供了一种特别的语法,就是goto
语句和跳转标号,goto
语句可以实现在同一个函数内跳转到设置好的标号处。
例1:
#include <stdio.h>
int main()
{
printf("hello\n");
goto next;
printf("haha\n");
next:
printf("跳过haha的打印\n");
return 0;
}
输出:
hello
跳过haha的打印
goto
语句如果使用不当,就会导致函数内随意跳转,打乱程序的执行流程,goto
语句一般用于在多层循环的代码中,目的是快速跳出多层循环。如下:
for (...)
{
for (...)
{
for (...)
{
if (...)
goto error;
}
}
}
error:
//...
for
循环想提前退出使用break
,但一个break
只能跳出一层for
循环,如果3层循环嵌套就得使用3个break
才能跳出循环,所以在这种情况下使用goto
语句就会更加便携。
完。