首先介绍一些前导知识
1.逻辑运算符
C 语言提供了 3 个逻辑运算符,用于对条件进行逻辑运算,通常用于 if
语句、while
循环、for
循环 等结构中。
1.1逻辑与&&
-
仅当两个条件都为
true
时,表达式的结果才是true
。 -
否则,结果为
false
。
#include <stdio.h>
int main() {
int a = 8, b = 6;
if (a > 5 && b < 10) {
printf("两个条件都满足,结果为真!\n");//会输出这个
} else {
printf("有一个条件不满足,结果为假!\n");
}
return 0;
}
-
a > 5为 true
-
b < 10 为 true
-
true && true → 结果 true
1.2逻辑或||
-
只要其中一个条件为
true
,结果就是true
。 -
只有两个条件都为
false
时,结果才是false
。
#include <stdio.h>
int main() {
int a = 3, b = 12;
if (a > 5 || b < 10) {
printf("至少一个条件满足,结果为真!\n");
} else {
printf("两个条件都不满足,结果为假!\n");//会输出这个
}
return 0;
}
1.3逻辑非!
-
将条件的真假取反。
-
如果原本为
true
,则变为false
;如果原本为false
,则变为true
。
#include <stdio.h>
int main() {
int a = 5;
if (!(a > 10)) {
printf("a 不大于 10,所以取反后为真!\n");//输出这个
} else {
printf("a 大于 10,取反后为假!\n");
}
return 0;
}
1.4逻辑运算符的短路特性
C 语言的 &&
和 ||
具有短路求值特性,即:
-
对
&&
,如果左侧为false
,右侧不会被执行。 -
对
||
,如果左侧为true
,右侧不会被执行。
2.条件运算符?:
条件运算符即C语言中的三目运算符,格式如下:
条件表达式 ? 表达式1 : 表达式2
执行逻辑:
-
如果
条件表达式
为true
(非 0),则执行表达式1
,并返回其值。 -
如果
条件表达式
为false
(0),则执行表达式2
,并返回其值。
#include <stdio.h>
int main() {
int a = 10, b = 20;
int max;
max = (a > b) ? a : b; // 如果 a > b,max 取 a,否则 max 取 b
printf("较大的数是: %d\n", max);
return 0;
}
3.getchar()和putchar()
getchar()
和 putchar()
是 C 标准库中的两个 字符输入输出函数,它们分别用于从标准输入流(键盘)读取一个字符和向标准输出流(屏幕)写入一个字符。包含在<stdio.h>头文件中。
getchar()
用于从标准输入(通常是键盘)读取一个字符。这里可能不是很好理解,下面举个例子就差不多了。
getchar()函数不带任何参数,他从输入队列中返回下一个字符,例如,下面的语句读取下一个字符输入,并把该字符的值赋给变量ch
ch = getchar();
该语句和下面的语句效果是一样的
scanf("%c",&ch);
而putchar()函数打印他的参数,例如,下面的语句把之前赋给ch的值作为字符打印出来:
putchar(ch);
该语句和下面的语句效果相同
printf("%c",ch);
举个例子来说明
#include <stdio.h>
int main() {
char c;
printf("请输入一些字符(按回车结束):\n");
// getchar 会读取每一个字符直到回车
while ((c = getchar()) != '\n') {
putchar(c); // 输出读取的字符
//printf("测试");
}
return 0;
}
执行过程:
1. 当程序执行到 `getchar()` 时,它会等待用户输入字符,并在每次按下一个字符时读取。用户可以输入多个字符,比如说我输入hello,跟着键盘敲打出h,e,l,l,o之后,getchar会读取输入的这几个字符。
2. 当用户按下回车键时,`getchar()` 会把输入的字符依次返回。
演示一下
这样可能看不出来所以然,你试着把上面代码中的注释掉的printf("测试");这个语句去掉注释试一下会输出什么,如下图
在来个例子
#include <stdio.h>
int main() {
char ch;
ch = getchar(); //逐个读取我输入的字符
while (ch != '\n') { //当一行还未结束的时候
if (ch == ' ') { //空格原样输出
putchar(ch);
}
else {
putchar(ch +1); //其余字符+1
}
ch = getchar(); //继续读取下一个字符
}
putchar(ch); //输出回车符('\n')
return 0;
}
4.选择语句
4.1if语句
在 C 语言中,if
语句是一种常用的条件控制语句,用于根据指定的条件来决定是否执行某个代码块。if
语句可以用于实现程序中的 分支逻辑,根据不同的输入或状态选择不同的执行路径。
基本语法
if (condition) {
// 如果 condition 为真(非零),执行此代码块
}
其中:
condition:一个表达式,通常是一个比较(如3>2)或逻辑表达式。它的值必须是布尔类型,即 true(非零)或 false(零)。
{ ... }:代码块。如果条件为真(即 condition 结果为非零值),就执行代码块内的语句。否则,跳过该代码块。
4.2if else语句
简单形式的if语句可以让程序选择执行一条语句,或者跳过这条语句,C语言还提供了if else的形式,可以在两条语句之间做选择。
基本语法
if (condition) {
// 如果 condition 为真(非零),执行此代码块
} else {
// 如果 condition 为假(零),执行此代码块
}
4.3else if
else if
是 if-else
语句的一部分,当有多个条件需要判断时,else if
语句可以帮助我们避免多次嵌套 if
语句。它用于在 if
语句条件为假时继续判断其他条件。
基本语法
if (condition1) {
// 如果 condition1 为真,执行此代码块
} else if (condition2) {
// 如果 condition1 为假且 condition2 为真,执行此代码块
} else if (condition3) {
// 如果 condition1 和 condition2 都为假且 condition3 为真,执行此代码块
} else {
// 如果以上所有条件都为假,执行此代码块
}
举个小栗子
根据学生的得分来评定等级
评分规则如下:
-
如果成绩大于等于 90 分,评定为 "优秀"。
-
如果成绩大于等于 75 分但小于 90 分,评定为 "良好"。
-
如果成绩大于等于 60 分但小于 75 分,评定为 "及格"。
-
如果成绩小于 60 分,评定为 "不及格"。
另外,还要判断如果输入的成绩无效(如负数或超过 100),则输出 "无效成绩"。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main(void) {
int score;
printf("请输入学生的成绩(0-100):");
// 如果是初学者的话这个while先不管,后面马上介绍到
while (1) {
if (scanf("%d", &score) != 1) {
printf("输入无效,请输入一个整数\n");
return 1;//表示程序异常退出
}
if (score < 0 || score > 100) {
printf("无效成绩\n");
return 1;
}
else if (score >= 90) {
printf("优秀\n");
}
else if (score >= 75) {
printf("良好\n");
}
else if (score >= 60) {
printf("及格\n");
}
else {
printf("不及格\n");
}
printf("请输入学生的成绩(0-100):");
}
return 0;
}
现在来解释一下这个东西:**if (scanf("%d", &score) != 1) **
在 C 语言中,`scanf` 是一个 **输入函数**,用于从标准输入(键盘)获取数据。
例如:
int score;
scanf("%d", &score);
其中:
%d 表示要读取一个整数
&score 表示读取的整数存入变量 score 的地址
而scanf
返回值 表示成功读取的变量个数。
看下面的表格更好理解:
用户输入 | scanf("%d", &score) 返回值 | 解释 |
---|---|---|
80(整数) | 1 | 成功读取了 1 个整数 |
abc(字母) | 0 | 失败,未能读取整数 |
#@!(符号) | 0 | 失败,未能读取整数 |
Ctrl+D / Ctrl+Z (EOF) | EOF(-1) | 输入结束 |
如果scanf输入字母,则scanf返回0或者EOF(-1),条件!=1成立,进入if语句中,输出错误信息并终止程序。
下面是输入字母的时候出现的错误提示信息
4.4switch和break
使用if else和条件运算符语句可以很容易的编写二选一的程序,然后有时程序需要在多个选项中进行选择,可以使用if else if ... else来完成,但是大多数情况下使用switch更方便一些,switch
语句用于 多个相等比较的情况,适用于枚举值或常量判断。
基本结构
switch
语句是用于基于某个变量的值,执行不同分支代码的一种控制流语句。
switch (expression) {
case constant1:
// 当 expression == constant1 时执行的代码
break;
case constant2:
// 当 expression == constant2 时执行的代码
break;
case constant3:
// 当 expression == constant3 时执行的代码
break;
default:
// 如果没有匹配的 case,执行的代码
}
解释
-
switch
后面跟着一个表达式,通常是一个变量。该表达式的值将与后续的各个case
标签进行匹配。 -
每个
case
后面跟着一个常量(或常量表达式)。如果switch
表达式的值与某个case
后面的常量值相等,就会执行该case
下的代码。 -
如果
case
匹配成功,执行该case
下的代码后,如果不加break;
,程序会继续执行下一个case
的代码。通常在每个case
结束时使用break
来终止switch
语句,防止继续执行后面的代码。 -
default
是可选的,它是当所有case
都不匹配时执行的代码块。
举个简单的例子
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int grade;
printf("请输入成绩(0-100):");
scanf("%d", &grade);
switch (grade / 10) {
case 10:
case 9:
printf("优秀\n");
break;
case 8:
printf("良好\n");
break;
case 7:
printf("中等\n");
break;
case 6:
printf("及格\n");
break;
default:
printf("不及格\n");
}
return 0;
}
再来一个例子
根据输入的小写字母来输出对应的动物名称
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<ctype.h>
int main() {
char ch;
printf("给我一个字母,我可以给你一个动物的名字(输入#表示结束)\n");
while ((ch = getchar()) != '#') {
// 这个if语句为了防止运行程序时直接按下回车键会输出,因为按下回车键是\n
// 如果没有这个判断的话,会输出“只接受小写的”的情况
if (ch == '\n') {
continue;
}
// 只接受小写字母的
if (islower(ch)) {
switch (ch) {
case 'a':
printf("alpaca:羊驼\n");
break;
case 'b':
printf("bee:蜜蜂\n");
break;
case 'c':
printf("cat:猫\n");
break;
default:
printf("暂时没有这个选项\n");
break;
}
}
else {
printf("只接受小写的\n");
}
// 这个代码实现的是只读每行的首字符,下面有解释过程看一下
while (getchar() != '\n')
continue;
printf("继续输入您想要知道的动物名称\n");
}
printf("Bye!");
return 0;
}
解释一下输入abc为什么只输出的是alpaca:羊驼,而没有输出b和c开头的动物
当我们从键盘输入内容(比如 abc
并按下回车键)时,输入的内容会先被存储在一个叫做 输入缓冲区 的区域。输入缓冲区的数据是按字符存储的,比如输入 abc
并按下回车键后,缓冲区的内容是:
'a', 'b', 'c', '\n'
其中 '\n' 是按下回车键时产生的换行符。
每次输入都通过 getchar() 从输入缓冲区中逐个字符读取
执行顺序
第一次执行 getchar():
-
程序第一次执行 ch = getchar() 时,缓冲区的第一个字符 'a'被读取。
-
因为
'a'
是小写字母,islower(ch)
返回true
,程序进入if (islower(ch))
语句。 -
进入
switch (ch)
,匹配到case 'a'
,输出alpaca:羊驼
。 -
执行完
break
跳出switch
后,进入while (getchar() != '\n') continue;
。此时缓冲区中剩余的字符是'b', 'c', '\n'
,程序继续从缓冲区中读取字符。
第二次执行 getchar()
:
-
getchar()
读取缓冲区中的第二个字符'b'
。 -
由于
'b' != '\n'
,程序继续执行while (getchar() != '\n') continue;
,这会跳过当前循环并进入下一次getchar()
调用。
第三次执行 getchar()
:
-
现在程序读取缓冲区中的第三个字符
'c'
。 -
同样,
'c' != '\n'
,程序继续执行while (getchar() != '\n') continue;
,跳过当前循环。
第四次执行 getchar()
:
-
此时缓冲区中只剩下换行符
'\n'
。 -
getchar()
读取到'\n'
,跳出while
循环。接下来执行printf("继续输入您想要知道的动物名称\n");
提示输入
4.5使用if还是switch
if语句一般适用于需要根据复杂条件进行判断时,或者条件数量较少的情况。或者使用逻辑运算符(如 &&, ||)来组合多个条件
switch语句适用于对单一变量进行多个固定值的比较,代码结构更清晰,执行效率通常更高。
5.循环语句
5.1while循环
while循环用于在条件为真的时候重复执行代码块,适用于循环次数不确定的场景,每次执行之前都会判断循环条件。
基本语法
while(条件表达式){
// 执行的循环体内容
}
// 条件表达式:在每次执行循环之前都会被判断,如果为真(非零),则执行循环体;否则退出循环。
1.补充:循环控制语句break语句
在while循环中可以使用break语句,用来立即退出当前的循环,也可以使用在上一节介绍的switch语句中,下面要讲的for和do while循环中,说白了就是说如果正在执行循环呢,然后执行到了break语句的话,条件表达式就不要再继续判断了,直接退出执行while循环后面的语句就行了。下面举个例子
#include <stdio.h>
int main() {
int i = 0;
while (i < 10) {
i++;
if (i == 2) {
break;
}
printf("%d\n", i);
}
return 0;
}
首先,i=0,执行i<10是满足条件的,所以执行i++之后i的值变成1了,然后1是不等于2的,所以执行printf()来输出i的值为1,然后继续执行循环,且1是小于10的,所以i++之后,i变成了2了,此时2是等于2的,所以会执行if里面的break语句,此时跳出整个的while循环,即使2是小于10的,但是执行了break语句会立即跳出当前的循环,下面的printf不会被执行了,所以最终的结果只会输出1,这个就是和后面马上要说的continue语句最主要的区别了
2.补充:循环控制语句continue语句
在while循环中也可以使用continue语句,用于终止当前的那次循环,在执行完continue语句之后,程序会接着重新检测表达式的值,决定是否继续执行循环,说白了就是说如果正在执行循环呢,然后执行到了continue语句的话,条件表达式会继续判断是否满足,如果满足继续进入执行。下面举个例子
#include <stdio.h>
int main() {
int i = 0;
while (i < 10) {
i++;
if (i == 2) {
continue;
}
printf("%d\n", i);
}
return 0;
}
首先,i=0,执行i<10是满足条件的,所以执行i++之后i的值变成1了,然后1是不等于2的,所以执行printf()来输出i的值为1,然后继续执行循环,且1是小于10的,所以i++之后,i变成了2了,此时2是等于2的,所以会执行if里面的continue语句,此时会跳出当前循环,也就是说printf这个语句 不会执行,重新判断while的条件是否满足,发现2是小于10的,所以继续执行while里面的内容,i++之后变成3,3不等于2,输出3,以此类推,所以最终的结果如下
5.2do...while循环
do...while循环和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;
}
5.3for循环
for循环是最常用的循环结构,适合在已知循环次数的情况下使用。
语法
for (初始化; 条件; 更新) {
// 循环体
}
关键字for后面的圆括号中有3个表达式,分别用两个分号进行分隔:
-
初始化:在循环开始前执行一次,通常用于初始化循环变量。
-
条件:每次循环开始前检查,如果为真(非零),则执行循环体;否则退出循环。
-
更新:每次循环结束后执行,通常用于更新循环变量。
#include<stdio.h>
int main(void) {
int num;
printf(" n n的立方\n");
for (num = 1;num <= 6;num++) {
printf("%5d %5d\n",num,num*num*num);
}
return 0;
}