C语言中表示真假:0表示假,非0表示真。
分支语句:if、switch。循环语句:while、for、do while。
switch后跟整形表达式:
switch(整形表达式)
{
case 整形常量表达式:
语句;
}
switch语句搭配break实现语句分支(在每一个case后放上break跳出)。
::: tip 在需要匹配相同输出内容时,可以连续使用“case:”在最后一个case后使用break。 每个switch语句中都需要有一个默认输出的default子句,后面也可以加break。 switch语句中defaults子句的位置没有确切要求(习惯放在最后)。 ::: ::: warning break表示永久中止循环。 continue表示中止循环中本次循环continue后面的代码, 直接跳到循环判断部分进行下一次循环的入口判断。
#include <stdio.h>
int main()
{
int i = 0;
while(i <= 10)
{
if (i == 5)
continue;
printf("%d",i);
i++;
}
return 0 ;
}
:::
if-else语句中,悬空else的匹配问题: else和距离最近的未匹配的if匹配,不和与之对齐的if匹配。
getchar和putchar getchar作用:输入一个字符(通常用于接受换行符以及空格)。 putchar作用:输出一个字符。
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
printf("请输入密码:");
scanf("%s",password); //输入密码并存放在password数组中
printf("请确认(N/Y)\n");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0 ;
}
请输入密码:123456
请确认(N/Y)
放弃确认
--------------------------------
Process exited after 2.484 seconds with return value 0
上述代码输出结果时候,没有输入N/Y,直接输出“放弃确认”后结束程序。 在调试中,第8行scanf执行输入123456后,变量password数组加入了值123456;程序运行到11行if (ret == ‘Y’)时,ret的值变为10。 ::: tip
#include <stdio.h>
int main()
{
printf("%d\n",'\n');
return 0;
}
10
--------------------------------
Process exited after 0.01777 seconds with return value 0
由上可知,“\n”的值为10。 :::
之前的代码中ret=getchar()=10,即getchar读到了一个“\n”。ret != Y,执行else语句,输出“放弃确认”。 在程序中,scanf和getchar属于输入函数,在读取输入内容时会检测输入缓冲区,在第一次需要读入内容时,输入缓冲区为空,程序会等待输入,当输入完毕后,输入函数会从输入缓冲区内拿走需要的数据,在getchar需要读入数据时,也会去检测输入缓冲区,如果输入缓冲区有内容,会直接被getchar读走,如果没有,程序会等待输入。
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
printf("请输入密码:");
scanf("%s",password);
//缓冲区剩余一个“\n”需要清空
getchar();
printf("请确认(N/Y)\n");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0 ;
}
请输入密码:123456
请确认(N/Y)
放弃确认
--------------------------------
Process exited after 3.49 seconds with return value 0
如上,在第一次输入密码“123456”后,回车使得scanf读到密码,即输入缓冲区内的内容是“1234546\n”,scanf读走了123456,剩下的“\n”被getchar读走。
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
printf("请输入密码:");
scanf("%s",password);
//缓冲区剩余一个“\n”需要清空
getchar();
printf("请确认(N/Y)\n");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0 ;
}
请输入密码:123456
请确认(N/Y)
Y
确认成功
--------------------------------
Process exited after 6.671 seconds with return value 0
如上述代码的第10行,在scanf读取结束后,将缓冲区内剩余的内容用getchar读走,此处的getchar并不关心返回值,只是为了清空缓冲区,可以直接用“gatchar();”。输入缓冲区被清空后,第12行的getchar不能从缓冲区内读到内容,程序就会停下来等待输入。
::: warning 上述代码的缺陷是,如果输入缓冲区内的内容较多,一个getchar就不能完全清空。如下:
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
printf("请输入密码:");
scanf("%s",password);
getchar();
printf("请确认(N/Y)\n");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0 ;
}
请输入密码:123456 ABCD
请确认(N/Y)
放弃确认
--------------------------------
Process exited after 6.08 seconds with return value 0
::: 上述代码执行错误的原因是,scanf读取到空格就会停止读入。第9行的getchar只能读到一个空格,第11行getchar读取时仍会从输入缓冲区内读入。
while循环流程图: 为了解决上述问题,需要写一个while循环,使得getchar不断读取输入缓冲区的内容,直到读取到第一次填充输入缓冲区后的回车“\n”。如下:
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
printf("请输入密码:");
scanf("%s",password);
while(getchar() != '\n')
{
; //空语句,循环只需要不断从缓冲区内读取内容,不需要其他动作
}
printf("请确认(N/Y)\n");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0 ;
}
请输入密码:123456 ABCD
请确认(N/Y)
Y
确认成功
--------------------------------
Process exited after 7.183 seconds with return value 0
for循环 for(表达式1;表达式2;表达式3) 循环语句; ::: tip 表达式1为初始化部分,用于初始化循环变量;表达式2为条件判断部分,用于判断循环是否终止;表达式3为调整部分,用于循环条件的调整。 执行顺序是表达式1-表达式2-循环语句-表达式3-表达式2。 :::
for循环执行流程图:
for语句循控制变量: 1.不可在for循环体内修改循环变量,防止for循环失去控制。 如下:
#include <stdio.h>
int main()
{
int i = 0;
for(i = 0;i < 10;i++)
{
if(i = 5)
printf("haha\n");
printf("hehe\n");
}
return 0;
}
上述代码第8行if语句内是赋值语句,在for循环内,设置了变量i的调整语句,使得每次进入循环后,变量i的值都被赋值成5,出现死循环。 2.建议for语句的循环控制变量的取值采用“前闭后开区间”写法。 如下:
#include <stdio.h>
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i = 0;i < 10;i++)
{
printf("%d ",a[i]);
}
return 0;
}
上述代码第7行的条件判断语句,写成前闭后开的写法i<10,不会写成i<=9。 ::: tip 不是所有的循环控制语句都写成前闭后开,具体情况具体分析。 :::
for循环的变种: 1.for循环的初始化、调整、判断都可以省略。如果省略for循环的判断部分,即判断结果恒为真,会陷入死循环:
#include <stdio.h>
int main()
{
for(;;)
{
printf("emmm\n");
}
return 0;
}
2.for循环中不能随意省略语句: 上图左边代码因为for循环中初始化值和定义变量的值相同,省去了初始化的语句,在代码执行结果中出现了和原结果不同的结果。 ::: warning 在上述右侧省去初始化语句的代码中,进入第一个for循环时,i=0,符合判断条件,进入内层循环,j从0增加到3,打印3次结果,此时j=3,不满足判断条件,跳出内层循环;i++变为1,符合判断条件,进入内层循环,j=0的初始化语句不存在,j的值为上次跳出循环的值,j=3,不满足条件,跳出内层循环;i++变为2…i++变为3,不满足条件,跳出循环,结束,整个程序运行过程中只有i=0,j=0、1、2时打印结果,即打印出3个结果。 :::
::: tip 面试题:
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
for(i = 0,j = 0;j = 0;i++,j++)
{
j++;
}
return 0;
}
--------------------------------
Process exited after 0.01387 seconds with return value 0
上述代码中第7行j=0的位置应该是一条判断语句,但写成了赋值语句,把0赋给j,表达式的结果是j的值即为0,0表示假,判断结果为假,不满足条件,不进入循环。 (如果这个语句是j赋值非0,就是死循环)。 :::
do-while语句执行流程图: