C语言分支与循环语句

  C语言之所以被称为结构化的程序设计语言,其原因就是因为C语言能够支持顺序结构,选择结构(分支结构),循环结构这三种结构,而日常生活中的几乎所有问题都是由这三种结构构成的,所以生活中遇到的几乎所有的问题,都可以通过C语言编写代码来解决,所以学会分支与循环语句就显得十分重要。

一  分支结构

  分支结构,顾名思义,就是分出多条路线,然后选择一条路线去执行,就是分支结构,就比如你去公司上班,一共有A和B两条路可以走,你可以选择走A路线去上班,同时,B路线也就不走了,这就是分支结构。而在C语言中,分支结构可以通过if语句和switch语句来实现。

1 if语句

  if语句是C语言中使用最多的一中分支语句,其语法是:

if (表达式)
   语句

表达式为真,则执行下面的语句,如果为假,则不执行下面的语句,而在C语言中0也表示假,非0表示真,所以当表达式结果为0是语句也不执行,结果不是0时,语句则会执行

例如:

//输入一个整数,判断是否为偶数

#include<stdio.h>

int main()
{
  int num = 0;
  scanf("%d", &num);
  
  if (num % 2 == 0)
  {
    printf("%d是偶数\n",num);
  }
  
  return 0;
}  
  

输入6,结果为“6是偶数”;输入5,则什么都没有输出。

 2 else语句

if语句一般只包含一种情况,那么如果有多种情况的话,就需要if...else....语句了,其语法是:

if (表达式)
    语句1
else
    语句2
    

 如果表达式为真,则执行语句1,否则,就执行语句2。

例如:

//输入一个数,判断一个数是奇数还是偶数

#include<stdio.h>

int main()
{
  int num = 0;
  scanf("%d",&num);
  
  if (num % 2 == 0)
    printf("%d是偶数\n",num);
  else
    printf("%d是奇数\n",num);
 
  return 0;
}

输入5,输出“5是奇数”;输入6,输出“6是偶数”。

3 if语句或else语句中包含多条语句

  如果是下面一段代码,会输出什么呢?

#include<stdio.h>

int main()
{
  int num = 6;
  
  if (num % 2 == 0)
    printf("Hello World ");
    printf("Hello C");

  return 0;
}
   

实际上其输出的是“Hello World Hello C”,这是因为在C语言中ifelse语句默认只控制一条语句,那么该如何控制多条语句呢?只需要把多条代码放到{ }中即可让if或者else语句控制多条语句了。

{ }叫做代码块,也叫做复合语句,使用{ }会使写的代码逻辑看起来更加清晰,可读性更强,所以在代码中要使用必要的一些{ }来增强代码的可读性。 

4 if语句的嵌套

    有时候呢,分支语句并不只有两种情况,可能会有多种情况,这时候就需要if语句嵌套使用来完成多种情况的实现。比如:

//大于0就输出正数,0就输出零,小于0就输出负数
int main()
{
  int a = 0;
  
  if (a == 0)
    printf("零\n");
  else
  {
    if (a > 0)
      printf("正数\n");
    else
      printf("负数\n");
  }

  return 0;
}

  其实,在if语句的嵌套结构中,else后面的大括号在语法上是支持省略的,比如:

//大于0就输出正数,0就输出零,小于0就输出负数
int main()
{
  int a = 0;
  
  if (a == 0)
    printf("零\n");
  else if (a > 0)
    printf("正数\n");
  else
    printf("负数\n");

  return 0;
}

所以平常所见的else if语句其实是if语句的嵌套结构。

5 悬空else

  请看下面代码会输出什么

int main()
{
  int a = 0;
  int b = 1;
  
  if (a)
    if (b)
      printf("Hello World!\n");
  else
    printf("Hello C!\n");
  
  return 0;
}

看对齐方式应该是输出Hello C!,实际上呢,什么都没有输出,其原因就是else总是与它最近的if语句相匹配,所以示例代码中else是与它上一句的if语句相匹配的,故什么都没有输出。

6 switch 语句

  C语言中还支持一种分支语句叫做switch语句,其中包含case语句,default语句与break语句,swtich语句是else...if语句的一种替代形式,是代码可读性更强,逻辑更加清晰。

其语法形式是:

switch(expression)
{
case value1:
  statement
case value2:
  statement
default:
  statement
}

  其中,expression是整形表达式,value1与value2是expression可能出现的各种值的情况,default是除了value1和value2之外的情况所执行的情况,值得注意的是,case后面的值必须是常量表达式,不能是变量,也不能是定义的整型变量,而且case与后面的常量表达式之间必须有空格

  那下面这个代码的输出结果是啥呢?

#include<stdio.h>

int main()
{
  int a = 3;
  
  switch(a % 3)
  {
  case 0:
    printf("余数是0 ");
  case 1:
    printf("余数是1 ");
  case 2:
    printf("余数是2 ");
  }
  
  return 0;
}

