C语言的分支语句和循环语句(1)【初阶详解篇4】

【声明】本章重点学习分支语句和循环语句的使用,计划对本章内容做两次更新。
其中代码内容注释较多,可能会给读者造成些许阅读障碍,建议电脑阅读。
由于水平有限,如发现有错误之处,恳切希望读者们批评指正,以免自己或他人入坑!

本节重点

分支语句
什么是语句?

C语言中由一个分号;隔开的就是一条语句。

如:

int main()
{
 printf("hehe\n");//它是一条语句
 3 + 5;//它是一条语句
 ;//空语句
 return 0;
}

什么叫分支语句?
分支语句对应的是选择结构

if 语句
if语句的语法结构
写法1(单分支):if(表达式)//if里面的表达式为真,语句执行,为假,语句不执行
                   语句;
                   
写法2(双分支):if(表达式)//if里面的表达式为真,语句1执行,为假,语句2执行
                     语句1;
                 else
                     语句2;
                     
写法3(多分支):if(表达式1)//判断表达式1是否成立,如果成立执行语句1,如果不成立判断表达式2
                     语句1;
                 else if(表达式2)
                     语句2;
                 else
                     语句3;
               

提问:C语言是如何表示真和假的呢?
答:非0就是真,0就是假

if语句的语法结构举例逐一讲解
单分支
#include<stdio.h>
int main()
{
 int age = 10;
 if (age >= 19)
  printf("成年\n");//打印结果为空
 return 0;
}
双分支
int main()
{
 int age = 10;
 if (age >= 18)
  printf("成年\n");
 else
 {
  printf("未成年\n");
  printf("不能谈恋爱");
 }
 //注意:if和else只能控制一条语句,若想控制多条,需要给它们加上大括号,不带大括号,默认控制1条语句。
 //一对大括号叫做一个代码块
 return 0;
}
多分支
int main()
{
 int age = 160;
 if (age < 18)
  printf("少年\n");
 //else if (18 <= age < 26)//这种表达式的写法是错误的,这样写它会先判断18<=age,结果为真就是1,结果为假就是0,1或0再和26比较,背离初衷。
 else if (age >= 18 && age < 26)//这种写法正确
  printf("青年\n");
 else if (age >= 26 && age < 40)
  printf("中年\n");
 else if (age >= 40 && age < 60)
  printf("壮年\n");
 else if (age >= 60 && age < 100)
  printf("老年\n");
 else    //最后这个else也可不写
  printf("老不死\n");
 return 0;
}
悬空else
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匹配,而不是跟哪个if对齐就跟哪个if匹配
因此要重视代码的书写风格,对齐方式,正确书写,以免阅读出错,易于阅读!!

代码分析

在这里插入图片描述

if语句书写形式的对比

关于写代码的风格

//num=5的写法
 int num = 1;
 if (num = 5)//如果我们不小心少写一个等于号,就变成了赋值操作,此时代码也能正常运行,这种写代码风格,不易发现错误
 {
  printf("hehe\n");//此时打印结果为:hehe
 }
 return 0;
}

//5=num的写法

int mian()
{
 int num = 1;
 if (5=num)//如果我们不小心少写一个等于号,就变成了赋值操作,此时代码会给出错误提示,这种写代码风格,易于发现错误,建议采用!!
 {
  printf("hehe\n");//此时打印会报错,因此可以发现错误
 }
 return 0;
}

练习:判断一个数是不是奇数
奇数就是除2余1的数字

int main()
{
 int num = 15;
 if (num % 2 == 1)
  printf("奇数\n");
 return 0;
}

练习:输出1-100之间的奇数
方式一:

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

方式二:

int main()
{
 for (int i = 1; i <= 100; i += 2)
 {
  printf("%d ", i);
 }
  return 0;
}
switch语句 (分支语句)
语法格式:

switch(整型表达式)
{
语句项;
}

语句项是什么呢?
它是一些case语句
如:

case 整型常量表达式:    //case后必须是整型常量表达式
     语句;

下面来一个例子

int main()
{
 int day = 0;
 scanf("%d", &day);//把输入的值放到day里面去
 switch (day)//switch中的day是几就从case几里面进去(入口),
 {
 case 1:    //case决定入口
  printf("星期一\n");
  break; //决定出口,只要执行break的话就会跳出case,直接走到最后
 case 2:
  printf("星期二\n");
  break;
  case 3:
  printf("星期三\n");
         //不执行break 程序就不会跳出,后面的case也都会执行
                 //不执行break 程序就不会跳出,后面的case也都会执行
 case 4:
  printf("星期四\n");
 case 5:
  printf("星期五\n");
  
 case 6:
  printf("星期六\n");
   case 7:
  printf("星期天\n");
 }
  return 0;
}

下面再来一个例子,并且输出要求是
1-5工作日
6-7休息日

int main()
{
 int day = 0;
 scanf("%d", &day);//把输入的值放到day里面去
 switch (day)//switch中的day是几就从case几里面进去(入口),
 {
 case 1:  
 case 2:
 case 3:
 case 4:
 case 5:
  printf("工作日\n");//此时前面不加break才能满足要求,因此case后面的break并不是必须加的而是看需不需要
  break;
 case 6:
 case 7:
  printf("休息日\n");
  break;//最后一个break可加可不加,但最好加上。
 default :  //default写在前面后面都可以,它是处理异常的
  printf("输入错误\n");
  break;
 }
 return 0;
}
switch语句也可嵌套
int main()
{
 int n = 1;
 int m = 2;
 switch (n)//n此时是1,因此需要从case1进去
 {
 case 1:m++;//3
 case 2:n++;//2
 case 3:
  switch (n)//n此时是2,因此需要从case2进去
  {//switch允许嵌套使用
  case 1:
    n++;
   case 2:m++; n++;//4,3
    break;//此时的break跳出的是嵌套的switch语句
  }
 case 4:
  m++;//5
  break;
 default:
  break;
 }
 printf("m=%d,n=%d\n", m, n);//打印结果:m=5,n=3
 return 0;
}
循环
while循环
while 语法结构
while(表达式)        //表达式结果如果为真,循环语句就会被执行,否则循环停止
     循环语句;
举例理解语法
int main()
{
 while (1)
  printf("hehe\n");//打印结果;hehe死循环
 return 0;
}

打印1-10的数

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

while循环里面也会有break跳出循环

break的用法
int main()
{
 int i = 1;
 while (i <= 10)
 {
  if (i == 5)
   break;//如果i=5,跳出循环
  printf("%d ", i);
  i++;
 }
 return 0;
 //总结:在while循环中,break用于永久的终止循环
}
continue的用法
int main()
{
 int i = 1;
 while (i <= 10)
 {
  if (i == 5)
   continue;
  //总结continue作用是跳过本次循环continue后面的代码,
  //直接去判断部分,看是否进行下一次循环,因为i++在后面,所以就造成了死循环
  printf("%d ", i);//打印结果:1 2 3 4后面死循环
  i++;
 }
 return 0;
}
while循环流程图含break和continue

在这里插入图片描述

疑问
1.什么时候用break?
当某个条件发生的时候,循环要终止,就用break
2.什么时候用continue?
当某个条件发生的时候,这一次continue不执行了,但还要继续下一次判断时,因为整个循环还没有结束时用continue

分析下面两个代码

代码1

#include<stdio.h>
int main()
{
 int ch = 0;
 while ((ch = getchar()) != EOF)//getchar读取一个字符放到ch中,如果它不等于EOF(即不是遇到错误了),
 //那就正常读取一个字符,并把这个字符打印到屏幕上
 {
  //getchar:是获取一个字符的意思
  //EOF//是定义的一个符号,值是-1.它的全称是end of file(文件结束标志)
  putchar(ch);//putchar是输出一个字符到屏幕上。它是getchar对应的输出函数
  //它等于:printf("%c\n",ch);
 }
 return 0;
}

这样的代码有什么意义呢?
1.不断地在屏幕上读取一个字符
2.键盘上按ctrl+z:getchar就读取结束,相当于getchar读到了一个EOF
3.getchar和键盘之间有一个缓冲区,当缓冲区是空时,getchar等待,当输入一个字符并点击回车时,这时getchar实际读到的是一个字符和\n

getchar应用场景

#include<stdio.h>
int main()
{
 char password[20] = { 0 };
 printf("请输入密码:>");
 scanf("%s", password);//password是一个数组,数组的数组名本身就是一个地址,因此不用写&符号
 printf("请确认密码(Y/N):>");//如果输入Y,输出确认成功,否则输出确认失败
 int ch=getchar();//使用getchar获取要输入的字符
 if (ch == 'Y')
 {
  printf("确认成功\n");//打印结果:如下图
 }
 else
 {
  printf("确认失败\n");
 }
    return 0;
}