实际上,这个代码的输出结果是“余数是0 余数是1 余数是2 ”,那么为什么会输出这个呢?其实,case是相当于分支的入口,直到swich分支结构的最后一行,整个switch分支结构才结束,那么如果要提前结束switch分支结构要怎么办呢?这时候只要在每一个case语句后面加一个break语句,就可以提前结束switch分支结构了,如上面那个代码:

#include<stdio.h>

int main()
{
  int a = 3;
  
  switch(a % 3)
  {
  case 0:
    printf("余数是0 ");
    break;
  case 1:
    printf("余数是1 ");
    break;
  case 2:
    printf("余数是2 ");
    break;
  }
  
  return 0;
}

这样之后,就只会输出“余数是0 ”了。

 所以一般为了保证switch分支结构的正确性,要在case语句后面加上break语句,但要注意的是,break语句是需要但不是必要,还要根据实际情况来选择是否加上break语句,而不是盲目的在每一个case语句后都加上break语句,这样可能会导致代码的冗余甚至是错误,如:

//输入一个值,如果是周一到周五输出工作日,如果是周六周日输出休息日
#include<stdio.h>

int main()
{
  int a = 0;

  scanf("%d",&a);

  switch(a)
  {
  case 1:
    printf("工作日\n"); 
    break;
  case 2:
    printf("工作日\n"); 
    break;
  case 3:
    printf("工作日\n"); 
    break;
  case 4:
    printf("工作日\n"); 
    break;
  case 5:
    printf("工作日\n"); 
    break;
  case 6:
    printf("休息日\n"); 
    break;
  case 7:
    printf("休息日\n"); 
    break;
  default:
    printf("输入错误\n");
  return 0;
} 

可以看到,这样写有大量代码重复,造成了冗余,可以进行如下优化: 

//输入一个值,如果是周一到周五输出工作日,如果是周六周日输出休息日
#include<stdio.h>

int main()
{
  int a = 0;

  scanf("%d",&a);

  switch(a)
  {
  case 1:
  case 2:
  case 3:
  case 4:
  case 5:
    printf("工作日\n"); 
    break;
  case 6:
  case 7:
    printf("休息日\n"); 
    break;
  default:
    printf("输入错误\n");
  return 0;
} 

    还有一点需要注意的是,default语句并不是必须放在最后,放在前面也是可以的,所以switch分支结构中的语句是没有先后顺序的。

7 条件操作符

  在C语言中,有一个唯一的三目操作符(需要三个操作数),那就是条件操作符,其基本形式是

表达式1 ? 表达式2 : 表达式3

表达式1表示判断的条件,如果为真,执行表达式2,为假执行表达式3,如:

//求出两个数中的较大值

#include<stdio.h>

int main()
{
  int a = 0;
  int b = 0;
  scanf("%d %d", &a, &b);

  int max = a>b ? a : b;
  printf("%d\n",max);
  
  return 0;
}

 

二  循环结构

  上面介绍了分支语句,那循环语句包括哪些呢?循环语句共有三种,分别是while语句,do while语句,以及for语句。

1 while循环

其语法是:

while (表达式)
{
  语句1
  语句2
  ...
}

  while循环特点是,先判断表达式是否为真(或结果非0),若为真,则执行代码块中的语句,若为假(或结果为0),则不执行代码块中的语句 。

如:

//输出10-1 10个数字

#include<stdio.h>

int main()
{
  int n = 10;

  while(n)
  {
    printf("%d ",n);
    n--;
  }

  return 0;
}

2 for循环

其语法是:

for (表达式1;表达式2;表达式3)
{
  语句1;
  语句2;
  ....
}

表达式1是循环变量的初始化,表达式2是循环的条件,表达式3是循环变量的调整部分,在语法上是支持三个表达式都省略的,但是一般不会省略,如果省略,可能会陷入死循环。

  for循环的特点是表达式1只会在第一次循环时执行一次, 接下来的循环就是表达式2,循环语句,和表达式3之间的循环。

  for循环举例:

//输出10-1 10个数字

#include<stdio.h>

int main()
{
  int i = 0;
  
  for(i = 10; i ;i--)
  {
    printf("%d ",i);
  }

  return 0;
}

3 do while循环 

其语法是:

do
{
  语句1
  语句2
  ....
}while(表达式);

  do while循环的特点是,不管表达式判断是否为真,其循环语句至少会被执行一次。

do while循环举例:

//输出10-1 10个数字

#include<stdio.h>

int main()
{
  int i = 10;
  
  do
  {
    printf("%d ",i);
    i--;
  }while(i);
  
  return 0;
}

4 循环结构中的break语句以及continue语句

  循环语句在使用时,有时需要提前结束循环或者跳过本次循环,那这时候就要使用break语句来跳出循环,或者使用continue语句来结束本次循环。

  不管循环是否执行完,使用break语句都会跳出循环,接着执行循环下面的语句;而使用continue语句会​跳过本次循环中continue后面的代码,进行下一次循环的判断。

  break与continue语句举例:

//输出1 2 3 4 6 7

#include<stdio.h>

int main()
{
  int i = 0;

  for (i = 1;i <= 10;i++)
  {
    if (5 == i)
      continue;
    if (8 == i)
      break;
    printf("%d ",i);
  }

  return 0;
}

当 i 等于5的时候,加上continue语句会跳过本次循环后面的代码,所以不会输出5,当 i 等于8的时候,加上break语句会跳出循环,所以8 9 10就不会输出了。

5 循环语句使用时的注意事项

  在使用循环语句时,有那么两个注意事项:

  1  一般要为循环添加一个循环变量,而且要在循环中进行循环变量的调整,否则可能会陷入死循环。

  2 在使用break和continue语句时,要仔细考虑使用时机,否则可能会陷入死循环。

如:

#include<stdio.h>

int main()
{
  int i = 0;
  
  while(i <= 10)
  {
    if (5 == i)
      continue;

    printf("%d ",i);
    i++;
  }

  return 0;
}

这里当 i 自增到5的时候,由于执行了continue语句,所以后面的 i++ 语句会被跳过,也就跳过了循环变量的调整语句,所以 i 一直等于5,一直小于10,循环会一直进行下去,陷入了死循环。

6 循环嵌套--求素数 

  在循环结构的嵌套中,有一个经典代码,就是求出素数,其代码是:

//输出100-200之间的素数(只能被1和本身整除)
//1 用一个for循环来产生100-200之间的数,但是由于偶数是可以被2整除的,所以偶数都不是素数,那么i
//可以从101开始,每次加2
//2 由于如果一个正数存在其他因子,那么其中一个因子必然会小于等于i的平方根,所以再在第一个for循环
//里面再用一个for循环来产生2-i的平方根之间的数字来试除i,如果能整除,那么i就不是素数


#include<stdio.h>
#include<math.h>

int main()
{
  int i = 0;
 
  for (i = 101;i <= 199;i += 2)
  {
    int j = 0;
    int flag = 1;//假设i是素数
    
    for (j = 2;j <= sqrt(i);j++)
    {
      if (i % j == 0)
         flag = 0;//i不是素数
         break;
    }
    if (1 == flag)
      printf("%d ",i);
  }
  
  return 0;
}

7 goto语句 

  C语言中还提供了一种语句,叫goto语句,可以实现代码之间的跳转,本来break只能跳出一个循环,而使用goto语句可以跳出多个循环,其基本形式是:

  goto 标志
  语句1
  语句2
  ....
标志:
  语句3
  语句4
  ....

标志是你想要执行goto语句是你想要跳转到的标志,比如goto next; goto begin等,执行到goto语句时,就会跳过语句1,语句2的执行,而直接跳转到标志,执行标志下面的语句。

  goto语句虽然可以实现代码的快速跳转,但是如果使用较多的话,会使得代码随意乱跳,打乱执行流程,所以建议尽量不使用goto语句。

三  逻辑操作符

  在if分支结构,while、do while、for循环结构中,他们都会判断表达式的真假来决定循环语句是否执行,而在C语言中真好有那么三个逻辑操作符来实现多条件之间的判断,这三个逻辑操作符分别是&&(逻辑与操作符),||(逻辑或操作符),!(逻辑取反操作符)。

  值得注意的一点是,逻辑操作符如果判断为假,则会返回0,如果判断为真,则会返回1。

1 &&--逻辑与操作符

  && 是并且的意思,其是一个双目操作符(操作符需要两个操作数),其判断逻辑是全真为真,有假则为假(有0为0,双非0为1)。

2  ||--逻辑或操作符 

  ||是或者的意思,其也是一个双目操作符,其判断逻辑是有真则为真,全假则为假(有非0为1,全0为0)。

  逻辑与,逻辑或操作符举例:

//输入一个月份,根据月份进行判断,输出月份相对应季节

#include<stdio.h>

int main()
{
  int m = 0;
  scanf("%d",&m);

  if (m == 12 || (m >=1 && m <= 2))
    printf("冬季\n");
  else if (m <= 5)
    printf("春季\n");
  else if (m <= 8)
    printf("夏季\n");
  else
    printf("秋季\n");
  
  return 0;
}

3 !--逻辑取反操作符

  ! 是取反的意思,即把假变为真,把真变为假(非0为0,0为1)。

4 短路现象

  C语言中逻辑运算符有一个特点,就是逻辑运算符总是从左往右开始计算表达式,如果左边的表达式能够得出整个逻辑运算的结果,那就不再对右边的表达式进行运算,这就称为‘‘短路’’。

即:由于&&操作符如果表达式中其中一个是假(或者结果为0),那么逻辑运算的结果就为假(或为0),所以当从左边开始运算,碰到结果为假(或为0)的表达式,那么右边的表达式是便不再计算;同样地,当 || 操作符从左往右开始计算,当碰到结果为真(或为非0)的表达式,那么右边的表达式便不再计算。

例如:

#include<stdio.h>

int main()
{
  int i = 0;
  int a = 0;
  int b = 0;
  int c = 0;
  int d = 0;
 
  i = ++a && b++ || ++c || d++;

  printf("a=%d b=%d c=%d i=%d d=%d", a, b, c, i, d);

  return 0;
}

输出结果为:1 1 1 1 0

请思考:如果把++a换成a++呢? 

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值