上面代码打印结果:

在这里插入图片描述

打印结果出错?!!!
为什么呢?
不管是getchar还是scanf他们都是输入函数,这些输入函数是从哪里获取相关信息的呢?
是从键盘上拿到数据吗?
当然不是
答:
它要去从输入函数和键盘之间的缓冲区里面拿数据,如果发现缓冲区里面没有数据,它就会等待从键盘里输入信息到缓冲区里面去,如果输入函数发现缓冲区里面有东西
了,它就会拿走;
同时回车会触发scanf去读内容,此时读到的内容是123456;
接下来就是执行“请确认密码”这一行,正常情况下,getchar会等待输入一个字符(Y/N),但此时却没有等待,因为getchar发现缓冲区里面还有一个\n,所以就没有等待直接拿走了\n,并将\n放到了ch里面去了,此时ch就不等于Y了,因此就执行了else,在这个过程中并没有等待让我们输入Y或N,因此没有得到我们想要的输出内容。
那么如何解决这个问题呢?
答:
只要把缓冲区里面的\n清除掉即可(清楚之后getchar就会等待输入一个字符了)。
解决方式:
在getchar前面再写一个getchar让它先把\n处理掉,因为此时的这个getchar读取字符后不用了,所以就无须再设置变量进行存储了,这时第二个getchar就等待输入,就能执行成功了!

代码如下

#include<stdio.h>
int main()
{
 char password[20] = { 0 };
 printf("请输入密码:>");
 scanf("%s", password);//password是一个数组,数组的数组名本身就是一个地址,因此不用写&符号
 printf("请确认密码(Y/N):>");//如果输入Y,输出确认成功,否则输出确认失败
 getchar();//清理缓冲区,处理'\n'
 int ch = getchar();//使用getchar获取要输入的字符
 if (ch == 'Y')
 {
  printf("确认成功\n");//
 }
 else
 {
  printf("确认失败\n");
 }
 return 0;
}

运行结果
在这里插入图片描述

可是这时又出现了一个问题
但是如果我们输入的是123456 abcdef\n呢?此时又会出现什么结果呢?
代码及运行结果如下:
在这里插入图片描述

这又是什么原因呢?
答:scanf只读缓冲区里面的123456,剩余的
空格abcdef\n还在缓冲区里,但是一个getchar只能处理一个字符,想要处理多个字符就需要使用多个getchar,也就用到了循环,一直循环到读到\n停下来。

解决方式如下面代码:

int main()
{
 char password[20] = { 0 };
 printf("请输入密码:>");
 scanf("%s", password);//password是一个数组,数组的数组名本身就是一个地址,因此不用写&符号
 printf("请确认密码(Y/N):>");//如果输入Y,输出确认成功,否则输出确认失败
 
 //清理缓冲区中的多个字符
 int tmp = 0;//定义临时变量tmp
 while ((tmp = getchar() != '\n'))//读取一个字符放到tmp里,如果读的字符不等于\n
 {
  ;//它是一条空语句,什么都不执行,目的是将读到的字符扔掉,继续循环直到读到\n,跳出循环
 }
 int ch = getchar();//使用getchar获取要输入的字符
 if (ch == 'Y')
 {
  printf("确认成功\n");//打印结果:截图
 }
 else
 {
  printf("确认失败\n");
 }

疑问:getchar读取的是一个字符,为什么用整型变量来存的?
答:
1.getchar读取的是一个字符,而字符本质上是以ASCII码值的形式存储,ASCII码值是整型,所以可以写成int,从MSDN中也可查出它的返回值是int
2.getchar读取的时候不一定返回的就是ASCII码值,它也可能会返回EOF值,而EOF本质上是一个-1, -1不是ASCII值而是一个整数,因此返回类型是int

代码2
这个代码的目的是只打印数字字符

int main()
{
 int ch = 0;
 while ((ch = getchar() != EOF))
 {
  if (ch<'0' || ch>'9')//ASCII码表上只有0-9是数字字符,其他都是非数字字符
   continue;//如果不是数字字符,就执行continue,continue就会跳过本次循环后面的代码,不打印,继续读;
  //如果是数字字符,就没有进入if语句中的continue,就会打印
  putchar(ch);//打印结果:如下图
 }
 return 0;
}

在这里插入图片描述

ASCII表

最后:附一张ASCII表
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值